visualizer now directly grabs data from openal.. slightly less synched for better efficiency?
This commit is contained in:
parent
b6da79adc2
commit
7b8f442f98
@ -64,7 +64,7 @@ public class BasicVisualizer extends VisualizerCore {
|
|||||||
super.render(batch, parentAlpha);
|
super.render(batch, parentAlpha);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void modify(float delta) {
|
public void update(float delta) {
|
||||||
//Averaging bins together
|
//Averaging bins together
|
||||||
for (int i = 0; i < barCount; i++) {
|
for (int i = 0; i < barCount; i++) {
|
||||||
float barHeight = 0;
|
float barHeight = 0;
|
||||||
@ -104,13 +104,13 @@ public class BasicVisualizer extends VisualizerCore {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setMM(MusicManager mm) {
|
public void setMM(MusicManager mm) {
|
||||||
super.setMM(mm);
|
|
||||||
maxAvgHeight = 0;
|
maxAvgHeight = 0;
|
||||||
currentAvg = 0;
|
currentAvg = 0;
|
||||||
float validBins = (5500/((mm.getSampleRate()/2)/((audioPCM.length/2)+1)));
|
float validBins = (5500/((mm.getSampleRate()/2)/((mm.getReadWindowSize()/2)+1)));
|
||||||
Gdx.app.debug("Visualizer", "valid frequency bins " + validBins);
|
Gdx.app.debug("Visualizer", "valid frequency bins " + validBins);
|
||||||
binsPerBar = MathUtils.round((validBins/barCount));
|
binsPerBar = MathUtils.round((validBins/barCount));
|
||||||
barHeights = new float[barCount];
|
barHeights = new float[barCount];
|
||||||
|
super.setMM(mm);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -11,44 +11,36 @@ import zero1hd.rhythmbullet.util.MusicManager;
|
|||||||
public class VisualizerCore implements Disposable {
|
public class VisualizerCore implements Disposable {
|
||||||
protected MusicManager mm;
|
protected MusicManager mm;
|
||||||
private FloatFFT_1D fft;
|
private FloatFFT_1D fft;
|
||||||
float[] audioPCM;
|
|
||||||
protected float width, height;
|
protected float width, height;
|
||||||
protected float xPos, yPos;
|
protected float xPos, yPos;
|
||||||
protected int barCount;
|
protected int barCount;
|
||||||
private boolean calc;
|
private boolean calc;
|
||||||
private ReentrantLock lock;
|
private ReentrantLock lock;
|
||||||
private float updateRate;
|
protected float[] audioPCM;
|
||||||
private float updateTimer;
|
|
||||||
public VisualizerCore(int width, int height, int x, int y) {
|
public VisualizerCore(int width, int height, int x, int y) {
|
||||||
this.height = height;
|
this.height = height;
|
||||||
this.width = width;
|
this.width = width;
|
||||||
this.xPos = x;
|
this.xPos = x;
|
||||||
this.yPos = y;
|
this.yPos = y;
|
||||||
updateRate = 1f/60f;
|
|
||||||
lock = new ReentrantLock();
|
lock = new ReentrantLock();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void calculate(float delta) {
|
public void calculate(float delta) {
|
||||||
if (mm != null && calc && mm.isPlaying()) {
|
if (mm != null && calc && mm.isPlaying()) {
|
||||||
updateTimer += delta;
|
|
||||||
if (updateTimer >= updateRate) {
|
|
||||||
//TODO use current buffer being played
|
|
||||||
lock.lock();
|
lock.lock();
|
||||||
mm.readSamples(audioPCM);
|
|
||||||
fft.realForward(audioPCM);
|
fft.realForward(audioPCM);
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
updateTimer = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setMM(MusicManager mm) {
|
public void setMM(MusicManager mm) {
|
||||||
lock.lock();
|
lock.lock();
|
||||||
if (audioPCM == null || audioPCM.length != mm.getReadWindowSize()) {
|
|
||||||
calc = false;
|
calc = false;
|
||||||
|
if (audioPCM == null || audioPCM.length != mm.getReadWindowSize()) {
|
||||||
|
audioPCM = new float[mm.getReadWindowSize()];
|
||||||
fft = new FloatFFT_1D(mm.getReadWindowSize());
|
fft = new FloatFFT_1D(mm.getReadWindowSize());
|
||||||
}
|
}
|
||||||
audioPCM = new float[mm.getReadWindowSize()];
|
|
||||||
this.mm = mm;
|
this.mm = mm;
|
||||||
calc = true;
|
calc = true;
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
@ -57,7 +49,7 @@ public class VisualizerCore implements Disposable {
|
|||||||
public void render(Batch batch, float parentAlpha) {
|
public void render(Batch batch, float parentAlpha) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void modify(float delta) {
|
public void update(float delta) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -98,11 +90,7 @@ public class VisualizerCore implements Disposable {
|
|||||||
return mm;
|
return mm;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setUpdateRate(float updateRate) {
|
public float[] getAudioPCM() {
|
||||||
this.updateRate = updateRate;
|
return audioPCM;
|
||||||
}
|
|
||||||
|
|
||||||
public float getUpdateRate() {
|
|
||||||
return updateRate;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
|
|
||||||
package zero1hd.rhythmbullet.util;
|
package zero1hd.rhythmbullet.util;
|
||||||
|
|
||||||
|
import com.badlogic.gdx.audio.Music;
|
||||||
import com.badlogic.gdx.audio.Music.OnCompletionListener;
|
import com.badlogic.gdx.audio.Music.OnCompletionListener;
|
||||||
import com.badlogic.gdx.files.FileHandle;
|
import com.badlogic.gdx.files.FileHandle;
|
||||||
import com.badlogic.gdx.utils.Disposable;
|
import com.badlogic.gdx.utils.Disposable;
|
||||||
@ -64,6 +65,10 @@ public interface MusicManager extends Disposable {
|
|||||||
|
|
||||||
public void setVolume(float percent);
|
public void setVolume(float percent);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the amount of channels this audio file has.
|
||||||
|
*/
|
||||||
|
public int getChannelCount();
|
||||||
/**
|
/**
|
||||||
* If the the properties of the song are done loading
|
* If the the properties of the song are done loading
|
||||||
* @return whether its done loading
|
* @return whether its done loading
|
||||||
@ -86,4 +91,6 @@ public interface MusicManager extends Disposable {
|
|||||||
* @return the amount of windows that have been read.
|
* @return the amount of windows that have been read.
|
||||||
*/
|
*/
|
||||||
public int framesRead();
|
public int framesRead();
|
||||||
|
|
||||||
|
public Music getMusic();
|
||||||
}
|
}
|
||||||
|
@ -265,4 +265,14 @@ public class Mp3Manager implements MusicManager {
|
|||||||
public int framesRead() {
|
public int framesRead() {
|
||||||
return readIndex;
|
return readIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getChannelCount() {
|
||||||
|
return channels;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Music getMusic() {
|
||||||
|
return playbackMusic;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -141,4 +141,14 @@ public class WAVManager implements MusicManager {
|
|||||||
public int framesRead() {
|
public int framesRead() {
|
||||||
return readIndex;
|
return readIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getChannelCount() {
|
||||||
|
return d.getChannels();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Music getMusic() {
|
||||||
|
return music;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,21 @@
|
|||||||
package zero1hd.rhythmbullet.desktop.graphics.ui.components;
|
package zero1hd.rhythmbullet.desktop.graphics.ui.components;
|
||||||
|
|
||||||
|
import static org.lwjgl.openal.AL10.*;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.ShortBuffer;
|
||||||
|
|
||||||
|
import org.lwjgl.openal.AL11;
|
||||||
|
|
||||||
import com.badlogic.gdx.Gdx;
|
import com.badlogic.gdx.Gdx;
|
||||||
|
import com.badlogic.gdx.backends.lwjgl.audio.OpenALMusic;
|
||||||
import com.badlogic.gdx.graphics.Color;
|
import com.badlogic.gdx.graphics.Color;
|
||||||
import com.badlogic.gdx.graphics.g2d.Batch;
|
import com.badlogic.gdx.graphics.g2d.Batch;
|
||||||
import com.badlogic.gdx.scenes.scene2d.ui.Widget;
|
import com.badlogic.gdx.scenes.scene2d.ui.Widget;
|
||||||
import com.badlogic.gdx.utils.Disposable;
|
import com.badlogic.gdx.utils.Disposable;
|
||||||
|
import com.badlogic.gdx.utils.reflect.ClassReflection;
|
||||||
|
import com.badlogic.gdx.utils.reflect.Field;
|
||||||
|
import com.badlogic.gdx.utils.reflect.ReflectionException;
|
||||||
|
|
||||||
import zero1hd.rhythmbullet.audio.visualizer.BasicVisualizer;
|
import zero1hd.rhythmbullet.audio.visualizer.BasicVisualizer;
|
||||||
import zero1hd.rhythmbullet.util.MusicManager;
|
import zero1hd.rhythmbullet.util.MusicManager;
|
||||||
@ -14,8 +25,20 @@ public class Visualizer extends Widget implements Disposable {
|
|||||||
private boolean updatePositioning = true;
|
private boolean updatePositioning = true;
|
||||||
private boolean mmSet;
|
private boolean mmSet;
|
||||||
private MusicManager mm;
|
private MusicManager mm;
|
||||||
|
private ShortBuffer buffer;
|
||||||
|
private int sourceID;
|
||||||
public Visualizer() {
|
public Visualizer() {
|
||||||
vis = new BasicVisualizer();
|
vis = new BasicVisualizer();
|
||||||
|
|
||||||
|
try {
|
||||||
|
Field tempBufferField = ClassReflection.getDeclaredField(OpenALMusic.class, "tempBuffer");
|
||||||
|
tempBufferField.setAccessible(true);
|
||||||
|
buffer = ((ByteBuffer) tempBufferField.get(null)).asShortBuffer();
|
||||||
|
} catch (IllegalArgumentException | SecurityException | ReflectionException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
Gdx.app.debug("Visualizer reflection", "Failed attempt at retrieving tempBuffer field.");
|
||||||
|
Gdx.app.exit();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -34,18 +57,47 @@ public class Visualizer extends Widget implements Disposable {
|
|||||||
mmSet = true;
|
mmSet = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
vis.modify(delta);
|
vis.update(delta);
|
||||||
updateVisualizerProperties();
|
updateVisualizerProperties();
|
||||||
if (updatePositioning) {
|
if (updatePositioning) {
|
||||||
vis.updatePositionInfo();
|
vis.updatePositionInfo();
|
||||||
vis.setxPos((getWidth() - vis.getActualWidth())/2f);
|
vis.setxPos((getWidth() - vis.getActualWidth())/2f);
|
||||||
}
|
}
|
||||||
|
if (mmSet) {
|
||||||
|
setupPCMData();
|
||||||
|
}
|
||||||
vis.calculate(delta);
|
vis.calculate(delta);
|
||||||
super.act(delta);
|
super.act(delta);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setupPCMData() {
|
||||||
|
short chanVal;
|
||||||
|
|
||||||
|
int pos = (int) ((alGetSourcef(sourceID, AL11.AL_SAMPLE_OFFSET)-4));
|
||||||
|
try {
|
||||||
|
buffer.position((int) Math.max(0, pos));
|
||||||
|
} catch (IllegalArgumentException outOfBounds) {
|
||||||
|
System.out.println(outOfBounds);
|
||||||
|
}
|
||||||
|
for (int sid = 0; sid < vis.getAudioPCM().length && sid < buffer.remaining(); sid++) {
|
||||||
|
for (int channel = 0; channel < mm.getChannelCount(); channel ++) {
|
||||||
|
if (vis.getAudioPCM()[sid] < (chanVal = buffer.get())) {
|
||||||
|
vis.getAudioPCM()[sid] = chanVal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
vis.getAudioPCM()[sid] /= Short.MAX_VALUE+1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void setMM(MusicManager mm) {
|
public void setMM(MusicManager mm) {
|
||||||
|
try {
|
||||||
|
Field sourceIDField = ClassReflection.getDeclaredField(OpenALMusic.class, "sourceID");
|
||||||
|
sourceIDField.setAccessible(true);
|
||||||
|
sourceID = (int) sourceIDField.get(mm.getMusic());
|
||||||
|
} catch (ReflectionException e) {
|
||||||
|
// TODO Auto-generated catch block
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
this.mm = mm;
|
this.mm = mm;
|
||||||
mmSet = false;
|
mmSet = false;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user