reworked the reading system as previous system was not working; not yet
tested;
This commit is contained in:
parent
25142029af
commit
677ada45b6
@ -73,6 +73,7 @@ project(":core") {
|
|||||||
compile "com.badlogicgames.gdx:gdx-freetype:$gdxVersion"
|
compile "com.badlogicgames.gdx:gdx-freetype:$gdxVersion"
|
||||||
|
|
||||||
compile group: 'com.badlogicgames.jlayer', name: 'jlayer', version: '1.0.1-gdx'
|
compile group: 'com.badlogicgames.jlayer', name: 'jlayer', version: '1.0.1-gdx'
|
||||||
|
compile group: 'com.googlecode.soundlibs', name: 'mp3spi', version: '1.9.5-1'
|
||||||
compile "org.apache.commons:commons-math3:3.2"
|
compile "org.apache.commons:commons-math3:3.2"
|
||||||
|
|
||||||
compile "com.github.rwl:jtransforms:2.4.0"
|
compile "com.github.rwl:jtransforms:2.4.0"
|
||||||
|
@ -1,121 +1,69 @@
|
|||||||
package zero1hd.rhythmbullet.audio;
|
package zero1hd.rhythmbullet.audio;
|
||||||
|
|
||||||
import java.io.FileNotFoundException;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.util.Map;
|
||||||
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;
|
|
||||||
import java.util.concurrent.locks.ReentrantLock;
|
|
||||||
import java.util.logging.Level;
|
|
||||||
import java.util.logging.Logger;
|
|
||||||
|
|
||||||
import org.jaudiotagger.audio.exceptions.InvalidAudioFrameException;
|
import javax.sound.sampled.AudioFormat;
|
||||||
import org.jaudiotagger.audio.exceptions.ReadOnlyFileException;
|
import javax.sound.sampled.AudioInputStream;
|
||||||
import org.jaudiotagger.audio.mp3.MP3File;
|
import javax.sound.sampled.AudioSystem;
|
||||||
import org.jaudiotagger.tag.TagException;
|
import javax.sound.sampled.UnsupportedAudioFileException;
|
||||||
|
|
||||||
|
import org.tritonus.share.sampled.TAudioFormat;
|
||||||
|
|
||||||
import com.badlogic.gdx.Gdx;
|
import com.badlogic.gdx.Gdx;
|
||||||
import com.badlogic.gdx.audio.Music;
|
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.math.MathUtils;
|
import com.badlogic.gdx.math.MathUtils;
|
||||||
import com.badlogic.gdx.utils.GdxRuntimeException;
|
|
||||||
|
|
||||||
import javazoom.jl.decoder.Bitstream;
|
import zero1hd.rhythmbullet.audio.wavedecoder.AudioSampleReader;
|
||||||
import javazoom.jl.decoder.BitstreamException;
|
|
||||||
import javazoom.jl.decoder.DecoderException;
|
|
||||||
import javazoom.jl.decoder.Header;
|
|
||||||
import javazoom.jl.decoder.MP3Decoder;
|
|
||||||
import javazoom.jl.decoder.OutputBuffer;
|
|
||||||
|
|
||||||
public class Mp3Manager implements MusicManager {
|
public class Mp3Manager implements MusicManager {
|
||||||
private int readWindowSize = 1024;
|
private int readWindowSize = 1024;
|
||||||
|
private Music music;
|
||||||
private int readWindowIndex;
|
|
||||||
private Music playbackMusic;
|
|
||||||
private int playbackIndex;
|
private int playbackIndex;
|
||||||
|
private FileHandle fileHandle;
|
||||||
|
private AudioInputStream ais;
|
||||||
|
private AudioFormat af;
|
||||||
|
private AudioSampleReader d;
|
||||||
|
private Map<String, Object> properties;
|
||||||
|
|
||||||
private long bitrate;
|
public Mp3Manager(FileHandle file) {
|
||||||
private int sampleRate;
|
this.fileHandle = file;
|
||||||
private long sampleCount;
|
|
||||||
private double durationInSeconds;
|
|
||||||
private byte channels;
|
|
||||||
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();
|
|
||||||
|
|
||||||
private ExecutorService exec;
|
|
||||||
|
|
||||||
private String basicSongName;
|
|
||||||
public Mp3Manager(FileHandle audioFile) {
|
|
||||||
this.file = audioFile;
|
|
||||||
lock = new ReentrantLock();
|
|
||||||
this.basicSongName = audioFile.name();
|
|
||||||
exec = Executors.newSingleThreadExecutor();
|
|
||||||
exec.submit(() -> {
|
|
||||||
lock.lock();
|
|
||||||
Logger.getLogger("org.jaudiotagger").setLevel(Level.OFF);
|
|
||||||
try {
|
|
||||||
MP3File mp3File = new MP3File(audioFile.file());
|
|
||||||
sampleCount = MathUtils.round(Float.valueOf((float) (mp3File.getAudioHeader().getSampleRateAsNumber()*mp3File.getMP3AudioHeader().getPreciseTrackLength())));
|
|
||||||
sampleRate = mp3File.getMP3AudioHeader().getSampleRateAsNumber();
|
|
||||||
durationInSeconds = mp3File.getMP3AudioHeader().getPreciseTrackLength();
|
|
||||||
bitrate = mp3File.getAudioHeader().getBitRateAsNumber();
|
|
||||||
} catch (IOException | TagException | ReadOnlyFileException | InvalidAudioFrameException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
lock.unlock();
|
|
||||||
});
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
raf = new RandomAccessFile(audioFile.file(), "r");
|
AudioInputStream in;
|
||||||
bitstream = new Bitstream(inputStream = Channels.newInputStream(raf.getChannel()));
|
in = AudioSystem.getAudioInputStream(file.file());
|
||||||
decoder = new MP3Decoder();
|
AudioFormat baseFormat = in.getFormat();
|
||||||
} catch (FileNotFoundException e2) {
|
properties = ((TAudioFormat)baseFormat).properties();
|
||||||
e2.printStackTrace();
|
af = new AudioFormat(
|
||||||
throw new InvalidParameterException("Error with creating RandomAccessFile.");
|
AudioFormat.Encoding.PCM_SIGNED,
|
||||||
}
|
baseFormat.getSampleRate(),
|
||||||
try {
|
16, baseFormat.getChannels(),
|
||||||
Header header = bitstream.readFrame();
|
baseFormat.getChannels()*2,
|
||||||
if (header == null) throw new GdxRuntimeException("Empty MP3");
|
baseFormat.getSampleRate(), false);
|
||||||
channels = (byte) (header.mode() == Header.SINGLE_CHANNEL ? 1 : 2);
|
ais = AudioSystem.getAudioInputStream(baseFormat, in);
|
||||||
sampleBuffer = new OutputBuffer(channels, false);
|
in.close();
|
||||||
decoder.setOutputBuffer(sampleBuffer);
|
d = new AudioSampleReader(ais);
|
||||||
workset = new byte[channels*2];
|
music = Gdx.audio.newMusic(file);
|
||||||
} catch (BitstreamException e) {
|
} catch (UnsupportedAudioFileException | IOException e) {
|
||||||
throw new GdxRuntimeException("error while preloading mp3", e);
|
|
||||||
}
|
|
||||||
|
|
||||||
playbackMusic = Gdx.audio.newMusic(audioFile);
|
|
||||||
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public void setReadIndexToPlaybackIndex() {
|
|
||||||
try {
|
|
||||||
long pointer = (long) (getPositionInSeconds()*(bitrate*sampleRate/8f));
|
|
||||||
raf.seek(pointer);
|
|
||||||
System.out.println(pointer);
|
|
||||||
readWindowIndex = playbackIndex;
|
|
||||||
currentByteSet = null;
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void dispose() {
|
||||||
|
music.dispose();
|
||||||
|
try {
|
||||||
|
ais.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void playbackIndexUpdate() {
|
public void playbackIndexUpdate() {
|
||||||
playbackIndex = (int) (playbackMusic.getPosition() * sampleRate / readWindowSize);
|
playbackIndex = (int) ((getDuration()*getSampleRate())/getReadWindowSize());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -128,172 +76,122 @@ public class Mp3Manager implements MusicManager {
|
|||||||
return readWindowSize;
|
return readWindowSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int readSamples(float[] samples) {
|
||||||
|
try {
|
||||||
|
return d.readSamples(samples);
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
};
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getSampleCount() {
|
public long getSampleCount() {
|
||||||
return sampleCount;
|
return ais.getFrameLength();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public float getDuration() {
|
public float getDuration() {
|
||||||
return Float.valueOf(String.valueOf(durationInSeconds));
|
return ((long) properties.get("duration"))/1000000f;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public int readSamples(float[] samples) {
|
|
||||||
int framesRead = 0;
|
|
||||||
for (int sid = 0; sid < samples.length; sid++) {
|
|
||||||
for (int wsid = 0; wsid < workset.length; wsid++) {
|
|
||||||
workset[wsid] = nextByte();
|
|
||||||
}
|
|
||||||
if (currentByteSet != null) {
|
|
||||||
samples[sid] += (workset[1] << 8) + (workset[0] & 0x00ff);
|
|
||||||
if (channels > 1) {
|
|
||||||
short altChan = (short) ((workset[3] << 8) + (workset[2] & 0x00ff));
|
|
||||||
|
|
||||||
samples[sid] = altChan > samples[sid] ? altChan : samples[sid];
|
|
||||||
}
|
|
||||||
framesRead ++;
|
|
||||||
samples[sid] /= Short.MAX_VALUE+1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
readWindowIndex++;
|
|
||||||
|
|
||||||
return framesRead;
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte nextByte() {
|
|
||||||
indexHead++;
|
|
||||||
if (currentByteSet == null || indexHead >= currentByteSet.length) {
|
|
||||||
loadNextBuffer();
|
|
||||||
if (currentByteSet == null) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
indexHead = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return currentByteSet[indexHead];
|
|
||||||
}
|
|
||||||
|
|
||||||
public int loadNextBuffer() {
|
|
||||||
if (bitstream != null) {
|
|
||||||
int bytesRead = 0;
|
|
||||||
try {
|
|
||||||
Header header = bitstream.readFrame();
|
|
||||||
if (header != null) {
|
|
||||||
|
|
||||||
try {
|
|
||||||
decoder.decodeFrame(header, bitstream);
|
|
||||||
} catch (ArrayIndexOutOfBoundsException | DecoderException e) {
|
|
||||||
System.out.println(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
bitstream.closeFrame();
|
|
||||||
bytesRead = sampleBuffer.reset();
|
|
||||||
|
|
||||||
currentByteSet = sampleBuffer.getBuffer();
|
|
||||||
} else {
|
|
||||||
currentByteSet = null;
|
|
||||||
}
|
|
||||||
} catch (BitstreamException e1) {
|
|
||||||
e1.printStackTrace();
|
|
||||||
}
|
|
||||||
return bytesRead;
|
|
||||||
} else {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public float getSampleRate() {
|
public float getSampleRate() {
|
||||||
return sampleRate;
|
return af.getSampleRate();
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getBitrate() {
|
|
||||||
return bitrate;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getreadWindowIndex() {
|
|
||||||
return readWindowIndex;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void pause() {
|
public void pause() {
|
||||||
Gdx.app.debug("MP3Manager", "Pausing...");
|
music.pause();
|
||||||
playbackMusic.pause();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void play() {
|
public void play() {
|
||||||
Gdx.app.debug("Mp3Manager", "MP3 Playing...");
|
music.play();
|
||||||
playbackMusic.play();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isPlaying() {
|
public boolean isPlaying() {
|
||||||
return playbackMusic.isPlaying();
|
return music.isPlaying();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public float getPositionInSeconds() {
|
public float getPositionInSeconds() {
|
||||||
return playbackMusic.getPosition();
|
|
||||||
|
return music.getPosition();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setPosition(float position) {
|
public void setPosition(float position) {
|
||||||
playbackMusic.setPosition(position);
|
music.setPosition(position);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setOnCompletionListener(OnCompletionListener listener) {
|
public void setOnCompletionListener(OnCompletionListener listener) {
|
||||||
playbackMusic.setOnCompletionListener(listener);
|
music.setOnCompletionListener(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setVolume(float percent) {
|
public void setVolume(float percent) {
|
||||||
playbackMusic.setVolume(percent);
|
music.setVolume(percent);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isFinishedLoading() {
|
public boolean isFinishedLoading() {
|
||||||
if (lock.isHeldByCurrentThread()) {
|
return true;
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
if (lock.tryLock(0, TimeUnit.SECONDS)) {
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getBasicSongName() {
|
public String getBasicSongName() {
|
||||||
return basicSongName;
|
return fileHandle.nameWithoutExtension();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public FileHandle getMusicFile() {
|
public FileHandle getMusicFile() {
|
||||||
return file;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
private void closeStream() {
|
||||||
public void dispose() {
|
if (ais != null) {
|
||||||
Gdx.app.debug("MP3Manager", "Disposing...");
|
try {
|
||||||
playbackMusic.stop();
|
ais.close();
|
||||||
playbackMusic.dispose();
|
} catch (IOException e) {
|
||||||
exec.shutdown();
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void reInitStream() {
|
||||||
try {
|
try {
|
||||||
bitstream.close();
|
AudioInputStream in = AudioSystem.getAudioInputStream(fileHandle.file());
|
||||||
bitstream = null;
|
ais = AudioSystem.getAudioInputStream(af, in);
|
||||||
inputStream.close();
|
in.close();
|
||||||
} catch (BitstreamException | IOException e) {
|
} catch (UnsupportedAudioFileException | IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void synchronize() {
|
||||||
|
seek(MathUtils.round(((Integer) properties.get("audio.length.bytes")).intValue() * (getPositionInSeconds()/getDuration())));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -50,16 +50,6 @@ public interface MusicManager extends Disposable {
|
|||||||
*/
|
*/
|
||||||
public float getSampleRate();
|
public float getSampleRate();
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the bitrate of the audio.
|
|
||||||
*/
|
|
||||||
public long getBitrate();
|
|
||||||
/**
|
|
||||||
* The current numerical value of the last window read
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public int getreadWindowIndex();
|
|
||||||
|
|
||||||
public void pause();
|
public void pause();
|
||||||
|
|
||||||
public void play();
|
public void play();
|
||||||
@ -93,7 +83,13 @@ public interface MusicManager extends Disposable {
|
|||||||
public FileHandle getMusicFile();
|
public FileHandle getMusicFile();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Synchronizes reading to current playback.
|
* sets the reading position to the given position;
|
||||||
|
* @param position the byte to skip to.
|
||||||
*/
|
*/
|
||||||
public void setReadIndexToPlaybackIndex();
|
public void seek(long position);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Synchronizes the playback and read threads
|
||||||
|
*/
|
||||||
|
public void synchronize();
|
||||||
}
|
}
|
||||||
|
@ -1,167 +1,177 @@
|
|||||||
package zero1hd.rhythmbullet.audio;
|
package zero1hd.rhythmbullet.audio;
|
||||||
|
|
||||||
import java.io.BufferedInputStream;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.RandomAccessFile;
|
|
||||||
import java.nio.channels.Channels;
|
|
||||||
import java.security.InvalidParameterException;
|
|
||||||
|
|
||||||
import javax.sound.sampled.AudioFormat;
|
import javax.sound.sampled.AudioFormat;
|
||||||
|
import javax.sound.sampled.AudioInputStream;
|
||||||
|
import javax.sound.sampled.AudioSystem;
|
||||||
|
import javax.sound.sampled.UnsupportedAudioFileException;
|
||||||
|
|
||||||
import com.badlogic.gdx.Gdx;
|
import com.badlogic.gdx.Gdx;
|
||||||
import com.badlogic.gdx.audio.Music;
|
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.math.MathUtils;
|
||||||
|
|
||||||
import zero1hd.rhythmbullet.audio.wavedecoder.WavDecoder;
|
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 AudioFormat format;
|
|
||||||
private int playbackIndex;
|
private int playbackIndex;
|
||||||
private int readWindowIndex;
|
private Music music;
|
||||||
private Music playbackMusic;
|
private FileHandle fileHandle;
|
||||||
private WavDecoder decoder;
|
private AudioInputStream ais;
|
||||||
private FileHandle file;
|
private AudioFormat af;
|
||||||
private String basicSongName;
|
private AudioSampleReader d;
|
||||||
private RandomAccessFile raf;
|
|
||||||
|
|
||||||
private int sampleSizeInBits;
|
|
||||||
public WAVManager(FileHandle file) {
|
public WAVManager(FileHandle file) {
|
||||||
this.file = file;
|
this.fileHandle = file;
|
||||||
basicSongName = file.name();
|
|
||||||
try {
|
try {
|
||||||
raf = new RandomAccessFile(file.file(), "r");
|
ais = AudioSystem.getAudioInputStream(file.file());
|
||||||
decoder = new WavDecoder(new BufferedInputStream(Channels.newInputStream(raf.getChannel())));
|
d = new AudioSampleReader(ais);
|
||||||
} catch (InvalidParameterException | IOException e) {
|
af = ais.getFormat();
|
||||||
// TODO Auto-generated catch block
|
} catch (UnsupportedAudioFileException | IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
playbackMusic = Gdx.audio.newMusic(file);
|
music = Gdx.audio.newMusic(file);
|
||||||
format = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, (float) decoder.getSampleRate(), decoder.getSampleSizeInBits(), decoder.getChannels(), decoder.getChannels()*2, (float) decoder.getSampleRate(), false);
|
|
||||||
sampleSizeInBits = decoder.getSampleSizeInBits();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void playbackIndexUpdate() {
|
public void dispose() {
|
||||||
playbackIndex = (int) (playbackMusic.getPosition() * decoder.getSampleRate() / readWindowSize);
|
music.dispose();
|
||||||
|
try {
|
||||||
|
ais.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void playbackIndexUpdate() {
|
||||||
|
playbackIndex = (int) ((getSampleRate() * getDuration())/getReadWindowSize());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getPlaybackIndexPosition() {
|
public int getPlaybackIndexPosition() {
|
||||||
return playbackIndex;
|
return playbackIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getReadWindowSize() {
|
public int getReadWindowSize() {
|
||||||
return readWindowSize;
|
return readWindowSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setReadIndexToPlaybackIndex() {
|
|
||||||
try {
|
|
||||||
long pointer = (long) (getPositionInSeconds()*(getBitrate()/8f));
|
|
||||||
raf.seek(pointer);
|
|
||||||
readWindowIndex = playbackIndex;
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int readSamples(float[] samples) {
|
public int readSamples(float[] samples) {
|
||||||
int samplesRead = 0;
|
|
||||||
try {
|
try {
|
||||||
samplesRead = decoder.readSamples(samples);
|
return d.readSamples(samples);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
if (samplesRead != 0) {
|
|
||||||
readWindowIndex++;
|
|
||||||
}
|
|
||||||
return samplesRead;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getSampleCount() {
|
public long getSampleCount() {
|
||||||
return decoder.getFrameLength();
|
return ais.getFrameLength();
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void dispose() {
|
|
||||||
playbackMusic.stop();
|
|
||||||
playbackMusic.dispose();
|
|
||||||
decoder.cleanAndClose();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public float getDuration() {
|
public float getDuration() {
|
||||||
return decoder.getDurationInSeconds();
|
return ais.getFrameLength()/af.getFrameRate();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public float getSampleRate() {
|
public float getSampleRate() {
|
||||||
return format.getSampleRate();
|
return af.getSampleRate();
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getreadWindowIndex() {
|
|
||||||
return readWindowIndex;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void pause() {
|
public void pause() {
|
||||||
playbackMusic.pause();
|
music.pause();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void play() {
|
public void play() {
|
||||||
playbackMusic.play();
|
music.play();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isPlaying() {
|
public boolean isPlaying() {
|
||||||
return playbackMusic.isPlaying();
|
return music.isPlaying();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public float getPositionInSeconds() {
|
public float getPositionInSeconds() {
|
||||||
return playbackMusic.getPosition();
|
return music.getPosition();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setPosition(float position) {
|
public void setPosition(float position) {
|
||||||
playbackMusic.setPosition(position);
|
music.setPosition(position);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setOnCompletionListener(OnCompletionListener listener) {
|
public void setOnCompletionListener(OnCompletionListener listener) {
|
||||||
playbackMusic.setOnCompletionListener(listener);
|
music.setOnCompletionListener(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setVolume(float percent) {
|
public void setVolume(float percent) {
|
||||||
playbackMusic.setVolume(percent);
|
music.setVolume(percent);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isFinishedLoading() {
|
public boolean isFinishedLoading() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getBasicSongName() {
|
public String getBasicSongName() {
|
||||||
return basicSongName;
|
return fileHandle.nameWithoutExtension();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public FileHandle getMusicFile() {
|
public FileHandle getMusicFile() {
|
||||||
return file;
|
return fileHandle;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getBitrate() {
|
public void seek(long position) {
|
||||||
return (long) (getSampleRate()*sampleSizeInBits);
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void restartStream() {
|
||||||
|
try {
|
||||||
|
ais.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
AudioInputStream in = AudioSystem.getAudioInputStream(fileHandle.file());
|
||||||
|
ais = AudioSystem.getAudioInputStream(af, in);
|
||||||
|
in.close();
|
||||||
|
} catch (UnsupportedAudioFileException | IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void synchronize() {
|
||||||
|
seek(MathUtils.round(getPositionInSeconds()*getSampleRate()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,30 +1,23 @@
|
|||||||
package zero1hd.rhythmbullet.audio.wavedecoder;
|
package zero1hd.rhythmbullet.audio.wavedecoder;
|
||||||
|
|
||||||
import java.io.BufferedInputStream;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import javax.sound.sampled.AudioInputStream;
|
import javax.sound.sampled.AudioInputStream;
|
||||||
import javax.sound.sampled.AudioSystem;
|
|
||||||
import javax.sound.sampled.UnsupportedAudioFileException;
|
|
||||||
|
|
||||||
public class WavDecoder {
|
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 int sampleSize;
|
||||||
private AudioInputStream audioInputStream;
|
private AudioInputStream audioInputStream;
|
||||||
|
|
||||||
public WavDecoder(BufferedInputStream inputStream) throws IOException {
|
public AudioSampleReader(AudioInputStream ais) throws IOException {
|
||||||
try {
|
audioInputStream = ais;
|
||||||
audioInputStream = AudioSystem.getAudioInputStream(inputStream);
|
buffer = new byte[audioInputStream.getFormat().getFrameSize()];
|
||||||
buffer = new byte[audioInputStream.getFormat().getFrameSize()];
|
|
||||||
|
channels = audioInputStream.getFormat().getChannels();
|
||||||
channels = audioInputStream.getFormat().getChannels();
|
sampleRate = audioInputStream.getFormat().getSampleRate();
|
||||||
sampleRate = audioInputStream.getFormat().getSampleRate();
|
sampleSize = audioInputStream.getFormat().getSampleSizeInBits();
|
||||||
sampleSize = audioInputStream.getFormat().getSampleSizeInBits();
|
|
||||||
} catch (UnsupportedAudioFileException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getChannels() {
|
public int getChannels() {
|
@ -29,8 +29,7 @@ public class Visualizer extends Widget implements Disposable {
|
|||||||
if (mm != null && mm.isFinishedLoading() && !mmSet) {
|
if (mm != null && mm.isFinishedLoading() && !mmSet) {
|
||||||
Gdx.app.debug("Visualizer", "\nsample count: " + mm.getSampleCount()
|
Gdx.app.debug("Visualizer", "\nsample count: " + mm.getSampleCount()
|
||||||
+ "\nDuration in seconds: " + mm.getDuration() +
|
+ "\nDuration in seconds: " + mm.getDuration() +
|
||||||
"\nSample rate: " + mm.getSampleRate()
|
"\nSample rate: " + mm.getSampleRate());
|
||||||
+ "\nBit rate: " + mm.getBitrate());
|
|
||||||
vis.setMM(mm);
|
vis.setMM(mm);
|
||||||
mmSet = true;
|
mmSet = true;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user