changed analysis system's structure by adding mini context object for analysis output; multithreading changed to using executor service

This commit is contained in:
Harrison Deng 2017-08-30 20:26:24 -05:00
parent 695ed19c50
commit e15d571848
23 changed files with 485 additions and 342 deletions

View File

@ -3,7 +3,7 @@ package zero1hd.rhythmbullet.audio;
import com.badlogic.gdx.files.FileHandle;
public class Audio {
public static AudioData getAudioData(FileHandle file) {
public static BasicMusicInfo getAudioData(FileHandle file) {
if (file.extension().equalsIgnoreCase("wav")) {
return new WavAudioData(file);
} else if (file.extension().equalsIgnoreCase("mp3")) {

View File

@ -1,5 +1,8 @@
package zero1hd.rhythmbullet.audio;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.utils.FloatArray;
@ -11,7 +14,7 @@ public class AudioAnalyzer {
private boolean containsData;
private boolean finalized;
FloatFFT_1D fft;
public AudioData audioData;
private BasicMusicInfo audioData;
float[] audioPCM;
float[] spectrum;
@ -23,9 +26,6 @@ public class AudioAnalyzer {
int bassBinBegin;
int bassBinEnd;
private FloatArray bassSpectralFlux = new FloatArray();
private FloatArray bassThreshold = new FloatArray();
private FloatArray bassPrunned = new FloatArray();
private FloatArray bassPeaks = new FloatArray();
private float bassMaxValue;
private float bassAvg;
float bassThresholdMultiplier;
@ -34,9 +34,6 @@ public class AudioAnalyzer {
int mBinBegin;
int mBinEnd;
private FloatArray mSpectralFlux = new FloatArray();
private FloatArray mThreshold = new FloatArray();
private FloatArray mPrunned = new FloatArray();
private FloatArray mPeaks = new FloatArray();
private float mMaxValue;
private float mAvg;
float mThresholdMultiplier;
@ -45,310 +42,303 @@ public class AudioAnalyzer {
int umBinBegin;
int umBinEnd;
private FloatArray umSpectralFlux = new FloatArray();
private FloatArray umThreshold = new FloatArray();
private FloatArray umPrunned = new FloatArray();
private FloatArray umPeaks = new FloatArray();
private float umMaxValue;
private float umAvg;
float umThresholdMultiplier;
int umThresholdCalcRange;
public volatile MiniSender sender;
public MiniSender sender;
private float avgSPB;
int PUID;
boolean work;
private volatile int progress;
private int progress;
private float secondsPerWindow;
private AudioDataPackage pack;
public AudioAnalyzer() {
sender = new MiniSender();
analysisAlgorithm = new Runnable() {
analysisAlgorithm = () -> {
progress = 0;
int tasksDone = 0;
long totalTasks = audioData.getSampleCount()/audioData.getReadWindowSize();
bassThresholdMultiplier = 1.5f;
mThresholdMultiplier = 1.4f;
umThresholdMultiplier = 1.4f;
bassBinBegin = 0;
bassBinEnd = 12;
mBinBegin = 50;
mBinEnd = 250;
umBinBegin = 350;
umBinEnd = 513;
bassThresholdCalcRange = thresholdRangeCalc(0.27f);
mThresholdCalcRange = thresholdRangeCalc(0.4f);
umThresholdCalcRange = thresholdRangeCalc(0.4f);
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);
@Override
public void run() {
progress = 0;
int tasksDone = 0;
long totalTasks = audioData.getSampleCount()/audioData.getReadWindowSize();
Gdx.app.debug("Total tasks", String.valueOf(totalTasks));
Gdx.app.debug("Threshold Calc Range UM", String.valueOf(umThresholdCalcRange));
Gdx.app.debug("Threshold Calc Range M", String.valueOf(umThresholdCalcRange));
Gdx.app.debug("Threshold Calc Range Bass", String.valueOf(bassThresholdCalcRange));
fft = new FloatFFT_1D(audioData.getReadWindowSize());
int seedDigit = 0;
while (audioData.readSamples(audioPCM) > 0 && work) {
bassThresholdMultiplier = 1.5f;
mThresholdMultiplier = 1.4f;
umThresholdMultiplier = 1.4f;
fft.realForward(audioPCM);
bassBinBegin = 0;
bassBinEnd = 12;
mBinBegin = 50;
mBinEnd = 250;
umBinBegin = 350;
umBinEnd = 513;
bassThresholdCalcRange = thresholdRangeCalc(0.27f);
mThresholdCalcRange = thresholdRangeCalc(0.4f);
umThresholdCalcRange = thresholdRangeCalc(0.4f);
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("Total tasks", String.valueOf(totalTasks));
Gdx.app.debug("Threshold Calc Range UM", String.valueOf(umThresholdCalcRange));
Gdx.app.debug("Threshold Calc Range M", String.valueOf(umThresholdCalcRange));
Gdx.app.debug("Threshold Calc Range Bass", String.valueOf(bassThresholdCalcRange));
fft = new FloatFFT_1D(audioData.getReadWindowSize());
int seedDigit = 0;
while (audioData.readSamples(audioPCM) > 0 && work) {
fft.realForward(audioPCM);
//Building a PUID (Pseudo unique ID)
if (tasksDone == (seedDigit*totalTasks/9)) {
float avg = 0;
for (int frame = 0; frame < spectrum.length; frame++) {
avg += spectrum[frame];
}
avg /= spectrum.length;
if (avg < 0) {
avg *= -1f;
}
PUID +=(int) Math.pow(10, 9-seedDigit) * ((int)(avg*1000f)-(int)(avg*100f)*10);
seedDigit ++;
//Building a PUID (Pseudo unique ID)
if (tasksDone == (seedDigit*totalTasks/9)) {
float avg = 0;
for (int frame = 0; frame < spectrum.length; frame++) {
avg += spectrum[frame];
}
System.arraycopy(spectrum, 0, lastSpectrum, 0, spectrum.length);
System.arraycopy(audioPCM, 0, spectrum, 0, spectrum.length);
float fluxVal;
//bass detection
fluxVal = 0;
for (int i = bassBinBegin; i < bassBinEnd && work; i++) {
fluxVal += ((spectrum[i] - lastSpectrum[i])) < 0
? 0 : (spectrum[i] - lastSpectrum[i]);
avg /= spectrum.length;
if (avg < 0) {
avg *= -1f;
}
bassSpectralFlux.add(fluxVal);
//m detection
fluxVal = 0;
for (int i = mBinBegin; i < mBinEnd && work; i++) {
fluxVal += ((spectrum[i] - lastSpectrum[i])) < 0
? 0 : (spectrum[i] - lastSpectrum[i]);
}
mSpectralFlux.add(fluxVal);
//um detection
fluxVal = 0;
for (int i = umBinBegin; i < umBinEnd && work; i++) {
fluxVal += ((spectrum[i] - lastSpectrum[i])) < 0
? 0 : (spectrum[i] - lastSpectrum[i]);
}
umSpectralFlux.add(fluxVal);
tasksDone++;
progress = (int) (100f*tasksDone/totalTasks);
sender.send(MiniEvents.ANALYZER_ITERATED);
PUID +=(int) Math.pow(10, 9-seedDigit) * ((int)(avg*1000f)-(int)(avg*100f)*10);
seedDigit ++;
}
if (work) {
Gdx.app.debug("Audio Analyzer", "Done getting spectral flux.");
Gdx.app.debug("Audio Analyzer", "window count: " + bassSpectralFlux.size);
shrinkData();
containsData = true;
Gdx.app.debug("Audio Analyzer", "USING SEED: " + PUID);
progress = 100;
sender.send(MiniEvents.SPECTRAL_FLUX_DONE);
System.arraycopy(spectrum, 0, lastSpectrum, 0, spectrum.length);
System.arraycopy(audioPCM, 0, spectrum, 0, spectrum.length);
float fluxVal;
//bass detection
fluxVal = 0;
for (int i = bassBinBegin; i < bassBinEnd; i++) {
fluxVal += ((spectrum[i] - lastSpectrum[i])) < 0
? 0 : (spectrum[i] - lastSpectrum[i]);
}
bassSpectralFlux.add(fluxVal);
//m detection
fluxVal = 0;
for (int i = mBinBegin; i < mBinEnd; i++) {
fluxVal += ((spectrum[i] - lastSpectrum[i])) < 0
? 0 : (spectrum[i] - lastSpectrum[i]);
}
mSpectralFlux.add(fluxVal);
//um detection
fluxVal = 0;
for (int i = umBinBegin; i < umBinEnd; i++) {
fluxVal += ((spectrum[i] - lastSpectrum[i])) < 0
? 0 : (spectrum[i] - lastSpectrum[i]);
}
umSpectralFlux.add(fluxVal);
tasksDone++;
progress = (int) (100f*tasksDone/totalTasks);
sender.send(MiniEvents.ANALYZER_ITERATED);
}
if (work) {
Gdx.app.debug("Audio Analyzer", "Done getting spectral flux.");
Gdx.app.debug("Audio Analyzer", "window count: " + bassSpectralFlux.size);
containsData = true;
Gdx.app.debug("Audio Analyzer", "USING SEED: " + PUID);
progress = 100;
sender.send(MiniEvents.SPECTRAL_FLUX_DONE);
}
};
thresholdCalculator = new Runnable() {
@Override
public void run() {
Gdx.app.debug("Audio Analyzer", "beginning thrshold calc.");
//threshold calculation
for (int i = 0; i < umSpectralFlux.size && work; i++) {
int start = Math.max(0, i - umThresholdCalcRange/2);
int end = Math.min(umSpectralFlux.size - 1, i + umThresholdCalcRange/2);
float average = 0;
for (int j = start; j <= end; j++) {
average += bassSpectralFlux.get(j);
}
average /= (end - start);
bassThreshold.add(average * bassThresholdMultiplier);
average = 0;
for (int j = start; j <= end; j++) {
average+= mSpectralFlux.get(j);
}
average /= (end - start);
mThreshold.add(average*mThresholdMultiplier);
average = 0;
for (int j = start; j <= end; j++) {
average+= umSpectralFlux.get(j);
}
average /= (end - start);
umThreshold.add(average*umThresholdMultiplier);
thresholdCalculator = () -> {
Gdx.app.debug("Audio Analyzer", "beginning threshold calc.");
FloatArray bassThreshold = new FloatArray();
FloatArray mThreshold = new FloatArray();
FloatArray umThreshold = new FloatArray();
//threshold calculation
for (int i = 0; i < umSpectralFlux.size && work; i++) {
int start = Math.max(0, i - umThresholdCalcRange/2);
int end = Math.min(umSpectralFlux.size - 1, i + umThresholdCalcRange/2);
float average = 0;
for (int j = start; j <= end; j++) {
average += bassSpectralFlux.get(j);
}
average /= (end - start);
bassThreshold.add(average * bassThresholdMultiplier);
average = 0;
for (int j = start; j <= end; j++) {
average+= mSpectralFlux.get(j);
}
average /= (end - start);
mThreshold.add(average*mThresholdMultiplier);
average = 0;
for (int j = start; j <= end; j++) {
average+= umSpectralFlux.get(j);
}
average /= (end - start);
umThreshold.add(average*umThresholdMultiplier);
}
Gdx.app.debug("Audio Analyzer", "Threshold calculated.");
//pruning data
float prunnedCurrentVal;
FloatArray bassPrunned = new FloatArray();
FloatArray mPrunned = new FloatArray();
FloatArray umPrunned = new FloatArray();
for (int i = 0; i < umSpectralFlux.size && work; i++) {
prunnedCurrentVal = bassSpectralFlux.get(i) - bassThreshold.get(i);
if (prunnedCurrentVal >= 0) {
bassPrunned.add(prunnedCurrentVal);
} else {
bassPrunned.add(0);
}
Gdx.app.debug("Audio Analyzer", "Threshold calculated.");
//pruning data
float prunnedCurrentVal;
for (int i = 0; i < umSpectralFlux.size && work; i++) {
prunnedCurrentVal = bassSpectralFlux.get(i) - bassThreshold.get(i);
if (prunnedCurrentVal >= 0) {
bassPrunned.add(prunnedCurrentVal);
} else {
bassPrunned.add(0);
}
prunnedCurrentVal = mSpectralFlux.get(i) - mThreshold.get(i);
if (prunnedCurrentVal >= 0 ) {
mPrunned.add(prunnedCurrentVal);
} else {
mPrunned.add(0);
}
prunnedCurrentVal = umSpectralFlux.get(i) - umThreshold.get(i);
if (prunnedCurrentVal >= 0 ) {
umPrunned.add(prunnedCurrentVal);
} else {
umPrunned.add(0);
}
}
Gdx.app.debug("Audio Analyzer", "Data prunned.");
secondsPerWindow = audioData.getReadWindowSize()/audioData.getSampleRate();
//peak detection
int lastID = 0;
float bassBeats = 0;
float mBeats = 0;
float umBeats = 0;
avgSPB = -1f;
for (int i = 0; i < umPrunned.size-1 && work; i++) {
bassPeaks.add((bassPrunned.get(i) > bassPrunned.get(i+1) ? bassPrunned.get(i) : 0f));
if (bassPeaks.get(i) > bassMaxValue) {
bassMaxValue = bassPeaks.get(i);
}
mPeaks.add((mPrunned.get(i) > mPrunned.get(i+1) ? mPrunned.get(i) : 0f));
if (mPeaks.get(i) > mMaxValue) {
mMaxValue = mPeaks.get(i);
}
umPeaks.add((umPrunned.get(i) > umPrunned.get(i+1) ? umPrunned.get(i) : 0f));
if (umPeaks.get(i) > umMaxValue) {
umMaxValue = umPeaks.get(i);
}
if (avgSPB != -1) {
if (bassPeaks.get(i) == 0) {
avgSPB ++;
} else {
lastID = i;
}
} else if (bassPeaks.get(i) != 0) {
avgSPB = 0;
}
if (bassPeaks.get(i) != 0) {
bassAvg += bassPeaks.get(i);
bassBeats++;
}
if (mPeaks.get(i) != 0) {
mAvg += mPeaks.get(i);
mBeats++;
}
if (umPeaks.get(i) != 0) {
umAvg += umPeaks.get(i);
umBeats++;
}
prunnedCurrentVal = mSpectralFlux.get(i) - mThreshold.get(i);
if (prunnedCurrentVal >= 0 ) {
mPrunned.add(prunnedCurrentVal);
} else {
mPrunned.add(0);
}
//then we minus one from the beats so it actually works out
avgSPB -= bassPrunned.size-lastID;
avgSPB *= secondsPerWindow;
avgSPB /= bassBeats;
Gdx.app.debug("Audio Analyzer", "Avg SPB: " + avgSPB);
bassAvg /= bassBeats;
mAvg /= mBeats;
umAvg /= umBeats;
Gdx.app.debug("Audio Analyzer", "Avg bass: " + bassAvg);
Gdx.app.debug("Audio Analyzer", "Avg M: " + mAvg);
Gdx.app.debug("Audio Analyzer", "Avg UM: " + umAvg);
if (work) {
finalized = true;
sender.send(MiniEvents.MUSIC_DATA_CLEANED);
prunnedCurrentVal = umSpectralFlux.get(i) - umThreshold.get(i);
if (prunnedCurrentVal >= 0 ) {
umPrunned.add(prunnedCurrentVal);
} else {
umPrunned.add(0);
}
}
Gdx.app.debug("Audio Analyzer", "Data prunned.");
secondsPerWindow = audioData.getReadWindowSize()/audioData.getSampleRate();
//peak detection
int lastID = 0;
float bassBeats = 0;
float mBeats = 0;
float umBeats = 0;
avgSPB = -1f;
FloatArray bassPeaks = new FloatArray();
FloatArray mPeaks = new FloatArray();
FloatArray umPeaks = new FloatArray();
for (int i = 0; i < umPrunned.size-1 && work; i++) {
bassPeaks.add((bassPrunned.get(i) > bassPrunned.get(i+1) ? bassPrunned.get(i) : 0f));
if (bassPeaks.get(i) > bassMaxValue) {
bassMaxValue = bassPeaks.get(i);
}
mPeaks.add((mPrunned.get(i) > mPrunned.get(i+1) ? mPrunned.get(i) : 0f));
if (mPeaks.get(i) > mMaxValue) {
mMaxValue = mPeaks.get(i);
}
umPeaks.add((umPrunned.get(i) > umPrunned.get(i+1) ? umPrunned.get(i) : 0f));
if (umPeaks.get(i) > umMaxValue) {
umMaxValue = umPeaks.get(i);
}
if (avgSPB != -1) {
if (bassPeaks.get(i) == 0) {
avgSPB ++;
} else {
lastID = i;
}
} else if (bassPeaks.get(i) != 0) {
avgSPB = 0;
}
if (bassPeaks.get(i) != 0) {
bassAvg += bassPeaks.get(i);
bassBeats++;
}
if (mPeaks.get(i) != 0) {
mAvg += mPeaks.get(i);
mBeats++;
}
if (umPeaks.get(i) != 0) {
umAvg += umPeaks.get(i);
umBeats++;
}
}
//then we minus one from the beats so it actually works out
avgSPB -= bassPrunned.size-lastID;
avgSPB *= secondsPerWindow;
avgSPB /= bassBeats;
Gdx.app.debug("Audio Analyzer", "Avg SPB: " + avgSPB);
bassAvg /= bassBeats;
mAvg /= mBeats;
umAvg /= umBeats;
Gdx.app.debug("Audio Analyzer", "Avg bass: " + bassAvg);
Gdx.app.debug("Audio Analyzer", "Avg M: " + mAvg);
Gdx.app.debug("Audio Analyzer", "Avg UM: " + umAvg);
pack = new AudioDataPackage();
pack.setBassData(bassPeaks, bassMaxValue, bassAvg);
pack.setmPeaks(mPeaks, mMaxValue, mAvg);
pack.setUmPeaks(umPeaks, umMaxValue, umAvg);
pack.setPUID(PUID);
pack.setAvgSPB(avgSPB);
pack.setSecPerWin(secondsPerWindow);
sender.send(MiniEvents.MUSIC_DATA_CLEANED);
};
}
public void shrinkData() {
bassSpectralFlux.shrink();
bassThreshold.shrink();
bassPrunned.shrink();
bassPeaks.shrink();
mSpectralFlux.shrink();
mThreshold.shrink();
mPrunned.shrink();
mPeaks.shrink();
umSpectralFlux.shrink();
umThreshold.shrink();
umPrunned.shrink();
umPeaks.shrink();
bassSpectralFlux = null;
mSpectralFlux = null;
umSpectralFlux = null;
}
public void startAnalyticalThread(AudioData audiofile) {
public void startAnalyticalThread(BasicMusicInfo audiofile) {
audioPCM = new float[audiofile.getReadWindowSize()];
spectrum = new float[(audiofile.getReadWindowSize()/2)+1];
lastSpectrum = new float[(audiofile.getReadWindowSize()/2)+1];
this.audioData = audiofile;
work = true;
Thread analyticalThread = new Thread(analysisAlgorithm);
analyticalThread.start();
ExecutorService exec = Executors.newSingleThreadExecutor();
exec.submit(analysisAlgorithm);
}
public void runThresholdCleaning(float rangeModifier) {
this.bassThresholdMultiplier -= rangeModifier;
this.umThresholdMultiplier -= rangeModifier;
work = true;
Thread thresholdClean = new Thread(thresholdCalculator);
thresholdClean.start();
if (containsData) {
ExecutorService exec = Executors.newSingleThreadExecutor();
exec.submit(thresholdCalculator);
} else {
throw new NullPointerException("Either you didn't start the spectral flux gen, or you didn't let it finish.");
}
}
public void runThresholdCleaning() {
Thread thresholdClean = new Thread(thresholdCalculator);
thresholdClean.start();
}
public FloatArray getBassPeaks() {
return bassPeaks;
}
public FloatArray getmPeaks() {
return mPeaks;
}
public FloatArray getUMPeaks() {
return umPeaks;
work = true;
if (containsData) {
ExecutorService exec = Executors.newSingleThreadExecutor();
exec.submit(thresholdCalculator);
} else {
throw new NullPointerException("Either you didn't start the spectral flux gen, or you didn't let it finish.");
}
}
private int thresholdRangeCalc(float durationOfRange) {
@ -367,14 +357,6 @@ public class AudioAnalyzer {
return umMaxValue;
}
public int getReadIndex() {
if (audioData.getReadIndex() < umPeaks.size) {
return audioData.getReadIndex();
} else {
return 0;
}
}
public boolean containsData() {
return containsData;
}
@ -395,7 +377,7 @@ public class AudioAnalyzer {
return PUID;
}
public AudioData getAudioData() {
public BasicMusicInfo getAudioData() {
return audioData;
}
@ -418,4 +400,12 @@ public class AudioAnalyzer {
public float getmAvg() {
return mAvg;
}
public synchronized AudioDataPackage getAudioDataPackage() {
if (pack != null) {
return pack;
} else {
throw new NullPointerException("Pack isn't filled yet... You made a mistake somewhere!");
}
}
}

View File

@ -0,0 +1,151 @@
package zero1hd.rhythmbullet.audio;
import java.security.InvalidParameterException;
import com.badlogic.gdx.utils.FloatArray;
public class AudioDataPackage {
private FloatArray bassPeaks;
private FloatArray mPeaks;
private FloatArray umPeaks;
private BasicMusicInfo musicInfo;
private float bassMaxVal, bassAvg;
private float mMaxVal, mAvg;
private float uMMaxval, uMAvg;
private int PUID;
private float secPerWin;
private float avgSPB;
/**
* Sets the bass data
* @param bassPeaks
* @param bassMaxVal
* @param bassAvg
*/
public void setBassData(FloatArray bassPeaks, float bassMaxVal, float bassAvg) {
if (bassPeaks != null) {
this.bassPeaks = bassPeaks;
this.bassMaxVal = bassMaxVal;
this.bassAvg = bassAvg;
} else {
throw new InvalidParameterException("The bass peaks of this audio pack has already been set.");
}
}
/**
* Sets the midrange data
* @param mPeaks
* @param mMaxVal
* @param mAvg
*/
public void setmPeaks(FloatArray mPeaks, float mMaxVal, float mAvg) {
if (mPeaks != null) {
throw new InvalidParameterException("The midrange peaks of this audio pack has already been set.");
}
this.mPeaks = mPeaks;
this.mMaxVal = mMaxVal;
this.mAvg = mAvg;
}
/**
* Sets the upper-midrange data
* @param umPeaks
* @param uMMaxVal
* @param uMAvg
*/
public void setUmPeaks(FloatArray umPeaks, float uMMaxVal, float uMAvg) {
if (umPeaks != null) {
throw new InvalidParameterException("The upper midrange peaks have already been set.");
}
this.umPeaks = umPeaks;
this.uMMaxval = uMMaxVal;
this.uMAvg = uMAvg;
}
public void setMusicInfo(BasicMusicInfo musicInfo) {
if (musicInfo != null) {
throw new InvalidParameterException("There is already music information in this package.");
}
this.musicInfo = musicInfo;
}
public void setPUID(int pUID) {
PUID = pUID;
}
public void setAvgSPB(float avgSPB) {
this.avgSPB = avgSPB;
}
public void setSecPerWin(float secPerWin) {
this.secPerWin = secPerWin;
}
//All the get methods...
public FloatArray getBassPeaks() {
if (bassPeaks != null) {
return bassPeaks;
} else {
throw new NullPointerException("Bass peaks currently null. This pack hasn't been properly packed!");
}
}
public FloatArray getmPeaks() {
if (mPeaks != null) {
return mPeaks;
} else {
throw new NullPointerException("midrange peaks currently null. This pack hasn't been properly packed!");
}
}
public FloatArray getuMPeaks() {
if (umPeaks != null) {
return umPeaks;
} else {
throw new NullPointerException("Upper midrange peaks currently null. This pack hasn't been properly packed!");
}
}
public BasicMusicInfo getMusicInfo() {
if (musicInfo == null) {
throw new NullPointerException("Music info hasn't been baked in...");
}
return musicInfo;
}
public float getBassMaxVal() {
return bassMaxVal;
}
public float getBassAvg() {
return bassAvg;
}
public float getmAvg() {
return mAvg;
}
public float getmMaxVal() {
return mMaxVal;
}
public float getuMMaxval() {
return uMMaxval;
}
public float getuMAvg() {
return uMAvg;
}
public int getPUID() {
return PUID;
}
public float getAvgSPB() {
return avgSPB;
}
public float getSecPerWin() {
return secPerWin;
}
}

View File

@ -1,9 +1,10 @@
package zero1hd.rhythmbullet.audio;
import com.badlogic.gdx.audio.Music;
import com.badlogic.gdx.utils.Disposable;
public interface AudioData extends Disposable {
public interface BasicMusicInfo extends Disposable {
/**
* sets a integer variable to the current window of audio data the playback is at.
* Useful for efficiency because we compute once for that frame then get the values everytime it is required instead of calculating every time we get the index.
@ -11,7 +12,7 @@ public interface AudioData extends Disposable {
public void readIndexUpdate();
/**
* Gets the current position in seconds
* Gets the current position in seconds s
* @return the current frame of audio.
*/
public int getReadIndex();
@ -41,7 +42,7 @@ public interface AudioData extends Disposable {
public int readSamples(float[] samples);
/**
* returns sample count
* returns sample count.
* Can be inaccurate.
* @return
*/

View File

@ -20,7 +20,7 @@ import javazoom.jl.decoder.Header;
import javazoom.jl.decoder.MP3Decoder;
import javazoom.jl.decoder.OutputBuffer;
public class Mp3AudioData implements AudioData {
public class Mp3AudioData implements BasicMusicInfo {
private int readWindowSize = 1024;
private Music playbackMusic;

View File

@ -11,7 +11,7 @@ import com.badlogic.gdx.files.FileHandle;
import zero1hd.wavedecoder.WavDecoder;
public class WavAudioData implements AudioData {
public class WavAudioData implements BasicMusicInfo {
private int readWindowSize = 1024;
private AudioFormat format;
int readIndex;
@ -70,7 +70,7 @@ public class WavAudioData implements AudioData {
@Override
public long getSampleCount() {
return decoder.getFrameCount();
return decoder.getFrameLength();
}
@Override

View File

@ -1,13 +1,13 @@
package zero1hd.rhythmbullet.audio.map;
import zero1hd.rhythmbullet.audio.AudioData;
import zero1hd.rhythmbullet.audio.BasicMusicInfo;
import zero1hd.rhythmbullet.entity.Entity;
import zero1hd.rhythmbullet.entity.EntityFrame;
import zero1hd.rhythmbullet.entity.coordinator.Coordinator;
import zero1hd.rhythmbullet.entity.coordinator.CoordinatorFrame;
public class GamePlayMap {
private AudioData musicData;
private BasicMusicInfo musicData;
private MapWindowData[] spawnList;
private boolean building;
private int index;
@ -17,7 +17,7 @@ public class GamePlayMap {
* GamePlayMap is what the game area will use to generate entities and judge current audio data
* @param audioData audio data
*/
public GamePlayMap(AudioData audioData, int totalWindows) {
public GamePlayMap(BasicMusicInfo audioData, int totalWindows) {
this.musicData = audioData;
spawnList = new MapWindowData[totalWindows];
hudType = new byte[totalWindows];
@ -68,7 +68,7 @@ public class GamePlayMap {
index = spawnList.length-1;
}
public AudioData getMusicData() {
public BasicMusicInfo getMusicData() {
return musicData;
}

View File

@ -6,7 +6,7 @@ import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.utils.FloatArray;
import zero1hd.rhythmbullet.RhythmBullet;
import zero1hd.rhythmbullet.audio.AudioAnalyzer;
import zero1hd.rhythmbullet.audio.AudioDataPackage;
import zero1hd.rhythmbullet.entity.EntityManager;
import zero1hd.rhythmbullet.entity.coordinator.CoordinatorManager;
import zero1hd.rhythmbullet.util.MiniEvents;
@ -34,29 +34,29 @@ public class RhythmMapAlgorithm implements Runnable {
private float windowPerSecond;
private volatile int progress;
public RhythmMapAlgorithm(EntityManager em, CoordinatorManager cm, AudioAnalyzer analyzer, float speedMod, float healthMod, float difficultyMod) {
public RhythmMapAlgorithm(EntityManager em, CoordinatorManager cm, AudioDataPackage adp, float speedMod, float healthMod, float difficultyMod) {
this.cm = cm;
this.em = em;
sender = new MiniSender();
bassPeaks = analyzer.getBassPeaks();
mPeaks = analyzer.getmPeaks();
umPeaks = analyzer.getUMPeaks();
map = new GamePlayMap(analyzer.getAudioData(), umPeaks.size);
rand = new MersenneTwister(analyzer.getPUID());
avgSPB = analyzer.getAvgSPB();
windowPerSecond = 1/analyzer.getsecondsPerWindow();
bassPeaks = adp.getBassPeaks();
mPeaks = adp.getmPeaks();
umPeaks = adp.getuMPeaks();
map = new GamePlayMap(adp.getMusicInfo(), umPeaks.size);
rand = new MersenneTwister(adp.getPUID());
avgSPB = adp.getAvgSPB();
windowPerSecond = 1/adp.getSecPerWin();
this.speedMod = speedMod;
this.healthMod = healthMod;
this.difficultyMod = difficultyMod;
umMax = analyzer.getUMMaxValue();
avgUM = analyzer.getUmAvg();
umMax = adp.getuMMaxval();
avgUM = adp.getuMAvg();
bassMax = analyzer.getBassMaxValue();
avgBass = analyzer.getBassAvg();
bassMax = adp.getBassMaxVal();
avgBass = adp.getBassAvg();
}

View File

@ -9,9 +9,9 @@ import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import zero1hd.rhythmbullet.RhythmBullet;
import zero1hd.rhythmbullet.ui.stages.CreativeHUD;
import zero1hd.rhythmbullet.ui.stages.GameHUD;
import zero1hd.rhythmbullet.ui.stages.GamePlayArea;
import zero1hd.rhythmbullet.stages.GamePlayArea;
import zero1hd.rhythmbullet.stages.ui.CreativeHUD;
import zero1hd.rhythmbullet.stages.ui.GameHUD;
public class CreativeScreen extends ScreenAdapter {
CreativeHUD chud;

View File

@ -13,10 +13,10 @@ import com.badlogic.gdx.scenes.scene2d.ui.ImageButton;
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
import zero1hd.rhythmbullet.RhythmBullet;
import zero1hd.rhythmbullet.audio.AudioData;
import zero1hd.rhythmbullet.audio.BasicMusicInfo;
import zero1hd.rhythmbullet.audio.map.GamePlayMap;
import zero1hd.rhythmbullet.ui.stages.GameHUD;
import zero1hd.rhythmbullet.ui.stages.GamePlayArea;
import zero1hd.rhythmbullet.stages.GamePlayArea;
import zero1hd.rhythmbullet.stages.ui.GameHUD;
public class GameScreen extends ScreenAdapter {
private GamePlayArea gameArea;
@ -26,7 +26,7 @@ public class GameScreen extends ScreenAdapter {
public RhythmBullet core;
private AudioData music;
private BasicMusicInfo music;
SpriteBatch bgBatch;
private ShaderProgram bgShader;

View File

@ -1,7 +1,6 @@
package zero1hd.rhythmbullet.screens;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.ScreenAdapter;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.math.Vector3;

View File

@ -1,4 +1,4 @@
package zero1hd.rhythmbullet.ui.stages;
package zero1hd.rhythmbullet.stages;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Preferences;

View File

@ -1,4 +1,4 @@
package zero1hd.rhythmbullet.ui.stages;
package zero1hd.rhythmbullet.stages.ui;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input.Keys;
@ -17,6 +17,7 @@ import zero1hd.rhythmbullet.RhythmBullet;
import zero1hd.rhythmbullet.audio.AudioAnalyzer;
import zero1hd.rhythmbullet.audio.map.RhythmMapAlgorithm;
import zero1hd.rhythmbullet.screens.MainMenu;
import zero1hd.rhythmbullet.stages.GamePlayArea;
import zero1hd.rhythmbullet.ui.windows.BassUMGraphWindow;
import zero1hd.rhythmbullet.ui.windows.BeatViewer;
import zero1hd.rhythmbullet.ui.windows.DifficultyWindow;
@ -225,7 +226,7 @@ public class CreativeHUD extends Stage implements MiniListener {
@Override
public void dispose() {
if (analyzer != null) {
analyzer.audioData.dispose();
analyzer.getAudioDataPackage().getMusicInfo().dispose();
}
super.dispose();
}
@ -255,7 +256,7 @@ public class CreativeHUD extends Stage implements MiniListener {
break;
case MUSIC_DATA_CLEANED:
if (analyzer != null && analyzer.isFinalized()) {
mapGen = new RhythmMapAlgorithm(gpa.em, gpa.cm, analyzer, diffWindow.getSpeedModifier(), diffWindow.getHealthModifier(), diffWindow.getSensitivityVal());
mapGen = new RhythmMapAlgorithm(gpa.em, gpa.cm, analyzer.getAudioDataPackage(), diffWindow.getSpeedModifier(), diffWindow.getHealthModifier(), diffWindow.getOverallDiffMod());
mapGen.getSender().addListener(this);
Thread mapGenThread = new Thread(mapGen);
mapGenThread.start();
@ -265,16 +266,16 @@ public class CreativeHUD extends Stage implements MiniListener {
Gdx.app.debug("creative", "successfully generated map.");
musicPlayBackControls.setAudiofile(analyzer.getAudioData());
volumeWindow.setMusic(analyzer.getAudioData());
beatViewer.setMusic(analyzer.getAudioData(), analyzer);
beatViewer.setMusic(analyzer.getAudioData(), analyzer.getAudioDataPackage());
ghud.setMusic(null);
bassUMgraphWindow.setData(analyzer.getBassPeaks(), analyzer.getUMPeaks(), analyzer.getAudioData());
bassUMgraphWindow.setData(analyzer.getAudioDataPackage().getBassPeaks(), analyzer.getAudioDataPackage().getuMPeaks(), analyzer.getAudioData());
bassUMgraphWindow.getGraph().avgG1 = analyzer.getBassAvg();
bassUMgraphWindow.getGraph().normalDataG1 = analyzer.getBassMaxValue();
bassUMgraphWindow.getGraph().avgG2 = analyzer.getUmAvg();
bassUMgraphWindow.getGraph().normalDataG2 = analyzer.getUMMaxValue();
mGraphWindow.setData(analyzer.getmPeaks(), null, analyzer.getAudioData());
mGraphWindow.setData(analyzer.getAudioDataPackage().getmPeaks(), null, analyzer.getAudioData());
mGraphWindow.getGraph().normalDataG1 = analyzer.getmMaxValue();
mGraphWindow.getGraph().avgG1 = analyzer.getmAvg();
gpa.setAudioMap(mapGen.getMap());

View File

@ -1,4 +1,4 @@
package zero1hd.rhythmbullet.ui.stages;
package zero1hd.rhythmbullet.stages.ui;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input.Keys;
@ -19,6 +19,7 @@ import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
import zero1hd.rhythmbullet.RhythmBullet;
import zero1hd.rhythmbullet.stages.GamePlayArea;
import zero1hd.rhythmbullet.ui.builders.HealthBar;
import zero1hd.rhythmbullet.ui.windows.FPSWindow;
import zero1hd.rhythmbullet.ui.windows.PauseMenu;

View File

@ -18,7 +18,7 @@ import com.badlogic.gdx.utils.Align;
import zero1hd.rhythmbullet.RhythmBullet;
import zero1hd.rhythmbullet.audio.AudioAnalyzer;
import zero1hd.rhythmbullet.audio.AudioData;
import zero1hd.rhythmbullet.audio.BasicMusicInfo;
import zero1hd.rhythmbullet.audio.AudioInfo;
import zero1hd.rhythmbullet.audio.map.GamePlayMap;
import zero1hd.rhythmbullet.audio.map.RhythmMapAlgorithm;
@ -31,11 +31,11 @@ public class AnalyzePage extends Page implements MiniListener {
private AnalyzePage ap = this;
AudioAnalyzer audioAnalyzer;
AudioData music;
BasicMusicInfo music;
RhythmMapAlgorithm mapGenAlgorithm;
private volatile Table songInfo;
private volatile Label[] info;
private Table songInfo;
private Label[] info;
Table difficultyTable;
private Label diffTitle;
@ -185,7 +185,7 @@ public class AnalyzePage extends Page implements MiniListener {
addActor(back);
}
public void setSong(AudioData music, AudioInfo audioInfo, MiniListener listener) {
public void setSong(BasicMusicInfo music, AudioInfo audioInfo, MiniListener listener) {
confirmed = false;
confirmDiffButton.setDisabled(false);
sensitivityRating.setDisabled(false);
@ -267,7 +267,7 @@ public class AnalyzePage extends Page implements MiniListener {
@Override
public void run() {
gameScreen = new GameScreen(core, core.getScreen());
mapGenAlgorithm = new RhythmMapAlgorithm(gameScreen.getGameArea().em, gameScreen.getGameArea().cm, audioAnalyzer, speedModifier.getValue(), healthModifier.getValue(), sensitivityRating.getValue());
mapGenAlgorithm = new RhythmMapAlgorithm(gameScreen.getGameArea().em, gameScreen.getGameArea().cm, audioAnalyzer.getAudioDataPackage(), speedModifier.getValue(), healthModifier.getValue(), sensitivityRating.getValue());
mapGenAlgorithm.getSender().addListener(ap);
mapGenThread = new Thread(mapGenAlgorithm);
mapGenThread.start();

View File

@ -4,12 +4,12 @@ import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.scenes.scene2d.ui.Window;
import com.badlogic.gdx.utils.FloatArray;
import zero1hd.rhythmbullet.audio.AudioData;
import zero1hd.rhythmbullet.audio.BasicMusicInfo;
import zero1hd.rhythmbullet.ui.builders.AudioGraph;
public class BassUMGraphWindow extends Window {
AudioGraph graph;
AudioData audioData;
BasicMusicInfo audioData;
public BassUMGraphWindow(String title, Skin skin) {
super(title, skin, "tinted");
@ -30,7 +30,7 @@ public class BassUMGraphWindow extends Window {
return graph;
}
public void setData(FloatArray dataSet1, FloatArray dataSet2, AudioData audioData) {
public void setData(FloatArray dataSet1, FloatArray dataSet2, BasicMusicInfo audioData) {
this.audioData = audioData;
graph.setGraphingData(dataSet1, dataSet2);
}

View File

@ -9,15 +9,15 @@ import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.scenes.scene2d.ui.WidgetGroup;
import com.badlogic.gdx.scenes.scene2d.ui.Window;
import zero1hd.rhythmbullet.audio.AudioAnalyzer;
import zero1hd.rhythmbullet.audio.AudioData;
import zero1hd.rhythmbullet.audio.AudioDataPackage;
import zero1hd.rhythmbullet.audio.BasicMusicInfo;
public class BeatViewer extends Window {
Pixmap lights;
int songIndex;
AudioData music;
BasicMusicInfo music;
Texture lightOn;
private AudioAnalyzer data;
private AudioDataPackage data;
public BeatViewer(String title, Skin skin) {
super(title, skin, "tinted");
@ -43,7 +43,7 @@ public class BeatViewer extends Window {
try {
if (music != null && data.getBassPeaks().get(songIndex) != 0) {
clearActions();
addAction(Actions.sequence(Actions.sizeTo(getWidth(), (data.getBassPeaks().get(songIndex)/data.getBassMaxValue())*bgBassBar.getHeight()), Actions.sizeTo(getWidth(), 0, 0.3f)));
addAction(Actions.sequence(Actions.sizeTo(getWidth(), (data.getBassPeaks().get(songIndex)/data.getBassMaxVal())*bgBassBar.getHeight()), Actions.sizeTo(getWidth(), 0, 0.3f)));
}
} catch (IndexOutOfBoundsException e) {
}
@ -63,9 +63,9 @@ public class BeatViewer extends Window {
@Override
public void act(float delta) {
try {
if (music != null && data.getUMPeaks().get(songIndex) != 0) {
if (music != null && data.getBassPeaks().get(songIndex) != 0) {
clearActions();
addAction(Actions.sequence(Actions.sizeTo(getWidth(), (data.getUMPeaks().get(songIndex)/data.getUMMaxValue())*bgUMBar.getHeight()), Actions.sizeTo(getWidth(), 0f, 0.3f)));
addAction(Actions.sequence(Actions.sizeTo(getWidth(), (data.getuMPeaks().get(songIndex)/data.getuMMaxval())*bgUMBar.getHeight()), Actions.sizeTo(getWidth(), 0f, 0.3f)));
}
} catch (IndexOutOfBoundsException e) {
@ -103,7 +103,7 @@ public class BeatViewer extends Window {
@Override
public void act(float delta) {
try {
if (music != null && data.getUMPeaks().get(songIndex) != 0) {
if (music != null && data.getuMPeaks().get(songIndex) != 0) {
clearActions();
addAction(Actions.sequence(Actions.alpha(1f), Actions.fadeOut(0.15f)));
}
@ -125,8 +125,8 @@ public class BeatViewer extends Window {
super.act(delta);
}
public void setMusic(AudioData audioData, AudioAnalyzer analyzer) {
public void setMusic(BasicMusicInfo audioData, AudioDataPackage adp) {
this.music = audioData;
this.data = analyzer;
this.data = adp;
}
}

View File

@ -63,7 +63,7 @@ public class DifficultyWindow extends Window {
pack();
}
public float getSensitivityVal() {
public float getOverallDiffMod() {
return sensitivityRating.getValue();
}

View File

@ -4,12 +4,12 @@ import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.scenes.scene2d.ui.Window;
import com.badlogic.gdx.utils.FloatArray;
import zero1hd.rhythmbullet.audio.AudioData;
import zero1hd.rhythmbullet.audio.BasicMusicInfo;
import zero1hd.rhythmbullet.ui.builders.AudioGraph;
public class MGraphWindow extends Window {
private AudioGraph graph;
private AudioData audioData;
private BasicMusicInfo audioData;
public MGraphWindow(String title, Skin skin) {
super(title, skin, "tinted");
@ -30,7 +30,7 @@ public class MGraphWindow extends Window {
return graph;
}
public void setData(FloatArray dataSet1, FloatArray dataSet2, AudioData audioData) {
public void setData(FloatArray dataSet1, FloatArray dataSet2, BasicMusicInfo audioData) {
this.audioData = audioData;
graph.setGraphingData(dataSet1, dataSet2);
}

View File

@ -15,13 +15,13 @@ import com.badlogic.gdx.scenes.scene2d.ui.Window;
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
import zero1hd.rhythmbullet.audio.AudioData;
import zero1hd.rhythmbullet.audio.BasicMusicInfo;
public class MusicController extends Window implements OnCompletionListener {
Skin skin;
private Image togglePlay;
private TextField info;
private AudioData audiofile;
private BasicMusicInfo audiofile;
public MusicController(final Skin skin) {
super("Playback Controller", skin, "tinted");
@ -110,7 +110,7 @@ public class MusicController extends Window implements OnCompletionListener {
setSize(260, 75);
}
public void setAudiofile(AudioData audiofile) {
public void setAudiofile(BasicMusicInfo audiofile) {
this.audiofile = audiofile;
if (audiofile == null) {
togglePlay.setDrawable(skin.getDrawable("loading"));
@ -125,7 +125,7 @@ public class MusicController extends Window implements OnCompletionListener {
}
}
public AudioData getAudiofile() {
public BasicMusicInfo getAudiofile() {
return audiofile;
}

View File

@ -12,7 +12,7 @@ import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
import com.badlogic.gdx.utils.Array;
import zero1hd.rhythmbullet.audio.Audio;
import zero1hd.rhythmbullet.audio.AudioData;
import zero1hd.rhythmbullet.audio.BasicMusicInfo;
import zero1hd.rhythmbullet.util.MiniEvents;
import zero1hd.rhythmbullet.util.MiniSender;
@ -95,7 +95,7 @@ public class MusicSelector extends Window {
return isBack;
}
public AudioData getSelectedMusic() {
public BasicMusicInfo getSelectedMusic() {
if (selectedMusic != null) {
return Audio.getAudioData(selectedMusic);
} else {

View File

@ -9,7 +9,7 @@ import com.badlogic.gdx.scenes.scene2d.ui.Slider;
import com.badlogic.gdx.scenes.scene2d.ui.Window;
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
import zero1hd.rhythmbullet.audio.AudioData;
import zero1hd.rhythmbullet.audio.BasicMusicInfo;
public class VolumeWindow extends Window {
@ -17,7 +17,7 @@ public class VolumeWindow extends Window {
private Slider musicVolSlider;
private Preferences prefs;
private AudioData music;
private BasicMusicInfo music;
public VolumeWindow(String title, Skin skin, Preferences prefs) {
super(title, skin, "tinted");
this.prefs = prefs;
@ -67,7 +67,7 @@ public class VolumeWindow extends Window {
prefs.flush();
}
public void setMusic(AudioData music) {
public void setMusic(BasicMusicInfo music) {
this.music = music;
if (music != null) {
music.getPlaybackMusic().setVolume(prefs.getFloat("music vol")/100f);

View File

@ -45,7 +45,7 @@ public class WavDecoder {
return audioInputStream.getFrameLength()/audioInputStream.getFormat().getFrameRate();
}
public long getFrameCount() {
public long getFrameLength() {
return audioInputStream.getFrameLength();
}