initial attempt at implementing mp3

This commit is contained in:
Harrison Deng 2017-08-12 00:52:59 -05:00
parent d92af2b964
commit d32794152d
13 changed files with 78 additions and 125 deletions

View File

@ -68,18 +68,15 @@ project(":android") {
project(":core") {
apply plugin: "java"
dependencies {
compile "com.badlogicgames.gdx:gdx:$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 "com.github.rwl:jtransforms:2.4.0"
compile "org:jaudiotagger:2.0.3"
}
}

View File

@ -90,7 +90,7 @@ public class AudioAnalyzer {
mThresholdCalcRange = 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);
@ -221,7 +221,7 @@ public class AudioAnalyzer {
}
Gdx.app.debug("Audio Analyzer", "Data prunned.");
secondsPerWindow = audioData.getReadWindowSize()/audioData.getFormat().getSampleRate();
secondsPerWindow = audioData.getReadWindowSize()/audioData.getSampleRate();
//peak detection
int lastID = 0;
@ -349,7 +349,7 @@ public class AudioAnalyzer {
}
private int thresholdRangeCalc(float durationOfRange) {
return (int) (durationOfRange/(audioData.getReadWindowSize()/audioData.getFormat().getSampleRate()));
return (int) (durationOfRange/(audioData.getReadWindowSize()/audioData.getSampleRate()));
}
public float getBassMaxValue() {

View File

@ -1,7 +1,5 @@
package zero1hd.rhythmbullet.audio;
import javax.sound.sampled.AudioFormat;
import com.badlogic.gdx.audio.Music;
import com.badlogic.gdx.utils.Disposable;
@ -42,12 +40,6 @@ public interface AudioData extends Disposable {
*/
public int readSamples(float[] samples);
/**
* Returns properly setup AudioFormat object.
* @return
*/
public AudioFormat getFormat();
/**
* returns sample count
* @return
@ -59,4 +51,10 @@ public interface AudioData extends Disposable {
* @return
*/
public float getDuration();
/**
* returns sample rate
* @return sample rate as float
*/
public float getSampleRate();
}

View File

@ -1,14 +1,6 @@
package zero1hd.rhythmbullet.audio;
import java.io.File;
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.ReadOnlyFileException;
@ -19,54 +11,45 @@ import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.audio.Music;
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 {
private int readWindowSize = 1024;
private AudioInputStream din;
private AudioFormat decodedFormat;
private Music playbackMusic;
private int readIndex;
private int sampleRate;
private int sampleCount;
private float durationInSeconds;
private AudioInputStream in;
Decoder decoder = new Decoder();
Bitstream bitStream;
MP3Decoder decoder;
public Mp3AudioData(FileHandle audioFile) {
try {
MP3File mp3File = new MP3File(audioFile.file());
sampleCount = (int) mp3File.getMP3AudioHeader().getNumberOfFrames();
durationInSeconds = mp3File.getMP3AudioHeader().getNumberOfFrames()/readWindowSize;
sampleRate = mp3File.getMP3AudioHeader().getSampleRateAsNumber();
bitStream = new Bitstream(audioFile.read());
decoder = new MP3Decoder();
} catch (IOException | TagException | ReadOnlyFileException | InvalidAudioFrameException e1) {
e1.printStackTrace();
}
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);
}
@Override
public void readIndexUpdate() {
readIndex = (int) (playbackMusic.getPosition() * decodedFormat.getSampleRate() / readWindowSize);
readIndex = (int) (playbackMusic.getPosition() * sampleRate / readWindowSize);
}
@Override
@ -76,9 +59,7 @@ public class Mp3AudioData implements AudioData {
@Override
public void reset() {
if (playbackMusic != null) {
playbackMusic.stop();
}
playbackMusic.stop();
}
@Override
@ -91,48 +72,6 @@ public class Mp3AudioData implements AudioData {
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
public int getSampleCount() {
return sampleCount;
@ -142,15 +81,6 @@ public class Mp3AudioData implements AudioData {
public void dispose() {
reset();
playbackMusic.dispose();
if (din != null) {
try {
din.close();
in.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
@Override
@ -158,4 +88,33 @@ public class Mp3AudioData implements AudioData {
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;
}
}

View File

@ -64,11 +64,6 @@ public class WavAudioData implements AudioData {
return decoder.readSamples(samples);
}
@Override
public AudioFormat getFormat() {
return format;
}
@Override
public int getSampleCount() {
return decoder.getDataSize()/(2*decoder.getChannels());
@ -85,4 +80,9 @@ public class WavAudioData implements AudioData {
public float getDuration() {
return decoder.getDurationInSeconds();
}
@Override
public float getSampleRate() {
return format.getSampleRate();
}
}

View File

@ -114,13 +114,6 @@ public class RhythmMapAlgorithm implements Runnable {
esi.parameters.put("fuse", avgSPB*10f);
esi.parameters.put("angle", angle);
} 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);
}
}

View File

@ -158,6 +158,7 @@ public class Entity extends Actor implements Poolable {
sprite.setPosition(0, 0);
hitbox.set(0, 0, 0, 0);
sprite.setRotation(0);
sprite.setColor(Color.WHITE);
setPosition(0, 0);
center.set(0, 0);
angle = 0;

View File

@ -37,7 +37,6 @@ public class Flake extends Entity {
this.timer = fuse;
this.totalTime = fuse;
this.angle = angle;
hitbox.setSize(getWidth(), getHeight());
setPosition(x-getWidth()/2f, y-getHeight()/2f);
}
@ -86,7 +85,7 @@ public class Flake extends Entity {
@Override
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);
}
@ -109,7 +108,6 @@ public class Flake extends Entity {
public void reset() {
timer = 0;
shards = null;
hitbox.set(0, 0, 0, 0);
totalTime = 0;
super.reset();
}

View File

@ -72,6 +72,8 @@ public class Shard extends Entity {
public void collided(Entity entity) {
if (entity.getClass() == Laser.class) {
hp --;
} else {
dead = true;
}
}

View File

@ -47,7 +47,7 @@ public class CreativeScreen extends ScreenAdapter {
@Override
public void render(float delta) {
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.draw(background, 0f, 0f);

View File

@ -95,7 +95,7 @@ public class GameScreen extends ScreenAdapter {
@Override
public void render(float delta) {
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
bgBatch.begin();
if (bgShader != null) {

View File

@ -120,14 +120,18 @@ public class GameHUD extends Stage {
setScore(sm.getScore());
}
if (gpa.getAudioMap() != null && gpa.getAudioMap().getHudType()[gpa.getAudioMap().getIndex()] != 0) {
switch (gpa.getAudioMap().getHudType()[gpa.getAudioMap().getIndex()]) {
case 1:
changeStatusColor(bass, 0.2f, original);
break;
case 2:
changeStatusColor(um, 0.2f, original);
try {
if (gpa.getAudioMap() != null && gpa.getAudioMap().getHudType()[gpa.getAudioMap().getIndex()] != 0) {
switch (gpa.getAudioMap().getHudType()[gpa.getAudioMap().getIndex()]) {
case 1:
changeStatusColor(bass, 0.2f, original);
break;
case 2:
changeStatusColor(um, 0.2f, original);
}
}
} catch (ArrayIndexOutOfBoundsException e) {
Gdx.app.debug("GameHUD", "reached end of status data.");
}
super.act(delta);
}

View File

@ -121,6 +121,7 @@ public class MusicController extends Window implements OnCompletionListener {
info.setText("Ready.");
audiofile.getPlaybackMusic().play();
audiofile.getPlaybackMusic().pause();
audiofile.getPlaybackMusic().setOnCompletionListener(this);
}
}