initial attempt at implementing mp3
This commit is contained in:
parent
d92af2b964
commit
d32794152d
@ -68,14 +68,11 @@ project(":android") {
|
|||||||
|
|
||||||
project(":core") {
|
project(":core") {
|
||||||
apply plugin: "java"
|
apply plugin: "java"
|
||||||
|
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compile "com.badlogicgames.gdx:gdx:$gdxVersion"
|
compile "com.badlogicgames.gdx:gdx:$gdxVersion"
|
||||||
compile "com.badlogicgames.gdx:gdx-freetype:$gdxVersion"
|
compile "com.badlogicgames.gdx:gdx-freetype:$gdxVersion"
|
||||||
|
|
||||||
compile group: 'com.googlecode.soundlibs', name: 'mp3spi', version: '1.9.5.4'
|
compile group: 'com.badlogicgames.jlayer', name: 'jlayer', version: '1.0.1-gdx'
|
||||||
|
|
||||||
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"
|
||||||
|
@ -90,7 +90,7 @@ public class AudioAnalyzer {
|
|||||||
mThresholdCalcRange = thresholdRangeCalc(0.4f);
|
mThresholdCalcRange = thresholdRangeCalc(0.4f);
|
||||||
umThresholdCalcRange = thresholdRangeCalc(0.4f);
|
umThresholdCalcRange = thresholdRangeCalc(0.4f);
|
||||||
|
|
||||||
Gdx.app.debug("Read freq", String.valueOf(audioData.getFormat().getSampleRate()));
|
Gdx.app.debug("Read freq", String.valueOf(audioData.getSampleRate()));
|
||||||
Gdx.app.debug("Using following bin ranges", "\nBass freq begin: " + bassBinBegin + "\nBass freq end: " + bassBinEnd + "\nMain freq begin: " + umBinBegin + "\nMain freq end: " + umBinEnd);
|
Gdx.app.debug("Using following bin ranges", "\nBass freq begin: " + bassBinBegin + "\nBass freq end: " + bassBinEnd + "\nMain freq begin: " + umBinBegin + "\nMain freq end: " + umBinEnd);
|
||||||
|
|
||||||
|
|
||||||
@ -221,7 +221,7 @@ public class AudioAnalyzer {
|
|||||||
}
|
}
|
||||||
Gdx.app.debug("Audio Analyzer", "Data prunned.");
|
Gdx.app.debug("Audio Analyzer", "Data prunned.");
|
||||||
|
|
||||||
secondsPerWindow = audioData.getReadWindowSize()/audioData.getFormat().getSampleRate();
|
secondsPerWindow = audioData.getReadWindowSize()/audioData.getSampleRate();
|
||||||
//peak detection
|
//peak detection
|
||||||
|
|
||||||
int lastID = 0;
|
int lastID = 0;
|
||||||
@ -349,7 +349,7 @@ public class AudioAnalyzer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private int thresholdRangeCalc(float durationOfRange) {
|
private int thresholdRangeCalc(float durationOfRange) {
|
||||||
return (int) (durationOfRange/(audioData.getReadWindowSize()/audioData.getFormat().getSampleRate()));
|
return (int) (durationOfRange/(audioData.getReadWindowSize()/audioData.getSampleRate()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public float getBassMaxValue() {
|
public float getBassMaxValue() {
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
package zero1hd.rhythmbullet.audio;
|
package zero1hd.rhythmbullet.audio;
|
||||||
|
|
||||||
import javax.sound.sampled.AudioFormat;
|
|
||||||
|
|
||||||
import com.badlogic.gdx.audio.Music;
|
import com.badlogic.gdx.audio.Music;
|
||||||
import com.badlogic.gdx.utils.Disposable;
|
import com.badlogic.gdx.utils.Disposable;
|
||||||
|
|
||||||
@ -42,12 +40,6 @@ public interface AudioData extends Disposable {
|
|||||||
*/
|
*/
|
||||||
public int readSamples(float[] samples);
|
public int readSamples(float[] samples);
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns properly setup AudioFormat object.
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public AudioFormat getFormat();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* returns sample count
|
* returns sample count
|
||||||
* @return
|
* @return
|
||||||
@ -59,4 +51,10 @@ public interface AudioData extends Disposable {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public float getDuration();
|
public float getDuration();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* returns sample rate
|
||||||
|
* @return sample rate as float
|
||||||
|
*/
|
||||||
|
public float getSampleRate();
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,6 @@
|
|||||||
package zero1hd.rhythmbullet.audio;
|
package zero1hd.rhythmbullet.audio;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
import java.nio.ByteOrder;
|
|
||||||
|
|
||||||
import javax.sound.sampled.AudioFormat;
|
|
||||||
import javax.sound.sampled.AudioInputStream;
|
|
||||||
import javax.sound.sampled.AudioSystem;
|
|
||||||
import javax.sound.sampled.UnsupportedAudioFileException;
|
|
||||||
|
|
||||||
import org.jaudiotagger.audio.exceptions.InvalidAudioFrameException;
|
import org.jaudiotagger.audio.exceptions.InvalidAudioFrameException;
|
||||||
import org.jaudiotagger.audio.exceptions.ReadOnlyFileException;
|
import org.jaudiotagger.audio.exceptions.ReadOnlyFileException;
|
||||||
@ -19,54 +11,45 @@ import com.badlogic.gdx.Gdx;
|
|||||||
import com.badlogic.gdx.audio.Music;
|
import com.badlogic.gdx.audio.Music;
|
||||||
import com.badlogic.gdx.files.FileHandle;
|
import com.badlogic.gdx.files.FileHandle;
|
||||||
|
|
||||||
import javazoom.jl.decoder.Decoder;
|
import javazoom.jl.decoder.Bitstream;
|
||||||
|
import javazoom.jl.decoder.BitstreamException;
|
||||||
|
import javazoom.jl.decoder.DecoderException;
|
||||||
|
import javazoom.jl.decoder.MP3Decoder;
|
||||||
|
import javazoom.jl.decoder.OutputBuffer;
|
||||||
|
|
||||||
public class Mp3AudioData implements AudioData {
|
public class Mp3AudioData implements AudioData {
|
||||||
private int readWindowSize = 1024;
|
private int readWindowSize = 1024;
|
||||||
|
|
||||||
private AudioInputStream din;
|
|
||||||
|
|
||||||
private AudioFormat decodedFormat;
|
|
||||||
private Music playbackMusic;
|
private Music playbackMusic;
|
||||||
private int readIndex;
|
private int readIndex;
|
||||||
|
|
||||||
|
private int sampleRate;
|
||||||
private int sampleCount;
|
private int sampleCount;
|
||||||
private float durationInSeconds;
|
private float durationInSeconds;
|
||||||
|
|
||||||
private AudioInputStream in;
|
Bitstream bitStream;
|
||||||
|
MP3Decoder decoder;
|
||||||
Decoder decoder = new Decoder();
|
|
||||||
public Mp3AudioData(FileHandle audioFile) {
|
public Mp3AudioData(FileHandle audioFile) {
|
||||||
try {
|
try {
|
||||||
MP3File mp3File = new MP3File(audioFile.file());
|
MP3File mp3File = new MP3File(audioFile.file());
|
||||||
|
|
||||||
sampleCount = (int) mp3File.getMP3AudioHeader().getNumberOfFrames();
|
sampleCount = (int) mp3File.getMP3AudioHeader().getNumberOfFrames();
|
||||||
durationInSeconds = mp3File.getMP3AudioHeader().getNumberOfFrames()/readWindowSize;
|
durationInSeconds = mp3File.getMP3AudioHeader().getNumberOfFrames()/readWindowSize;
|
||||||
|
sampleRate = mp3File.getMP3AudioHeader().getSampleRateAsNumber();
|
||||||
|
|
||||||
|
bitStream = new Bitstream(audioFile.read());
|
||||||
|
decoder = new MP3Decoder();
|
||||||
} catch (IOException | TagException | ReadOnlyFileException | InvalidAudioFrameException e1) {
|
} catch (IOException | TagException | ReadOnlyFileException | InvalidAudioFrameException e1) {
|
||||||
e1.printStackTrace();
|
e1.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
reset();
|
reset();
|
||||||
|
|
||||||
try {
|
|
||||||
File file = audioFile.file();
|
|
||||||
in = AudioSystem.getAudioInputStream(file);
|
|
||||||
din = null;
|
|
||||||
AudioFormat baseFormat = in.getFormat();
|
|
||||||
decodedFormat = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, baseFormat.getSampleRate(), 16,
|
|
||||||
baseFormat.getChannels(), baseFormat.getChannels() * 2, baseFormat.getSampleRate(), false);
|
|
||||||
din = AudioSystem.getAudioInputStream(decodedFormat, in);
|
|
||||||
} catch (UnsupportedAudioFileException | IOException e) {
|
|
||||||
// TODO Auto-generated catch block
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
|
|
||||||
playbackMusic = Gdx.audio.newMusic(audioFile);
|
playbackMusic = Gdx.audio.newMusic(audioFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void readIndexUpdate() {
|
public void readIndexUpdate() {
|
||||||
readIndex = (int) (playbackMusic.getPosition() * decodedFormat.getSampleRate() / readWindowSize);
|
readIndex = (int) (playbackMusic.getPosition() * sampleRate / readWindowSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -76,10 +59,8 @@ public class Mp3AudioData implements AudioData {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void reset() {
|
public void reset() {
|
||||||
if (playbackMusic != null) {
|
|
||||||
playbackMusic.stop();
|
playbackMusic.stop();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getReadWindowSize() {
|
public int getReadWindowSize() {
|
||||||
@ -91,48 +72,6 @@ public class Mp3AudioData implements AudioData {
|
|||||||
return playbackMusic;
|
return playbackMusic;
|
||||||
}
|
}
|
||||||
|
|
||||||
byte[] toBeConverted = new byte[2];
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int readSamples(float[] samples) {
|
|
||||||
int samplesRead = 0;
|
|
||||||
short sampleAverage = 0;
|
|
||||||
|
|
||||||
|
|
||||||
for (int currentSample = 0; currentSample < samples.length; currentSample++) {
|
|
||||||
for (int channel = 0; channel < decodedFormat.getChannels(); channel++) {
|
|
||||||
try {
|
|
||||||
int readCount = din.read(toBeConverted, 0, toBeConverted.length);
|
|
||||||
|
|
||||||
ByteBuffer bBuffer = ByteBuffer.allocate(2);
|
|
||||||
bBuffer.order(ByteOrder.LITTLE_ENDIAN);
|
|
||||||
bBuffer.put(toBeConverted[0]);
|
|
||||||
bBuffer.put(toBeConverted[1]);
|
|
||||||
|
|
||||||
sampleAverage += bBuffer.getShort(0);
|
|
||||||
|
|
||||||
if (readCount == -1) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
|
||||||
// TODO Auto-generated catch block
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sampleAverage /= decodedFormat.getChannels() * Short.MAX_VALUE + 1;
|
|
||||||
samples[currentSample] = sampleAverage;
|
|
||||||
sampleAverage = 0;
|
|
||||||
samplesRead++;
|
|
||||||
}
|
|
||||||
return samplesRead;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AudioFormat getFormat() {
|
|
||||||
return decodedFormat;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getSampleCount() {
|
public int getSampleCount() {
|
||||||
return sampleCount;
|
return sampleCount;
|
||||||
@ -142,15 +81,6 @@ public class Mp3AudioData implements AudioData {
|
|||||||
public void dispose() {
|
public void dispose() {
|
||||||
reset();
|
reset();
|
||||||
playbackMusic.dispose();
|
playbackMusic.dispose();
|
||||||
if (din != null) {
|
|
||||||
try {
|
|
||||||
din.close();
|
|
||||||
in.close();
|
|
||||||
} catch (IOException e) {
|
|
||||||
// TODO Auto-generated catch block
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -158,4 +88,33 @@ public class Mp3AudioData implements AudioData {
|
|||||||
return durationInSeconds;
|
return durationInSeconds;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int readSamples(float[] samples) {
|
||||||
|
int samplesRead = 0;
|
||||||
|
try {
|
||||||
|
OutputBuffer samplesBuffer = decoder.decodeFrame(bitStream.readFrame(), bitStream);
|
||||||
|
byte[] frameBuffer = samplesBuffer.getBuffer();
|
||||||
|
for (int sampleID = 0; sampleID < samples.length; sampleID++) {
|
||||||
|
|
||||||
|
samples[sampleID] += (short) ((frameBuffer[1] << 8) + (frameBuffer[0] & 0xff));
|
||||||
|
if (samplesBuffer.isStereo()) {
|
||||||
|
samples[sampleID] = (short) ((frameBuffer[3] << 8) + (frameBuffer[2] & 0xff));
|
||||||
|
|
||||||
|
samples[sampleID] /= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
samples[sampleID] /= Short.MAX_VALUE+1;
|
||||||
|
samplesRead ++;
|
||||||
|
}
|
||||||
|
} catch (DecoderException | BitstreamException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return samplesRead;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float getSampleRate() {
|
||||||
|
return sampleRate;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -64,11 +64,6 @@ public class WavAudioData implements AudioData {
|
|||||||
return decoder.readSamples(samples);
|
return decoder.readSamples(samples);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public AudioFormat getFormat() {
|
|
||||||
return format;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getSampleCount() {
|
public int getSampleCount() {
|
||||||
return decoder.getDataSize()/(2*decoder.getChannels());
|
return decoder.getDataSize()/(2*decoder.getChannels());
|
||||||
@ -85,4 +80,9 @@ public class WavAudioData implements AudioData {
|
|||||||
public float getDuration() {
|
public float getDuration() {
|
||||||
return decoder.getDurationInSeconds();
|
return decoder.getDurationInSeconds();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float getSampleRate() {
|
||||||
|
return format.getSampleRate();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -114,13 +114,6 @@ public class RhythmMapAlgorithm implements Runnable {
|
|||||||
esi.parameters.put("fuse", avgSPB*10f);
|
esi.parameters.put("fuse", avgSPB*10f);
|
||||||
esi.parameters.put("angle", angle);
|
esi.parameters.put("angle", angle);
|
||||||
} else {
|
} else {
|
||||||
float xSpawnLocation = (rand.nextFloat()*(RhythmBullet.GAME_AREA_WIDTH-2))+1;
|
|
||||||
|
|
||||||
esi = map.addEntity(em.pellet, null);
|
|
||||||
esi.parameters.put("x", xSpawnLocation);
|
|
||||||
esi.parameters.put("y", RhythmBullet.GAME_AREA_HEIGHT-0.25f);
|
|
||||||
esi.parameters.put("angle", 140*rand.nextFloat()+200f);
|
|
||||||
esi.parameters.put("speed", (RhythmBullet.GAME_AREA_HEIGHT/8f)/avgSPB);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -158,6 +158,7 @@ public class Entity extends Actor implements Poolable {
|
|||||||
sprite.setPosition(0, 0);
|
sprite.setPosition(0, 0);
|
||||||
hitbox.set(0, 0, 0, 0);
|
hitbox.set(0, 0, 0, 0);
|
||||||
sprite.setRotation(0);
|
sprite.setRotation(0);
|
||||||
|
sprite.setColor(Color.WHITE);
|
||||||
setPosition(0, 0);
|
setPosition(0, 0);
|
||||||
center.set(0, 0);
|
center.set(0, 0);
|
||||||
angle = 0;
|
angle = 0;
|
||||||
|
@ -37,7 +37,6 @@ public class Flake extends Entity {
|
|||||||
this.timer = fuse;
|
this.timer = fuse;
|
||||||
this.totalTime = fuse;
|
this.totalTime = fuse;
|
||||||
this.angle = angle;
|
this.angle = angle;
|
||||||
hitbox.setSize(getWidth(), getHeight());
|
|
||||||
setPosition(x-getWidth()/2f, y-getHeight()/2f);
|
setPosition(x-getWidth()/2f, y-getHeight()/2f);
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -86,7 +85,7 @@ public class Flake extends Entity {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void draw(Batch batch, float parentAlpha) {
|
public void draw(Batch batch, float parentAlpha) {
|
||||||
sprite.setColor(0.1f,0.1f,0.1f, timer/totalTime);
|
sprite.setColor(0f, 0f, 0f, 1-(timer/totalTime));
|
||||||
super.draw(batch, parentAlpha);
|
super.draw(batch, parentAlpha);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -109,7 +108,6 @@ public class Flake extends Entity {
|
|||||||
public void reset() {
|
public void reset() {
|
||||||
timer = 0;
|
timer = 0;
|
||||||
shards = null;
|
shards = null;
|
||||||
hitbox.set(0, 0, 0, 0);
|
|
||||||
totalTime = 0;
|
totalTime = 0;
|
||||||
super.reset();
|
super.reset();
|
||||||
}
|
}
|
||||||
|
@ -72,6 +72,8 @@ public class Shard extends Entity {
|
|||||||
public void collided(Entity entity) {
|
public void collided(Entity entity) {
|
||||||
if (entity.getClass() == Laser.class) {
|
if (entity.getClass() == Laser.class) {
|
||||||
hp --;
|
hp --;
|
||||||
|
} else {
|
||||||
|
dead = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ public class CreativeScreen extends ScreenAdapter {
|
|||||||
@Override
|
@Override
|
||||||
public void render(float delta) {
|
public void render(float delta) {
|
||||||
Gdx.gl.glClearColor(0.2f, 0.2f, 0.2f, 1f);
|
Gdx.gl.glClearColor(0.2f, 0.2f, 0.2f, 1f);
|
||||||
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);
|
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
bgBatch.begin();
|
bgBatch.begin();
|
||||||
bgBatch.draw(background, 0f, 0f);
|
bgBatch.draw(background, 0f, 0f);
|
||||||
|
@ -95,7 +95,7 @@ public class GameScreen extends ScreenAdapter {
|
|||||||
@Override
|
@Override
|
||||||
public void render(float delta) {
|
public void render(float delta) {
|
||||||
Gdx.gl.glClearColor(0f, 0f, 0f, 0f);
|
Gdx.gl.glClearColor(0f, 0f, 0f, 0f);
|
||||||
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);
|
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
|
||||||
//Background stuff should literally span the whole screen so no matrice stuff
|
//Background stuff should literally span the whole screen so no matrice stuff
|
||||||
bgBatch.begin();
|
bgBatch.begin();
|
||||||
if (bgShader != null) {
|
if (bgShader != null) {
|
||||||
|
@ -120,6 +120,7 @@ public class GameHUD extends Stage {
|
|||||||
setScore(sm.getScore());
|
setScore(sm.getScore());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
if (gpa.getAudioMap() != null && gpa.getAudioMap().getHudType()[gpa.getAudioMap().getIndex()] != 0) {
|
if (gpa.getAudioMap() != null && gpa.getAudioMap().getHudType()[gpa.getAudioMap().getIndex()] != 0) {
|
||||||
switch (gpa.getAudioMap().getHudType()[gpa.getAudioMap().getIndex()]) {
|
switch (gpa.getAudioMap().getHudType()[gpa.getAudioMap().getIndex()]) {
|
||||||
case 1:
|
case 1:
|
||||||
@ -129,6 +130,9 @@ public class GameHUD extends Stage {
|
|||||||
changeStatusColor(um, 0.2f, original);
|
changeStatusColor(um, 0.2f, original);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} catch (ArrayIndexOutOfBoundsException e) {
|
||||||
|
Gdx.app.debug("GameHUD", "reached end of status data.");
|
||||||
|
}
|
||||||
super.act(delta);
|
super.act(delta);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,6 +121,7 @@ public class MusicController extends Window implements OnCompletionListener {
|
|||||||
info.setText("Ready.");
|
info.setText("Ready.");
|
||||||
audiofile.getPlaybackMusic().play();
|
audiofile.getPlaybackMusic().play();
|
||||||
audiofile.getPlaybackMusic().pause();
|
audiofile.getPlaybackMusic().pause();
|
||||||
|
audiofile.getPlaybackMusic().setOnCompletionListener(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user