Began work on music selection UI

This commit is contained in:
Harrison Deng 2017-04-18 23:34:39 -05:00
parent fa87f5e8cf
commit 5a472b21e6
5 changed files with 203 additions and 114 deletions

View File

@ -47,6 +47,8 @@ project(":desktop") {
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"
compile "com.mpatric:mp3agic:0.9.0"
} }
} }
@ -75,6 +77,8 @@ project(":android") {
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"
compile "com.mpatric:mp3agic:0.9.0"
} }
} }
@ -91,6 +95,8 @@ project(":core") {
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"
compile "com.mpatric:mp3agic:0.9.0"
} }
} }

View File

@ -1,8 +1,7 @@
package zero1hd.polyjet.audio; package zero1hd.polyjet.audio;
import java.io.BufferedInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.security.InvalidParameterException;
import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioFormat;
@ -11,19 +10,19 @@ import com.badlogic.gdx.audio.Music;
import com.badlogic.gdx.files.FileHandle; import com.badlogic.gdx.files.FileHandle;
import zero1hd.wavedecoder.WavDecoder; import zero1hd.wavedecoder.WavDecoder;
import zero1hd.wavedecoder.WavInfo;
public class WavAudioData implements AudioData { public class WavAudioData implements AudioData {
private int readWindowSize = 1024; private int readWindowSize = 1024;
private InputStream inStream;
private InputStream bufferedAudioIn;
private AudioFormat format; private AudioFormat format;
int readIndex; int readIndex;
Music playbackMusic; Music playbackMusic;
WavDecoder decoder; WavDecoder decoder;
WavInfo wavinfo;
@Override @Override
public void readIndexUpdate() { public void readIndexUpdate() {
readIndex = (int) (playbackMusic.getPosition() * decoder.getSampleRate() / readWindowSize); readIndex = (int) (playbackMusic.getPosition() * wavinfo.getSampleRate() / readWindowSize);
} }
@Override @Override
@ -31,15 +30,21 @@ public class WavAudioData implements AudioData {
return readIndex; return readIndex;
} }
public void setInfo(WavInfo wavinfo) {
this.wavinfo = wavinfo;
}
@Override @Override
public void setAudioFile(FileHandle audioFileHandler) { public void setAudioFile(FileHandle audioFileHandler) {
reset(); reset();
try {
inStream = audioFileHandler.read(); decoder.setAudioFile(wavinfo);
bufferedAudioIn = new BufferedInputStream(inStream); } catch (InvalidParameterException | IOException e) {
decoder.setAudioFile(audioFileHandler.file()); // TODO Auto-generated catch block
e.printStackTrace();
}
playbackMusic = Gdx.audio.newMusic(audioFileHandler); playbackMusic = Gdx.audio.newMusic(audioFileHandler);
format = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, (float) decoder.getSampleRate(), 16, decoder.getChannels(), decoder.getChannels()*2, (float)decoder.getSampleRate(), false); format = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, (float) wavinfo.getSampleRate(), 16, wavinfo.getChannels(), wavinfo.getChannels()*2, (float) wavinfo.getSampleRate(), false);
} }
@Override @Override
@ -49,16 +54,6 @@ public class WavAudioData implements AudioData {
playbackMusic.dispose(); playbackMusic.dispose();
playbackMusic = null; playbackMusic = null;
} }
if (inStream != null) {
try {
bufferedAudioIn.close();
inStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
} }
@Override @Override

View File

@ -1,16 +1,65 @@
package zero1hd.polyjet.ui.builders; package zero1hd.polyjet.ui.builders;
import com.badlogic.gdx.files.FileHandle; import java.io.IOException;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.ui.Image;
public class MusicSelectable extends Actor { import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.scenes.scene2d.ui.Image;
import com.badlogic.gdx.scenes.scene2d.ui.WidgetGroup;
import com.mpatric.mp3agic.ID3v2;
import com.mpatric.mp3agic.InvalidDataException;
import com.mpatric.mp3agic.Mp3File;
import com.mpatric.mp3agic.UnsupportedTagException;
import zero1hd.wavedecoder.WavInfo;
public class MusicSelectable extends WidgetGroup {
Image imageIcon; Image imageIcon;
FileHandle musicFile; FileHandle musicFile;
boolean invalidMusic;
long durationInSeconds;
String songName;
WavInfo wavinfo;
public MusicSelectable(FileHandle musicFile) { public MusicSelectable(FileHandle musicFile) {
this.musicFile = musicFile; this.musicFile = musicFile;
imageIcon = new Image(new Texture(musicFile));
if (musicFile.extension().toLowerCase().equals("mp3")) {
try {
Mp3File mp3File = new Mp3File(musicFile.file());
durationInSeconds = mp3File.getLengthInSeconds();
if (mp3File.hasId3v2Tag()) {
ID3v2 id3v2tag = mp3File.getId3v2Tag();
byte[] albumWorkBytes = id3v2tag.getAlbumImage();
Pixmap albumArt = new Pixmap(albumWorkBytes, 0, albumWorkBytes.length);
Texture albumArtTexture = new Texture(albumArt);
imageIcon = new Image(albumArtTexture);
float scale = 0.25f*Gdx.graphics.getHeight()/imageIcon.getHeight();
imageIcon.setScale(scale);
albumArtTexture.dispose();
songName = id3v2tag.getTitle();
}
} catch (UnsupportedTagException | InvalidDataException | IOException e) {
e.printStackTrace();
}
} else {
wavinfo = new WavInfo(musicFile.file());
durationInSeconds = wavinfo.getDurationInSeconds();
}
if (durationInSeconds > 60 * 5) {
invalidMusic = true;
}
if (songName == null || songName.isEmpty()) {
songName = musicFile.name();
}
} }
} }

