random access files now used to sync visualizer with song (optimization)

This commit is contained in:
Harrison Deng 2017-12-10 01:45:10 -06:00
parent 8023987148
commit 51ce146611
7 changed files with 93 additions and 53 deletions

View File

@ -1,6 +1,12 @@
package zero1hd.rhythmbullet.audio;
import java.io.BufferedInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.nio.channels.Channels;
import java.security.InvalidParameterException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
@ -30,9 +36,9 @@ import javazoom.jl.decoder.OutputBuffer;
public class Mp3Manager implements MusicManager {
private int readWindowSize = 1024;
private int currentReadWindowIndex;
private int readWindowIndex;
private Music playbackMusic;
private int readIndex;
private int playbackIndex;
private int sampleRate;
private long sampleCount;
@ -41,10 +47,11 @@ public class Mp3Manager implements MusicManager {
Bitstream bitstream;
MP3Decoder decoder;
OutputBuffer sampleBuffer;
InputStream inputStream;
private byte[] currentByteSet;
private byte[] workset;
private int indexHead = -1;
private RandomAccessFile raf;
private FileHandle file;
ReentrantLock lock = new ReentrantLock();
@ -71,9 +78,14 @@ public class Mp3Manager implements MusicManager {
lock.unlock();
});
bitstream = new Bitstream(audioFile.read());
decoder = new MP3Decoder();
try {
raf = new RandomAccessFile(audioFile.file(), "r");
bitstream = new Bitstream(inputStream = Channels.newInputStream(raf.getChannel()));
decoder = new MP3Decoder();
} catch (FileNotFoundException e2) {
e2.printStackTrace();
throw new InvalidParameterException("Error with creating RandomAccessFile.");
}
try {
Header header = bitstream.readFrame();
if (header == null) throw new GdxRuntimeException("Empty MP3");
@ -88,15 +100,22 @@ public class Mp3Manager implements MusicManager {
playbackMusic = Gdx.audio.newMusic(audioFile);
}
@Override
public void setReadIndexToPlaybackIndex() {
try {
raf.seek((long) (getPositionInSeconds()*(long)sampleRate));
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void playbackIndexUpdate() {
readIndex = (int) (playbackMusic.getPosition() * sampleRate / readWindowSize);
playbackIndex = (int) (playbackMusic.getPosition() * sampleRate / readWindowSize);
}
@Override
public int getPlaybackIndexPosition() {
return readIndex;
return playbackIndex;
}
@Override
@ -132,7 +151,7 @@ public class Mp3Manager implements MusicManager {
samples[sid] /= Short.MAX_VALUE+1;
}
}
currentReadWindowIndex++;
readWindowIndex++;
return framesRead;
}
@ -185,8 +204,8 @@ public class Mp3Manager implements MusicManager {
}
@Override
public int getCurrentReadWindowIndex() {
return currentReadWindowIndex;
public int getreadWindowIndex() {
return readWindowIndex;
}
@Override
@ -262,7 +281,8 @@ public class Mp3Manager implements MusicManager {
try {
bitstream.close();
bitstream = null;
} catch (BitstreamException e) {
inputStream.close();
} catch (BitstreamException | IOException e) {
e.printStackTrace();
}
}

View File

@ -13,7 +13,7 @@ public interface MusicManager extends Disposable {
public void playbackIndexUpdate();
/**
* Gets the current position in seconds s
* Gets the current position in seconds
* @return the current frame of audio.
*/
public int getPlaybackIndexPosition();
@ -54,7 +54,7 @@ public interface MusicManager extends Disposable {
* The current numerical value of the last window read
* @return
*/
public int getCurrentReadWindowIndex();
public int getreadWindowIndex();
public void pause();
@ -87,4 +87,8 @@ public interface MusicManager extends Disposable {
* @return the song filehandle.
*/
public FileHandle getMusicFile();
/**
*/
public void setReadIndexToPlaybackIndex();
}

View File

@ -1,6 +1,9 @@
package zero1hd.rhythmbullet.audio;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.channels.Channels;
import java.security.InvalidParameterException;
import javax.sound.sampled.AudioFormat;
@ -15,17 +18,20 @@ import zero1hd.rhythmbullet.audio.wavedecoder.WavDecoder;
public class WAVManager implements MusicManager {
private int readWindowSize = 1024;
private AudioFormat format;
private int readIndex;
private int currentReadWindowIndex;
private int playbackIndex;
private int readWindowIndex;
private Music playbackMusic;
WavDecoder decoder;
private FileHandle file;
private String basicSongName;
private RandomAccessFile raf;
public WAVManager(FileHandle file) {
this.file = file;
basicSongName = file.name();
try {
decoder = new WavDecoder(file);
raf = new RandomAccessFile(file.file(), "r");
decoder = new WavDecoder(new BufferedInputStream(Channels.newInputStream(raf.getChannel())));
} catch (InvalidParameterException | IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
@ -36,19 +42,28 @@ public class WAVManager implements MusicManager {
@Override
public void playbackIndexUpdate() {
readIndex = (int) (playbackMusic.getPosition() * decoder.getSampleRate() / readWindowSize);
playbackIndex = (int) (playbackMusic.getPosition() * decoder.getSampleRate() / readWindowSize);
}
@Override
public int getPlaybackIndexPosition() {
return readIndex;
return playbackIndex;
}
@Override
public int getReadWindowSize() {
return readWindowSize;
}
@Override
public void setReadIndexToPlaybackIndex() {
try {
raf.seek((long) (getPositionInSeconds()*(long)getSampleRate()));
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public int readSamples(float[] samples) {
int samplesRead = 0;
@ -59,7 +74,7 @@ public class WAVManager implements MusicManager {
}
if (samplesRead != 0) {
currentReadWindowIndex++;
readWindowIndex++;
}
return samplesRead;
}
@ -87,8 +102,8 @@ public class WAVManager implements MusicManager {
}
@Override
public int getCurrentReadWindowIndex() {
return currentReadWindowIndex;
public int getreadWindowIndex() {
return readWindowIndex;
}
@Override

View File

@ -172,7 +172,7 @@ public class BasicVisualizer extends VisualizerCore {
}
public void flip() {
flip = flip ? false : true;
flip = !flip;
}
public boolean isFlipped() {

View File

@ -17,26 +17,29 @@ public class VisualizerCore implements Disposable {
protected int barCount;
private boolean calc;
private ReentrantLock lock;
private float updateRate;
private float updateTimer;
public VisualizerCore(int width, int height, int x, int y) {
this.height = height;
this.width = width;
this.xPos = x;
this.yPos = y;
updateRate = 1f/30f;
lock = new ReentrantLock();
}
public void calculate() {
if (mm != null) {
mm.playbackIndexUpdate();
lock.lock();
while (calc && mm.isPlaying() && mm.getPlaybackIndexPosition() > mm.getCurrentReadWindowIndex()) {
public void calculate(float delta) {
if (mm != null && calc && mm.isPlaying()) {
updateTimer += delta;
if (updateTimer >= updateRate) {
mm.playbackIndexUpdate();
lock.lock();
mm.setReadIndexToPlaybackIndex();
mm.readSamples(audioPCM);
if (mm.getPlaybackIndexPosition() == mm.getCurrentReadWindowIndex()) {
fft.realForward(audioPCM);
}
fft.realForward(audioPCM);
lock.unlock();
updateTimer = 0;
}
lock.unlock();
}
}
@ -95,4 +98,12 @@ public class VisualizerCore implements Disposable {
public MusicManager getMm() {
return mm;
}
public void setUpdateRate(float updateRate) {
this.updateRate = updateRate;
}
public float getUpdateRate() {
return updateRate;
}
}

View File

@ -1,31 +1,25 @@
package zero1hd.rhythmbullet.audio.wavedecoder;
import java.io.BufferedInputStream;
import java.io.IOException;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.UnsupportedAudioFileException;
import com.badlogic.gdx.files.FileHandle;
public class WavDecoder {
private FileHandle file;
private int channels;
private double sampleRate;
private String fileName;
private byte[] buffer;
private AudioInputStream audioInputStream;
public WavDecoder(FileHandle file) throws IOException {
this.file = file;
public WavDecoder(BufferedInputStream inputStream) throws IOException {
try {
audioInputStream = AudioSystem.getAudioInputStream(file.file());
audioInputStream = AudioSystem.getAudioInputStream(inputStream);
buffer = new byte[audioInputStream.getFormat().getFrameSize()];
channels = audioInputStream.getFormat().getChannels();
sampleRate = audioInputStream.getFormat().getSampleRate();
fileName = file.name();
} catch (UnsupportedAudioFileException e) {
e.printStackTrace();
}
@ -47,14 +41,6 @@ public class WavDecoder {
return audioInputStream.getFrameLength();
}
public String getFileName() {
return fileName;
}
public FileHandle getFile() {
return file;
}
public int readSamples(float[] samples) throws IOException {
int framesRead = 0;
@ -74,6 +60,10 @@ public class WavDecoder {
return framesRead;
}
public AudioInputStream getAudioInputStream() {
return audioInputStream;
}
public void cleanAndClose() {
try {
audioInputStream.close();

View File

@ -40,7 +40,7 @@ public class Visualizer extends Widget implements Disposable {
vis.updatePositionInfo();
vis.setxPos((getWidth() - vis.getActualWidth())/2f);
}
vis.calculate();
vis.calculate(delta);
super.act(delta);
}