progress on mp3 pcm processor

This commit is contained in:
Harrison Deng 2018-06-25 20:52:00 -05:00
parent 92ff8871a9
commit aceaa7c89f
5 changed files with 89 additions and 48 deletions

View File

@ -19,7 +19,7 @@ public class RhythmBulletAudioThread extends Thread {
public RhythmBulletAudioThread(int windowSize, VisualizableMusic vm) { public RhythmBulletAudioThread(int windowSize, VisualizableMusic vm) {
music = vm; music = vm;
this.sp = vm.getSampleProcessor(); this.sp = vm.getSampleProcessor();
pcm = new short[sp.getChannels()*windowSize*2]; pcm = new short[(sp.isStereo() ? 2 : 1)*windowSize];
setName("RhythmBullet-AudioPlayback-Thread"); setName("RhythmBullet-AudioPlayback-Thread");
play(); play();
start(); start();
@ -29,7 +29,7 @@ public class RhythmBulletAudioThread extends Thread {
@Override @Override
public void run() { public void run() {
sp.initiate(); sp.initiate();
this.ad = Gdx.audio.newAudioDevice(sp.getSampleRate(), (sp.getChannels() > 1 ? false : true)); this.ad = Gdx.audio.newAudioDevice(sp.getSampleRate(), !sp.isStereo());
while (!terminated && sp.readSamples(pcm, this) > 0) { while (!terminated && sp.readSamples(pcm, this) > 0) {
ad.writeSamples(pcm, 0, pcm.length); ad.writeSamples(pcm, 0, pcm.length);

View File

@ -1,12 +1,11 @@
package zero1hd.rhythmbullet.audio; package zero1hd.rhythmbullet.audio;
import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Paths;
import javax.sound.sampled.UnsupportedAudioFileException; import javax.sound.sampled.UnsupportedAudioFileException;
import com.badlogic.gdx.audio.Music; import com.badlogic.gdx.audio.Music;
import com.badlogic.gdx.files.FileHandle;
import zero1hd.rhythmbullet.audio.processor.MP3PCMProcessor; import zero1hd.rhythmbullet.audio.processor.MP3PCMProcessor;
import zero1hd.rhythmbullet.audio.processor.PCMProcessor; import zero1hd.rhythmbullet.audio.processor.PCMProcessor;
@ -17,19 +16,19 @@ public class VisualizableMusic implements Music {
private OnCompletionListener ocl; private OnCompletionListener ocl;
private boolean looping; private boolean looping;
private RhythmBulletAudioThread rat; private RhythmBulletAudioThread rat;
private File musicFile; private String fileLoc;
private PCMProcessor sampleProcessor; private PCMProcessor sampleProcessor;
public VisualizableMusic(FileHandle file) { public VisualizableMusic(String fileLoc) {
musicFile = file.file(); this.fileLoc = fileLoc;
if (musicFile.getName().toLowerCase().endsWith("wav")) { if (fileLoc.toLowerCase().endsWith("wav")) {
try { try {
sampleProcessor = new WAVPCMProcessor(musicFile, windowSize); sampleProcessor = new WAVPCMProcessor(Paths.get(fileLoc), windowSize);
} catch (IOException | UnsupportedAudioFileException e) { } catch (IOException | UnsupportedAudioFileException e) {
e.printStackTrace(); e.printStackTrace();
} }
} else if (musicFile.getName().toLowerCase().endsWith("mp3")) { } else if (fileLoc.toLowerCase().endsWith("mp3")) {
sampleProcessor = new MP3PCMProcessor(musicFile, windowSize); sampleProcessor = new MP3PCMProcessor(Paths.get(fileLoc), windowSize);
} }
} }

View File

@ -1,68 +1,107 @@
package zero1hd.rhythmbullet.audio.processor; package zero1hd.rhythmbullet.audio.processor;
import java.io.File; import java.io.BufferedInputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import fr.delthas.javamp3.Sound;
public class MP3PCMProcessor implements PCMProcessor { public class MP3PCMProcessor implements PCMProcessor {
private int channels; private boolean stereo;
private int sampleRate; private int sampleRate;
private byte[] buffer;
private volatile float volume, pan; private volatile float volume, pan;
private boolean initiated; private boolean initiated;
private Sound audioInputStream;
private Path path;
private byte[] buffer;
public MP3PCMProcessor(File musicFile, int windowSize) { public MP3PCMProcessor(Path path, int windowSize) {
try(Sound sound = new Sound(new BufferedInputStream(Files.newInputStream(path)))) {
sampleRate = sound.getSamplingFrequency();
stereo = sound.isStereo();
} catch (IOException e) {
e.printStackTrace();
}
} }
@Override @Override
public void initiate() { public void initiate() {
try {
audioInputStream = new Sound(new BufferedInputStream(Files.newInputStream(path)));
} catch (IOException e) {
e.printStackTrace();
}
buffer = new byte[audioInputStream.getAudioFormat().getFrameSize()];
initiated = true;
} }
@Override @Override
public int getChannels() { public boolean isStereo() {
// TODO Auto-generated method stub return stereo;
return 0;
} }
@Override @Override
public int getSampleRate() { public int getSampleRate() {
// TODO Auto-generated method stub return sampleRate;
return 0;
} }
@Override @Override
public int readSamples(short[] pcm, Object syncObj) { public int readSamples(short[] pcm, Object syncObj) {
// TODO Auto-generated method stub if (initiated) {
return 0; synchronized (syncObj) {
int framesRead = 0;
for (int sampleID = 0; sampleID < pcm.length; sampleID++) {
try {
if (audioInputStream.read(buffer) > 0) {
pcm[sampleID] = (short) ((buffer[1] << 8) + (buffer[0] & 0x00ff));
pcm[sampleID] *= volume * (Math.min(1-pan, 1));
if (stereo) {
short secondChan = (short) ((buffer[3] << 8) + (buffer[2] & 0x00ff));
secondChan *= volume * (Math.min(1+pan, 1));
sampleID++;
pcm[sampleID] = secondChan;
}
framesRead++;
}
} catch (IOException e) {
e.printStackTrace();
}
}
return framesRead;
}
} else {
throw new IllegalStateException("Stream has not been initialized.");
}
} }
@Override @Override
public void setVolume(float volume) { public void setVolume(float volume) {
// TODO Auto-generated method stub this.volume = volume;
} }
@Override @Override
public float getVolume() { public float getVolume() {
// TODO Auto-generated method stub return volume;
return 0;
} }
@Override @Override
public void setPan(float pan) { public void setPan(float pan) {
// TODO Auto-generated method stub this.pan = pan;
} }
@Override @Override
public float getPan() { public float getPan() {
// TODO Auto-generated method stub return pan;
return 0;
} }
@Override @Override
public void dispose() { public void dispose() {
// TODO Auto-generated method stub try {
audioInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
} }
} }

View File

@ -13,7 +13,7 @@ public interface PCMProcessor extends Disposable {
/** /**
* @return number of channels * @return number of channels
*/ */
public int getChannels(); public boolean isStereo();
/** /**
* @return sample rate * @return sample rate

View File

@ -1,7 +1,7 @@
package zero1hd.rhythmbullet.audio.processor; package zero1hd.rhythmbullet.audio.processor;
import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Path;
import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream; import javax.sound.sampled.AudioInputStream;
@ -9,18 +9,18 @@ import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.UnsupportedAudioFileException; import javax.sound.sampled.UnsupportedAudioFileException;
public class WAVPCMProcessor implements PCMProcessor { public class WAVPCMProcessor implements PCMProcessor {
private int channels; private boolean stereo;
private int sampleRate; private int sampleRate;
private byte[] buffer; private byte[] buffer;
private File file; private Path path;
private AudioInputStream audioInputStream; private AudioInputStream audioInputStream;
private volatile float volume, pan; private volatile float volume, pan;
private boolean initiated; private boolean initiated;
public WAVPCMProcessor(File musicFile, int windowSize) throws IOException, UnsupportedAudioFileException { public WAVPCMProcessor(Path path, int windowSize) throws IOException, UnsupportedAudioFileException {
this.file = musicFile; this.path = path;
AudioFormat format = AudioSystem.getAudioFileFormat(file).getFormat(); AudioFormat format = AudioSystem.getAudioFileFormat(path.toFile()).getFormat();
channels = format.getChannels(); stereo = format.getChannels() > 1 ? true : false;
sampleRate = (int) format.getSampleRate(); sampleRate = (int) format.getSampleRate();
volume = 1f; volume = 1f;
} }
@ -28,7 +28,7 @@ public class WAVPCMProcessor implements PCMProcessor {
@Override @Override
public void initiate() { public void initiate() {
try { try {
audioInputStream = AudioSystem.getAudioInputStream(file); audioInputStream = AudioSystem.getAudioInputStream(path.toFile());
} catch (UnsupportedAudioFileException | IOException e) { } catch (UnsupportedAudioFileException | IOException e) {
e.printStackTrace(); e.printStackTrace();
} }
@ -36,8 +36,8 @@ public class WAVPCMProcessor implements PCMProcessor {
initiated = true; initiated = true;
} }
public int getChannels() { public boolean isStereo() {
return channels; return stereo;
} }
public int getSampleRate() { public int getSampleRate() {
@ -54,7 +54,7 @@ public class WAVPCMProcessor implements PCMProcessor {
if (audioInputStream.read(buffer) > 0) { if (audioInputStream.read(buffer) > 0) {
pcm[sampleID] = (short) ((buffer[1] << 8) + (buffer[0] & 0x00ff)); pcm[sampleID] = (short) ((buffer[1] << 8) + (buffer[0] & 0x00ff));
pcm[sampleID] *= volume * (Math.min(1-pan, 1)); pcm[sampleID] *= volume * (Math.min(1-pan, 1));
if (audioInputStream.getFormat().getChannels() > 1) { if (stereo) {
short secondChan = (short) ((buffer[3] << 8) + (buffer[2] & 0x00ff)); short secondChan = (short) ((buffer[3] << 8) + (buffer[2] & 0x00ff));
secondChan *= volume * (Math.min(1+pan, 1)); secondChan *= volume * (Math.min(1+pan, 1));
sampleID++; sampleID++;
@ -96,7 +96,10 @@ public class WAVPCMProcessor implements PCMProcessor {
@Override @Override
public void dispose() { public void dispose() {
// TODO Auto-generated method stub try {
audioInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
} }
} }