View File

@ -1,96 +1,16 @@
package zero1hd.wavedecoder; package zero1hd.wavedecoder;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException; import java.io.IOException;
import java.security.InvalidParameterException; import java.security.InvalidParameterException;
public class WavDecoder { public class WavDecoder {
DataInputStream readStream; private WavInfo initialData;
private int channels;
private double sampleRate;
private int dataSize;
private int byteRate;
public void setAudioFile(File file) throws InvalidParameterException { public void setAudioFile(WavInfo info) throws InvalidParameterException, IOException {
try { initialData = info;
FileInputStream audioFile = new FileInputStream(file); initialData.initDataStream();
readStream = new DataInputStream(audioFile); initialData.getHeaderInfo();
if (!readBytesToString(4).equals("RIFF")) {
throw new InvalidParameterException("RIFF tag not found in header.");
}
dataSize = littleEndianIntBytes();
if (!readBytesToString(4).equals("WAVE")) {
throw new InvalidParameterException("WAVE format tag not found.");
}
if (!readBytesToString(4).equals("fmt ")) {
throw new InvalidParameterException("fmt header not found.");
}
if (readStream.readByte() != 16) {
throw new InvalidParameterException("Data not pcm?");
}
readStream.skipBytes(3);
if (readStream.readByte() != 1) {
throw new InvalidParameterException("Data not pcm?");
}
readStream.skipBytes(1);
channels = readStream.readByte();
readStream.skipBytes(1);
sampleRate = littleEndianIntBytes();
byteRate = littleEndianIntBytes();
readStream.skipBytes(38);
if (!readBytesToString(4).equals("data")) {
throw new InvalidParameterException("initial data section tag not found");
}
readStream.skipBytes(4);
} catch (IOException e) {
e.printStackTrace();
}
} }
private String readBytesToString(int bytesToRead) throws IOException {
byte byteString[] = new byte[bytesToRead];
readStream.read(byteString);
return new String(byteString);
}
private int littleEndianIntBytes() throws IOException {
int data = readStream.readInt();
return Integer.reverseBytes(data);
}
private short readLittleEndianShort() throws IOException {
short data = readStream.readShort();
return Short.reverseBytes(data);
}
public int getChannels() {
return channels;
}
public double getSampleRate() {
return sampleRate;
}
public int getByteRate() {
return byteRate;
}
public int getDataSize() {
return dataSize;
}
public int readSamples(float[] samples) { public int readSamples(float[] samples) {
int samplesRead = 0; int samplesRead = 0;
@ -98,13 +18,18 @@ public class WavDecoder {
try { try {
int currentSample = 0; int currentSample = 0;
for (int channel = 0; channel < channels; channel++) { for (int channel = 0; channel < initialData.getChannels(); channel++) {
currentSample += readLittleEndianShort(); currentSample += initialData.readLittleEndianShort();
} }
currentSample /= channels*Short.MAX_VALUE+1; currentSample /= initialData.getChannels()*Short.MAX_VALUE+1;
samples[i] = currentSample; samples[i] = currentSample;
samplesRead++; samplesRead++;
} catch (IOException e) { } catch (IOException e) {
try {
initialData.closeStreams();
} catch (IOException e1) {
e1.printStackTrace();
}
break; break;
} }
} }

View File

@ -0,0 +1,114 @@
package zero1hd.wavedecoder;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.InvalidParameterException;
public class WavInfo {
private int channels;
private double sampleRate;
private int dataSize;
private int byteRate;
private FileInputStream audioFile;
private DataInputStream readStream;
public WavInfo(File file) throws InvalidParameterException {
try {
audioFile = new FileInputStream(file);
initDataStream();
getHeaderInfo();
closeStreams();
} catch (IOException e) {
e.printStackTrace();
}
}
protected void getHeaderInfo() throws IOException {
if (!readBytesToString(4).equals("RIFF")) { //4
throw new InvalidParameterException("RIFF tag not found in header.");
}
dataSize = littleEndianIntBytes(); //4
if (!readBytesToString(4).equals("WAVE")) { //4
throw new InvalidParameterException("WAVE format tag not found.");
}
if (!readBytesToString(4).equals("fmt ")) { //4
throw new InvalidParameterException("fmt header not found.");
}
if (readStream.readByte() != 16) { //1
throw new InvalidParameterException("Data not pcm?");
}
readStream.skipBytes(3); //3
if (readStream.readByte() != 1) { //1
throw new InvalidParameterException("Data not pcm?");
}
readStream.skipBytes(1); //1
channels = readStream.readByte(); //1
readStream.skipBytes(1); //1
sampleRate = littleEndianIntBytes(); //4
byteRate = littleEndianIntBytes(); //4
readStream.skipBytes(38); //38
if (!readBytesToString(4).equals("data")) { // 4
throw new InvalidParameterException("initial data section tag not found");
}
}
protected void initDataStream() {
readStream = new DataInputStream(audioFile);
}
protected void closeStreams() throws IOException {
readStream.close();
audioFile.close();
}
private String readBytesToString(int bytesToRead) throws IOException {
byte byteString[] = new byte[bytesToRead];
readStream.read(byteString);
return new String(byteString);
}
private int littleEndianIntBytes() throws IOException {
int data = readStream.readInt();
return Integer.reverseBytes(data);
}
protected short readLittleEndianShort() throws IOException {
short data = readStream.readShort();
return Short.reverseBytes(data);
}
protected DataInputStream getReadStream() {
return readStream;
}
public int getChannels() {
return channels;
}
public int getByteRate() {
return byteRate;
}
public int getDataSize() {
return dataSize;
}
public double getSampleRate() {
return sampleRate;
}
public long getDurationInSeconds() {
return (long) (dataSize/sampleRate);
}
}