From cebf36dff97f1230b365f485769d9859f5ec9fb3 Mon Sep 17 00:00:00 2001 From: Recrown Date: Fri, 15 Dec 2017 23:56:38 -0600 Subject: [PATCH] UNTESTED; basic mp3spi setup done; more efficient way of skipping bytes now; syncing of playback and read implemented --- .../rhythmbullet/audio/Mp3Manager.java | 49 +++++++++++------ .../rhythmbullet/audio/MusicManager.java | 13 ++--- .../rhythmbullet/audio/WAVManager.java | 49 ++++++++++------- .../audio/visualizer/VisualizerCore.java | 4 +- .../audio/wavedecoder/AudioSampleReader.java | 53 ++++++++++++------- 5 files changed, 109 insertions(+), 59 deletions(-) diff --git a/core/src/zero1hd/rhythmbullet/audio/Mp3Manager.java b/core/src/zero1hd/rhythmbullet/audio/Mp3Manager.java index a2a9f06..cc61ab2 100755 --- a/core/src/zero1hd/rhythmbullet/audio/Mp3Manager.java +++ b/core/src/zero1hd/rhythmbullet/audio/Mp3Manager.java @@ -22,8 +22,9 @@ import zero1hd.rhythmbullet.audio.wavedecoder.AudioSampleReader; public class Mp3Manager implements MusicManager { private int readWindowSize = 1024; private Music music; - private int playbackIndex; + private int playbackIndex, readIndex; private FileHandle fileHandle; + AudioInputStream in; private AudioInputStream ais; private AudioFormat af; private AudioSampleReader d; @@ -32,7 +33,6 @@ public class Mp3Manager implements MusicManager { public Mp3Manager(FileHandle file) { this.fileHandle = file; try { - AudioInputStream in; in = AudioSystem.getAudioInputStream(file.file()); AudioFormat baseFormat = in.getFormat(); properties = ((TAudioFormat)baseFormat).properties(); @@ -43,7 +43,6 @@ public class Mp3Manager implements MusicManager { baseFormat.getChannels()*2, baseFormat.getSampleRate(), false); ais = AudioSystem.getAudioInputStream(baseFormat, in); - in.close(); d = new AudioSampleReader(ais); music = Gdx.audio.newMusic(file); } catch (UnsupportedAudioFileException | IOException e) { @@ -56,6 +55,7 @@ public class Mp3Manager implements MusicManager { music.dispose(); try { ais.close(); + in.close(); } catch (IOException e) { e.printStackTrace(); } @@ -79,6 +79,7 @@ public class Mp3Manager implements MusicManager { @Override public int readSamples(float[] samples) { try { + readIndex++; return d.readSamples(samples); } catch (IOException e) { e.printStackTrace(); @@ -152,22 +153,10 @@ public class Mp3Manager implements MusicManager { return fileHandle; } - @Override public void seek(long position) { - long totalSkipped = 0; - long skipped = 0; closeStream(); reInitStream(); - while (totalSkipped < position) { - try { - skipped = ais.skip(position-totalSkipped); - } catch (IOException e) { - e.printStackTrace(); - } - - if (skipped == 0) break; - totalSkipped += skipped; - } + skip(position); } private void closeStream() { @@ -194,4 +183,32 @@ public class Mp3Manager implements MusicManager { public void synchronize() { 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++; + } + } diff --git a/core/src/zero1hd/rhythmbullet/audio/MusicManager.java b/core/src/zero1hd/rhythmbullet/audio/MusicManager.java index 396b357..b131e5f 100755 --- a/core/src/zero1hd/rhythmbullet/audio/MusicManager.java +++ b/core/src/zero1hd/rhythmbullet/audio/MusicManager.java @@ -82,14 +82,15 @@ public interface MusicManager extends Disposable { */ 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 */ public void synchronize(); + + /** + * @return the window that the current read index is on + */ + public int getReadIndex(); + + public void skipReadWindow(); } diff --git a/core/src/zero1hd/rhythmbullet/audio/WAVManager.java b/core/src/zero1hd/rhythmbullet/audio/WAVManager.java index 1613178..5485948 100755 --- a/core/src/zero1hd/rhythmbullet/audio/WAVManager.java +++ b/core/src/zero1hd/rhythmbullet/audio/WAVManager.java @@ -17,7 +17,7 @@ import zero1hd.rhythmbullet.audio.wavedecoder.AudioSampleReader; public class WAVManager implements MusicManager { private int readWindowSize = 1024; - private int playbackIndex; + private int playbackIndex, readIndex; private Music music; private FileHandle fileHandle; private AudioInputStream ais; @@ -64,6 +64,7 @@ public class WAVManager implements MusicManager { @Override public int readSamples(float[] samples) { try { + readIndex++; return d.readSamples(samples); } catch (IOException e) { e.printStackTrace(); @@ -136,22 +137,9 @@ public class WAVManager implements MusicManager { return fileHandle; } - @Override public void seek(long position) { - long totalSkipped = 0; - long skipped = 0; - restartStream(); - while (totalSkipped < position) { - try { - skipped = ais.skip(position-totalSkipped); - } catch (IOException e) { - e.printStackTrace(); - } - - if (skipped == 0) break; - totalSkipped += skipped; - } + skip(position); } private void restartStream() { @@ -162,9 +150,7 @@ public class WAVManager implements MusicManager { } try { - AudioInputStream in = AudioSystem.getAudioInputStream(fileHandle.file()); - ais = AudioSystem.getAudioInputStream(af, in); - in.close(); + ais = AudioSystem.getAudioInputStream(fileHandle.file()); } catch (UnsupportedAudioFileException | IOException e) { e.printStackTrace(); } @@ -173,5 +159,32 @@ public class WAVManager implements MusicManager { @Override public void synchronize() { 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++; } } diff --git a/core/src/zero1hd/rhythmbullet/audio/visualizer/VisualizerCore.java b/core/src/zero1hd/rhythmbullet/audio/visualizer/VisualizerCore.java index 4c412ce..90d3124 100755 --- a/core/src/zero1hd/rhythmbullet/audio/visualizer/VisualizerCore.java +++ b/core/src/zero1hd/rhythmbullet/audio/visualizer/VisualizerCore.java @@ -33,8 +33,10 @@ public class VisualizerCore implements Disposable { updateTimer += delta; if (updateTimer >= updateRate) { mm.playbackIndexUpdate(); + while (mm.getPlaybackIndexPosition() > mm.getReadIndex()) { + mm.skipReadWindow(); + } lock.lock(); - mm.setReadIndexToPlaybackIndex(); mm.readSamples(audioPCM); fft.realForward(audioPCM); lock.unlock(); diff --git a/core/src/zero1hd/rhythmbullet/audio/wavedecoder/AudioSampleReader.java b/core/src/zero1hd/rhythmbullet/audio/wavedecoder/AudioSampleReader.java index 1c35256..9589214 100755 --- a/core/src/zero1hd/rhythmbullet/audio/wavedecoder/AudioSampleReader.java +++ b/core/src/zero1hd/rhythmbullet/audio/wavedecoder/AudioSampleReader.java @@ -8,8 +8,8 @@ public class AudioSampleReader { private int channels; private double sampleRate; private byte[] buffer; - private int sampleSize; private AudioInputStream audioInputStream; + private boolean mergeChannels; public AudioSampleReader(AudioInputStream ais) throws IOException { audioInputStream = ais; @@ -17,7 +17,6 @@ public class AudioSampleReader { channels = audioInputStream.getFormat().getChannels(); sampleRate = audioInputStream.getFormat().getSampleRate(); - sampleSize = audioInputStream.getFormat().getSampleSizeInBits(); } public int getChannels() { @@ -28,30 +27,51 @@ public class AudioSampleReader { return sampleRate; } - public float getDurationInSeconds() { - return audioInputStream.getFrameLength()/audioInputStream.getFormat().getFrameRate(); - } - public long getFrameLength() { return audioInputStream.getFrameLength(); } public int readSamples(float[] samples) throws IOException { 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++) { 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)); - samples[sampleID] = altChan > samples[sampleID] ? altChan : samples[sampleID]; + if (mergeChannels) { + samples[sampleID] = altChan > samples[sampleID] ? altChan : samples[sampleID]; + } else { + sampleID++; + samples[sampleID] = altChan; + } } framesRead ++; - samples[sampleID] /= Short.MAX_VALUE+1; } } - return framesRead; } @@ -59,15 +79,12 @@ public class AudioSampleReader { 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(); - } - } }