UNTESTED; basic mp3spi setup done; more efficient way of skipping bytes now; syncing of playback and read implemented
This commit is contained in:
parent
677ada45b6
commit
cebf36dff9
@ -22,8 +22,9 @@ import zero1hd.rhythmbullet.audio.wavedecoder.AudioSampleReader;
|
|||||||
public class Mp3Manager implements MusicManager {
|
public class Mp3Manager implements MusicManager {
|
||||||
private int readWindowSize = 1024;
|
private int readWindowSize = 1024;
|
||||||
private Music music;
|
private Music music;
|
||||||
private int playbackIndex;
|
private int playbackIndex, readIndex;
|
||||||
private FileHandle fileHandle;
|
private FileHandle fileHandle;
|
||||||
|
AudioInputStream in;
|
||||||
private AudioInputStream ais;
|
private AudioInputStream ais;
|
||||||
private AudioFormat af;
|
private AudioFormat af;
|
||||||
private AudioSampleReader d;
|
private AudioSampleReader d;
|
||||||
@ -32,7 +33,6 @@ public class Mp3Manager implements MusicManager {
|
|||||||
public Mp3Manager(FileHandle file) {
|
public Mp3Manager(FileHandle file) {
|
||||||
this.fileHandle = file;
|
this.fileHandle = file;
|
||||||
try {
|
try {
|
||||||
AudioInputStream in;
|
|
||||||
in = AudioSystem.getAudioInputStream(file.file());
|
in = AudioSystem.getAudioInputStream(file.file());
|
||||||
AudioFormat baseFormat = in.getFormat();
|
AudioFormat baseFormat = in.getFormat();
|
||||||
properties = ((TAudioFormat)baseFormat).properties();
|
properties = ((TAudioFormat)baseFormat).properties();
|
||||||
@ -43,7 +43,6 @@ public class Mp3Manager implements MusicManager {
|
|||||||
baseFormat.getChannels()*2,
|
baseFormat.getChannels()*2,
|
||||||
baseFormat.getSampleRate(), false);
|
baseFormat.getSampleRate(), false);
|
||||||
ais = AudioSystem.getAudioInputStream(baseFormat, in);
|
ais = AudioSystem.getAudioInputStream(baseFormat, in);
|
||||||
in.close();
|
|
||||||
d = new AudioSampleReader(ais);
|
d = new AudioSampleReader(ais);
|
||||||
music = Gdx.audio.newMusic(file);
|
music = Gdx.audio.newMusic(file);
|
||||||
} catch (UnsupportedAudioFileException | IOException e) {
|
} catch (UnsupportedAudioFileException | IOException e) {
|
||||||
@ -56,6 +55,7 @@ public class Mp3Manager implements MusicManager {
|
|||||||
music.dispose();
|
music.dispose();
|
||||||
try {
|
try {
|
||||||
ais.close();
|
ais.close();
|
||||||
|
in.close();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
@ -79,6 +79,7 @@ public class Mp3Manager implements MusicManager {
|
|||||||
@Override
|
@Override
|
||||||
public int readSamples(float[] samples) {
|
public int readSamples(float[] samples) {
|
||||||
try {
|
try {
|
||||||
|
readIndex++;
|
||||||
return d.readSamples(samples);
|
return d.readSamples(samples);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
@ -152,22 +153,10 @@ public class Mp3Manager implements MusicManager {
|
|||||||
return fileHandle;
|
return fileHandle;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void seek(long position) {
|
public void seek(long position) {
|
||||||
long totalSkipped = 0;
|
|
||||||
long skipped = 0;
|
|
||||||
closeStream();
|
closeStream();
|
||||||
reInitStream();
|
reInitStream();
|
||||||
while (totalSkipped < position) {
|
skip(position);
|
||||||
try {
|
|
||||||
skipped = ais.skip(position-totalSkipped);
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (skipped == 0) break;
|
|
||||||
totalSkipped += skipped;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void closeStream() {
|
private void closeStream() {
|
||||||
@ -194,4 +183,32 @@ public class Mp3Manager implements MusicManager {
|
|||||||
public void synchronize() {
|
public void synchronize() {
|
||||||
seek(MathUtils.round(((Integer) properties.get("audio.length.bytes")).intValue() * (getPositionInSeconds()/getDuration())));
|
seek(MathUtils.round(((Integer) properties.get("audio.length.bytes")).intValue() * (getPositionInSeconds()/getDuration())));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getReadIndex() {
|
||||||
|
return readIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void skip(long bytes) {
|
||||||
|
long totalSkipped = 0;
|
||||||
|
long skipped = 0;
|
||||||
|
|
||||||
|
while (totalSkipped < bytes) {
|
||||||
|
try {
|
||||||
|
skipped = ais.skip(bytes-totalSkipped);
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (skipped == 0) break;
|
||||||
|
totalSkipped += skipped;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void skipReadWindow() {
|
||||||
|
skip(readWindowSize*af.getFrameSize());
|
||||||
|
readIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -82,14 +82,15 @@ public interface MusicManager extends Disposable {
|
|||||||
*/
|
*/
|
||||||
public FileHandle getMusicFile();
|
public FileHandle getMusicFile();
|
||||||
|
|
||||||
/**
|
|
||||||
* sets the reading position to the given position;
|
|
||||||
* @param position the byte to skip to.
|
|
||||||
*/
|
|
||||||
public void seek(long position);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Synchronizes the playback and read threads
|
* Synchronizes the playback and read threads
|
||||||
*/
|
*/
|
||||||
public void synchronize();
|
public void synchronize();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the window that the current read index is on
|
||||||
|
*/
|
||||||
|
public int getReadIndex();
|
||||||
|
|
||||||
|
public void skipReadWindow();
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ import zero1hd.rhythmbullet.audio.wavedecoder.AudioSampleReader;
|
|||||||
|
|
||||||
public class WAVManager implements MusicManager {
|
public class WAVManager implements MusicManager {
|
||||||
private int readWindowSize = 1024;
|
private int readWindowSize = 1024;
|
||||||
private int playbackIndex;
|
private int playbackIndex, readIndex;
|
||||||
private Music music;
|
private Music music;
|
||||||
private FileHandle fileHandle;
|
private FileHandle fileHandle;
|
||||||
private AudioInputStream ais;
|
private AudioInputStream ais;
|
||||||
@ -64,6 +64,7 @@ public class WAVManager implements MusicManager {
|
|||||||
@Override
|
@Override
|
||||||
public int readSamples(float[] samples) {
|
public int readSamples(float[] samples) {
|
||||||
try {
|
try {
|
||||||
|
readIndex++;
|
||||||
return d.readSamples(samples);
|
return d.readSamples(samples);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
@ -136,22 +137,9 @@ public class WAVManager implements MusicManager {
|
|||||||
return fileHandle;
|
return fileHandle;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void seek(long position) {
|
public void seek(long position) {
|
||||||
long totalSkipped = 0;
|
|
||||||
long skipped = 0;
|
|
||||||
|
|
||||||
restartStream();
|
restartStream();
|
||||||
while (totalSkipped < position) {
|
skip(position);
|
||||||
try {
|
|
||||||
skipped = ais.skip(position-totalSkipped);
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (skipped == 0) break;
|
|
||||||
totalSkipped += skipped;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void restartStream() {
|
private void restartStream() {
|
||||||
@ -162,9 +150,7 @@ public class WAVManager implements MusicManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
AudioInputStream in = AudioSystem.getAudioInputStream(fileHandle.file());
|
ais = AudioSystem.getAudioInputStream(fileHandle.file());
|
||||||
ais = AudioSystem.getAudioInputStream(af, in);
|
|
||||||
in.close();
|
|
||||||
} catch (UnsupportedAudioFileException | IOException e) {
|
} catch (UnsupportedAudioFileException | IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
@ -173,5 +159,32 @@ public class WAVManager implements MusicManager {
|
|||||||
@Override
|
@Override
|
||||||
public void synchronize() {
|
public void synchronize() {
|
||||||
seek(MathUtils.round(getPositionInSeconds()*getSampleRate()));
|
seek(MathUtils.round(getPositionInSeconds()*getSampleRate()));
|
||||||
|
readIndex = playbackIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getReadIndex() {
|
||||||
|
return readIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void skip(long bytes) {
|
||||||
|
long totalSkipped = 0;
|
||||||
|
long skipped = 0;
|
||||||
|
while (totalSkipped < bytes) {
|
||||||
|
try {
|
||||||
|
skipped = ais.skip(bytes-totalSkipped);
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (skipped == 0) break;
|
||||||
|
totalSkipped += skipped;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void skipReadWindow() {
|
||||||
|
skip(af.getFrameSize()*readWindowSize);
|
||||||
|
readIndex++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,8 +33,10 @@ public class VisualizerCore implements Disposable {
|
|||||||
updateTimer += delta;
|
updateTimer += delta;
|
||||||
if (updateTimer >= updateRate) {
|
if (updateTimer >= updateRate) {
|
||||||
mm.playbackIndexUpdate();
|
mm.playbackIndexUpdate();
|
||||||
|
while (mm.getPlaybackIndexPosition() > mm.getReadIndex()) {
|
||||||
|
mm.skipReadWindow();
|
||||||
|
}
|
||||||
lock.lock();
|
lock.lock();
|
||||||
mm.setReadIndexToPlaybackIndex();
|
|
||||||
mm.readSamples(audioPCM);
|
mm.readSamples(audioPCM);
|
||||||
fft.realForward(audioPCM);
|
fft.realForward(audioPCM);
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
|
@ -8,8 +8,8 @@ public class AudioSampleReader {
|
|||||||
private int channels;
|
private int channels;
|
||||||
private double sampleRate;
|
private double sampleRate;
|
||||||
private byte[] buffer;
|
private byte[] buffer;
|
||||||
private int sampleSize;
|
|
||||||
private AudioInputStream audioInputStream;
|
private AudioInputStream audioInputStream;
|
||||||
|
private boolean mergeChannels;
|
||||||
|
|
||||||
public AudioSampleReader(AudioInputStream ais) throws IOException {
|
public AudioSampleReader(AudioInputStream ais) throws IOException {
|
||||||
audioInputStream = ais;
|
audioInputStream = ais;
|
||||||
@ -17,7 +17,6 @@ public class AudioSampleReader {
|
|||||||
|
|
||||||
channels = audioInputStream.getFormat().getChannels();
|
channels = audioInputStream.getFormat().getChannels();
|
||||||
sampleRate = audioInputStream.getFormat().getSampleRate();
|
sampleRate = audioInputStream.getFormat().getSampleRate();
|
||||||
sampleSize = audioInputStream.getFormat().getSampleSizeInBits();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getChannels() {
|
public int getChannels() {
|
||||||
@ -28,30 +27,51 @@ public class AudioSampleReader {
|
|||||||
return sampleRate;
|
return sampleRate;
|
||||||
}
|
}
|
||||||
|
|
||||||
public float getDurationInSeconds() {
|
|
||||||
return audioInputStream.getFrameLength()/audioInputStream.getFormat().getFrameRate();
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getFrameLength() {
|
public long getFrameLength() {
|
||||||
return audioInputStream.getFrameLength();
|
return audioInputStream.getFrameLength();
|
||||||
}
|
}
|
||||||
|
|
||||||
public int readSamples(float[] samples) throws IOException {
|
public int readSamples(float[] samples) throws IOException {
|
||||||
int framesRead = 0;
|
int framesRead = 0;
|
||||||
|
for (int sampleID = 0; sampleID < samples.length; sampleID++) {
|
||||||
|
if (audioInputStream.read(buffer) > 0) {
|
||||||
|
samples[sampleID] += (buffer[1] << 8) + (buffer[0] & 0x00ff);
|
||||||
|
if (audioInputStream.getFormat().getChannels() > 1) {
|
||||||
|
short altChan = (short) ((buffer[3] << 8) + (buffer[2] & 0x00ff));
|
||||||
|
if (mergeChannels) {
|
||||||
|
samples[sampleID] = altChan > samples[sampleID] ? altChan : samples[sampleID];
|
||||||
|
} else {
|
||||||
|
sampleID++;
|
||||||
|
samples[sampleID] = altChan;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
framesRead ++;
|
||||||
|
samples[sampleID] /= Short.MAX_VALUE+1;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return framesRead;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int readSamples(short[] samples) throws IOException {
|
||||||
|
int framesRead = 0;
|
||||||
|
|
||||||
for (int sampleID = 0; sampleID < samples.length; sampleID++) {
|
for (int sampleID = 0; sampleID < samples.length; sampleID++) {
|
||||||
if (audioInputStream.read(buffer) > 0) {
|
if (audioInputStream.read(buffer) > 0) {
|
||||||
samples[sampleID] += (buffer[1] << 8) + (buffer[0] & 0x00ff);
|
samples[sampleID] += (buffer[1] << 8) + (buffer[0] & 0x00ff);
|
||||||
if (audioInputStream.getFormat().getChannels() > 1) {
|
if (audioInputStream.getFormat().getChannels() > 1) {
|
||||||
short altChan = (short) ((buffer[3] << 8) + (buffer[2] & 0x00ff));
|
short altChan = (short) ((buffer[3] << 8) + (buffer[2] & 0x00ff));
|
||||||
samples[sampleID] = altChan > samples[sampleID] ? altChan : samples[sampleID];
|
if (mergeChannels) {
|
||||||
|
samples[sampleID] = altChan > samples[sampleID] ? altChan : samples[sampleID];
|
||||||
|
} else {
|
||||||
|
sampleID++;
|
||||||
|
samples[sampleID] = altChan;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
framesRead ++;
|
framesRead ++;
|
||||||
samples[sampleID] /= Short.MAX_VALUE+1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return framesRead;
|
return framesRead;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,15 +79,12 @@ public class AudioSampleReader {
|
|||||||
return audioInputStream;
|
return audioInputStream;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getSampleSizeInBits() {
|
|
||||||
return sampleSize;
|
public void setMergeChannels(boolean mergeChannels) {
|
||||||
|
this.mergeChannels = mergeChannels;
|
||||||
|
}
|
||||||
|
public boolean isMergeChannels() {
|
||||||
|
return mergeChannels;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void cleanAndClose() {
|
|
||||||
try {
|
|
||||||
audioInputStream.close();
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user