removed creative screen; re-organized analysis system; analysis page progress; problems with analysis system needs to be fixed

This commit is contained in:
Harrison Deng 2017-12-03 01:43:50 -06:00
parent 07cc783624
commit 7d0f3a365d
16 changed files with 640 additions and 1156 deletions

View File

View File

@ -1,358 +0,0 @@
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;
import edu.emory.mathcs.jtransforms.fft.FloatFFT_1D;
import zero1hd.rhythmbullet.util.MiniEvents;
import zero1hd.rhythmbullet.util.MiniSender;
public class AudioAnalyzer {
private boolean containsData;
private MusicManager musicInfo;
float[] audioPCM;
float[] spectrum;
float[] lastSpectrum;
private ExecutorService exec = Executors.newSingleThreadExecutor();
private Runnable analysisAlgorithm;
private Runnable thresholdCalculator;
int bassBinBegin;
int bassBinEnd;
private FloatArray bassSpectralFlux = new FloatArray();
private float bassMaxValue;
private float bassAvg;
float bassThresholdMultiplier;
int bassThresholdCalcRange;
int mBinBegin;
int mBinEnd;
private FloatArray mSpectralFlux = new FloatArray();
private float mMaxValue;
private float mAvg;
float mThresholdMultiplier;
int mThresholdCalcRange;
int umBinBegin;
int umBinEnd;
private FloatArray umSpectralFlux = new FloatArray();
private float umMaxValue;
private float umAvg;
float umThresholdMultiplier;
int umThresholdCalcRange;
public MiniSender sender;
private float avgSPB;
int PUID;
boolean work;
private int progress;
private float secondsPerWindow;
private AudioDataPackage pack;
public AudioAnalyzer(MusicManager audiofile) {
sender = new MiniSender();
analysisAlgorithm = () -> {
progress = 0;
int tasksDone = 0;
long totalTasks = musicInfo.getSampleCount()/musicInfo.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(musicInfo.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));
FloatFFT_1D fft = new FloatFFT_1D(musicInfo.getReadWindowSize());
int seedDigit = 0;
while (musicInfo.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 ++;
}
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 = () -> {
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);
}
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 = musicInfo.getReadWindowSize()/musicInfo.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.setmData(mPeaks, mMaxValue, mAvg);
pack.setUmData(umPeaks, umMaxValue, umAvg);
pack.setPUID(PUID);
pack.setAvgSPB(avgSPB);
pack.setSecPerWin(secondsPerWindow);
pack.setMusicInfo(musicInfo);
if (work) {
Gdx.app.debug("Audio Analyzer", "data cleaned and ready for map gen.");
sender.send(MiniEvents.MUSIC_DATA_CLEANED);
}
};
audioPCM = new float[audiofile.getReadWindowSize()];
spectrum = new float[(audiofile.getReadWindowSize()/2)+1];
lastSpectrum = new float[(audiofile.getReadWindowSize()/2)+1];
this.musicInfo = audiofile;
work = true;
exec.submit(analysisAlgorithm);
}
public void runThresholdCleaning(float rangeModifier) {
this.bassThresholdMultiplier -= rangeModifier;
this.umThresholdMultiplier -= rangeModifier;
work = true;
if (containsData) {
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() {
work = true;
if (containsData) {
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) {
return (int) (durationOfRange/(musicInfo.getReadWindowSize()/musicInfo.getSampleRate()));
}
public boolean containsData() {
return containsData;
}
public synchronized int getProgress() {
return progress;
}
public void stop() {
work = false;
exec.shutdown();
}
public synchronized AudioDataPackage getAudioDataPackage() {
if (pack != null) {
exec.shutdown();
return pack;
} else {
throw new NullPointerException("Pack isn't filled yet... You made a mistake somewhere!");
}
}
}

View File

@ -45,6 +45,11 @@ public class MusicList extends Observable {
setChanged(); setChanged();
} }
/**
* creates an audio manager for the given music file.
* @param file
* @return a music manager of the given music file.
*/
public MusicManager getAudioData(FileHandle file) { public MusicManager getAudioData(FileHandle file) {
if (file.extension().equalsIgnoreCase("wav")) { if (file.extension().equalsIgnoreCase("wav")) {
return new WAVManager(file); return new WAVManager(file);

View File

@ -0,0 +1,50 @@
package zero1hd.rhythmbullet.audio.analyzer;
import java.util.Observable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import com.badlogic.gdx.utils.Disposable;
import zero1hd.rhythmbullet.audio.MusicManager;
public class AudioAnalyzer extends Observable implements Disposable {
private ExecutorService exec;
private SpectralFluxAnalysisRunnable sfar;
private ThresholdCalcRunnable tcr;
private PruneFluxRunnable pfr;
private PeakDetectionRunnable pdr;
public AudioAnalyzer(MusicManager musicManager) {
exec = Executors.newSingleThreadExecutor();
sfar = new SpectralFluxAnalysisRunnable(musicManager);
tcr = new ThresholdCalcRunnable(sfar);
pfr = new PruneFluxRunnable(tcr);
pdr = new PeakDetectionRunnable(pfr, sfar.getPUID());
}
public void start() {
exec.submit(sfar);
exec.submit(tcr);
exec.submit(pfr);
exec.submit(pdr);
}
public void stop() {
sfar.work = false;
tcr.work = false;
pfr.work = false;
pdr.work = false;
}
@Override
public void dispose() {
stop();
exec.shutdown();
}
public boolean isDone() {
return (sfar.isDone() && tcr.isDone() && pfr.isDone() && pdr.isDone());
}
}

View File

@ -0,0 +1,123 @@
package zero1hd.rhythmbullet.audio.analyzer;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.utils.FloatArray;
import zero1hd.rhythmbullet.audio.AudioDataPackage;
import zero1hd.rhythmbullet.audio.MusicManager;
public class PeakDetectionRunnable implements Runnable {
boolean work, done;
private FloatArray bassPrunned;
private FloatArray mPrunned;
private FloatArray umPrunned;
private FloatArray bassPeaks = new FloatArray();
private FloatArray mPeaks = new FloatArray();
private FloatArray umPeaks = new FloatArray();
private float bassMaxValue;
private float mMaxValue;
private float umMaxValue;
private float secondsPerWindow;
private float mAvg;
private float bassAvg;
private float umAvg;
private MusicManager musicManager;
private AudioDataPackage pack;
private int PUID;
public PeakDetectionRunnable(PruneFluxRunnable pfr, int PUID) {
bassPrunned = pfr.getBassPrunned();
mPrunned = pfr.getmPrunned();
umPrunned = pfr.getUmPrunned();
musicManager = pfr.getMusicManager();
this.PUID = PUID;
}
@Override
public void run() {
int lastID = 0;
float bassBeats = 0;
float mBeats = 0;
float umBeats = 0;
float 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++;
}
}
secondsPerWindow = musicManager.getReadWindowSize()/musicManager.getSampleRate();
//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.setmData(mPeaks, mMaxValue, mAvg);
pack.setUmData(umPeaks, umMaxValue, umAvg);
pack.setPUID(PUID);
pack.setAvgSPB(avgSPB);
pack.setSecPerWin(secondsPerWindow);
pack.setMusicInfo(musicManager);
if (work) {
Gdx.app.debug("Audio Analyzer", "data cleaned and ready for map gen.");
}
}
public AudioDataPackage getPack() {
return pack;
}
public boolean isDone() {
return done;
}
}

View File

@ -0,0 +1,96 @@
package zero1hd.rhythmbullet.audio.analyzer;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.utils.FloatArray;
import zero1hd.rhythmbullet.audio.MusicManager;
public class PruneFluxRunnable implements Runnable {
boolean work;
private boolean done;
private FloatArray bassSpectralFlux;
private FloatArray mSpectralFlux;
private FloatArray umSpectralFlux;
private FloatArray bassThreshold, mThreshold, umThreshold;
private FloatArray bassPrunned = new FloatArray();
private FloatArray mPrunned = new FloatArray();
private FloatArray umPrunned = new FloatArray();
private MusicManager musicManager;
public PruneFluxRunnable(ThresholdCalcRunnable tcr) {
bassSpectralFlux = tcr.getBassSpectralFlux();
mSpectralFlux = tcr.getmSpectralFlux();
umSpectralFlux = tcr.getUmSpectralFlux();
bassThreshold = tcr.getBassThreshold();
umThreshold = tcr.getUmThreshold();
mThreshold = tcr.getmThreshold();
this.musicManager = tcr.getMusicManager();
}
@Override
public void run() {
//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);
}
}
done = true;
Gdx.app.debug("Audio Analyzer", "Data prunned.");
}
public FloatArray getBassSpectralFlux() {
return bassSpectralFlux;
}
public FloatArray getmSpectralFlux() {
return mSpectralFlux;
}
public FloatArray getBassThreshold() {
return bassThreshold;
}
public FloatArray getmThreshold() {
return mThreshold;
}
public FloatArray getUmSpectralFlux() {
return umSpectralFlux;
}
public FloatArray getUmThreshold() {
return umThreshold;
}
public FloatArray getBassPrunned() {
return bassPrunned;
}
public FloatArray getmPrunned() {
return mPrunned;
}
public FloatArray getUmPrunned() {
return umPrunned;
}
public boolean isDone() {
return done;
}
public MusicManager getMusicManager() {
return musicManager;
}
}

View File

@ -0,0 +1,140 @@
package zero1hd.rhythmbullet.audio.analyzer;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.utils.FloatArray;
import edu.emory.mathcs.jtransforms.fft.FloatFFT_1D;
import zero1hd.rhythmbullet.audio.MusicManager;
public class SpectralFluxAnalysisRunnable implements Runnable {
boolean work;
private boolean done;
private FloatArray bassSpectralFlux = new FloatArray();
private FloatArray mSpectralFlux = new FloatArray();
private FloatArray umSpectralFlux = new FloatArray();
MusicManager musicManager;
private int PUID;
private int progress;
public SpectralFluxAnalysisRunnable(MusicManager mm) {
this.musicManager = mm;
}
@Override
public void run() {
progress = 0;
int tasksDone = 0;
long totalTasks = musicManager.getSampleCount()/musicManager.getReadWindowSize();
float[] audioPCM = new float[musicManager.getReadWindowSize()];
float[] spectrum = new float[(musicManager.getReadWindowSize()/2)+1];
float[] lastSpectrum = new float[(musicManager.getReadWindowSize()/2)+1];
int bassBinBegin = 0;
int bassBinEnd = 12;
int mBinBegin = 50;
int mBinEnd = 250;
int umBinBegin = 350;
int umBinEnd = 513;
Gdx.app.debug("Analyzing Song", musicManager.getBasicSongName());
Gdx.app.debug("Read freq", String.valueOf(musicManager.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));
FloatFFT_1D fft = new FloatFFT_1D(musicManager.getReadWindowSize());
int seedDigit = 0;
while (musicManager.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 ++;
}
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);
}
if (work) {
Gdx.app.debug("Audio Analyzer", "Done getting spectral flux.");
Gdx.app.debug("Audio Analyzer", "window count: " + bassSpectralFlux.size);
done = true;
Gdx.app.debug("Audio Analyzer", "USING SEED: " + PUID);
progress = 100;
}
}
public synchronized int getProgress() {
return progress;
}
public FloatArray getBassSpectralFlux() {
return bassSpectralFlux;
}
public FloatArray getmSpectralFlux() {
return mSpectralFlux;
}
public FloatArray getUmSpectralFlux() {
return umSpectralFlux;
}
public int getPUID() {
return PUID;
}
public boolean isDone() {
return done;
}
public boolean isWorking() {
return work;
}
public void setWork(boolean work) {
this.work = work;
}
public MusicManager getMusicManager() {
return musicManager;
}
}

View File

@ -0,0 +1,102 @@
package zero1hd.rhythmbullet.audio.analyzer;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.utils.FloatArray;
import zero1hd.rhythmbullet.audio.MusicManager;
public class ThresholdCalcRunnable implements Runnable {
boolean work;
private boolean done;
private MusicManager musicManager;
private FloatArray bassSpectralFlux;
private FloatArray mSpectralFlux;
private FloatArray umSpectralFlux;
private FloatArray bassThreshold = new FloatArray();
private FloatArray mThreshold = new FloatArray();
private FloatArray umThreshold = new FloatArray();
public ThresholdCalcRunnable(SpectralFluxAnalysisRunnable sfar) {
this.bassSpectralFlux = sfar.getBassSpectralFlux();
this.mSpectralFlux = sfar.getmSpectralFlux();
this.umSpectralFlux = sfar.getUmSpectralFlux();
this.musicManager = sfar.getMusicManager();
}
@Override
public void run() {
Gdx.app.debug("Audio Analyzer", "beginning threshold calc.");
float bassThresholdMultiplier = 1.5f;
float mThresholdMultiplier = 1.4f;
float umThresholdMultiplier = 1.4f;
int bassThresholdCalcRange = thresholdRangeCalc(0.27f);
int mThresholdCalcRange = thresholdRangeCalc(0.4f);
int umThresholdCalcRange = thresholdRangeCalc(0.4f);
//threshold calculation
for (int i = 0; i < umSpectralFlux.size && work; i++) {
int start = Math.max(0, i - bassThresholdCalcRange/2);
int end = Math.min(umSpectralFlux.size - 1, i + bassThresholdCalcRange/2);
float average = 0;
for (int j = start; j <= end; j++) {
average += bassSpectralFlux.get(j);
}
average /= (end - start);
bassThreshold.add(average * bassThresholdMultiplier);
start = Math.max(0, i - mThresholdCalcRange/2);
end = Math.min(umSpectralFlux.size - 1, i + mThresholdCalcRange/2);
average = 0;
for (int j = start; j <= end; j++) {
average+= mSpectralFlux.get(j);
}
average /= (end - start);
mThreshold.add(average*mThresholdMultiplier);
start = Math.max(0, i - umThresholdCalcRange/2);
end = Math.min(umSpectralFlux.size - 1, i + umThresholdCalcRange/2);
average = 0;
for (int j = start; j <= end; j++) {
average+= umSpectralFlux.get(j);
}
average /= (end - start);
umThreshold.add(average*umThresholdMultiplier);
}
done = true;
Gdx.app.debug("Audio Analyzer", "Threshold calculated.");
}
private int thresholdRangeCalc(float durationOfRange) {
return (int) (durationOfRange/(musicManager.getReadWindowSize()/musicManager.getSampleRate()));
}
public boolean isDone() {
return done;
}
public FloatArray getBassSpectralFlux() {
return bassSpectralFlux;
}
public FloatArray getmSpectralFlux() {
return mSpectralFlux;
}
public FloatArray getUmSpectralFlux() {
return umSpectralFlux;
}
public FloatArray getBassThreshold() {
return bassThreshold;
}
public FloatArray getmThreshold() {
return mThreshold;
}
public FloatArray getUmThreshold() {
return umThreshold;
}
public MusicManager getMusicManager() {
return musicManager;
}
}

View File

@ -0,0 +1,109 @@
package zero1hd.rhythmbullet.graphics.ui.pages;
import java.util.Observable;
import java.util.Observer;
import com.badlogic.gdx.assets.AssetManager;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.ui.Label;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.scenes.scene2d.ui.Slider;
import com.badlogic.gdx.scenes.scene2d.ui.Table;
import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
import zero1hd.rhythmbullet.audio.MusicManager;
import zero1hd.rhythmbullet.audio.analyzer.AudioAnalyzer;
public class AnalysisPage extends Page implements Observer {
private boolean confirmed;
private volatile AudioAnalyzer aa;
private Table table;
private Label difficultyModLabel, healthModLabel, speedModLabel;
private Slider difficultyModifierSlider, healthModifierSlider, speedModifierSlider;
private Label diffModPercentLabel, heltModPercentLabel, speeModPercentLabel;
private Label progressLabel;
private TextButton confirmButton;
public AnalysisPage(Skin skin, AssetManager assets) {
setTextureBackground(assets.get("gradients.atlas", TextureAtlas.class).findRegion("red-round"));
table = new Table();
table.setFillParent(true);
table.defaults().space(10f);
addActor(table);
difficultyModLabel = new Label("Difficulty Modifier: ", skin, "sub-font", skin.getColor("default"));
difficultyModifierSlider = new Slider(1, 3, 0.5f, false, skin);
diffModPercentLabel = new Label(String.valueOf(difficultyModifierSlider.getValue()) + "x", skin);
difficultyModifierSlider.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
diffModPercentLabel.setText(String.valueOf(difficultyModifierSlider.getValue()) + "x");
}
});
table.add(difficultyModLabel);
table.add(difficultyModifierSlider).minWidth(0.5f*getWidth());
table.add(diffModPercentLabel).minWidth(diffModPercentLabel.getWidth()*1.5f);
table.row();
healthModLabel = new Label("Health Modifier: ", skin, "sub-font", skin.getColor("default"));
healthModifierSlider = new Slider(1f, 3f, 0.5f, false, skin);
heltModPercentLabel = new Label(String.valueOf(healthModifierSlider.getValue()) + "x", skin);
healthModifierSlider.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
heltModPercentLabel.setText(String.valueOf(healthModifierSlider.getValue()) + "x");
}
});
table.add(healthModLabel);
table.add(healthModifierSlider).fillX();
table.add(heltModPercentLabel).fillX();
table.row();
speedModLabel = new Label("Speed Modifier: ", skin, "sub-font", skin.getColor("default"));
speedModifierSlider = new Slider(1, 3, 0.5f, false, skin);
speeModPercentLabel = new Label(String.valueOf(speedModifierSlider.getValue()) + "x", skin);
speedModifierSlider.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
speeModPercentLabel.setText(String.valueOf(speedModifierSlider.getValue()) + "x");
}
});
table.add(speedModLabel);
table.add(speedModifierSlider).fillX();
table.add(speeModPercentLabel).fillX();
table.row();
confirmButton = new TextButton("Confirm", skin);
confirmButton.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
confirmed = true;
confirmButton.setDisabled(true);
}
});
table.add(confirmButton);
table.row().colspan(3).fillX();
progressLabel = new Label("Loading... ", skin);
table.add(progressLabel).colspan(2).left().spaceTop(20f);
}
public void processSong(MusicManager mm) {
aa = new AudioAnalyzer(mm);
aa.addObserver(this);
aa.start();
}
@Override
public void update(Observable arg0, Object arg1) {
if (arg0 == aa) {
}
}
@Override
public void act(float delta) {
if (aa != null && aa.isDone() && confirmed) {
//TODO GAMESCREEN!!!
}
super.act(delta);
}
}

View File

@ -1,323 +0,0 @@
package zero1hd.rhythmbullet.graphics.ui.pages;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.math.Interpolation;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.actions.Actions;
import com.badlogic.gdx.scenes.scene2d.ui.Image;
import com.badlogic.gdx.scenes.scene2d.ui.Label;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.scenes.scene2d.ui.Slider;
import com.badlogic.gdx.scenes.scene2d.ui.Table;
import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
import com.badlogic.gdx.utils.Align;
import com.badlogic.gdx.utils.Disposable;
import zero1hd.rhythmbullet.RhythmBullet;
import zero1hd.rhythmbullet.audio.AudioAnalyzer;
import zero1hd.rhythmbullet.audio.MusicManager;
import zero1hd.rhythmbullet.audio.SongInfo;
import zero1hd.rhythmbullet.audio.map.GamePlayMap;
import zero1hd.rhythmbullet.audio.map.RhythmMapAlgorithm;
import zero1hd.rhythmbullet.graphics.ui.components.ScrollText;
import zero1hd.rhythmbullet.screens.GameScreen;
import zero1hd.rhythmbullet.util.MiniEvents;
import zero1hd.rhythmbullet.util.MiniListener;
public class AnalyzePage extends Page implements MiniListener, Disposable {
private AnalyzePage ap = this;
AudioAnalyzer audioAnalyzer;
MusicManager music;
RhythmMapAlgorithm mapGenAlgorithm;
private Table songInfo;
private Label[] info;
Table difficultyTable;
private Label diffTitle;
private Slider sensitivityRating;
private Label sensitivityRatingTitle;
private Slider speedModifier;
private Label speedModifierTitle;
private Slider healthModifier;
private Label healthModifierTitle;
private TextButton confirmDiffButton;
private boolean confirmed;
private Skin skin;
private Table beginTable;
private TextButton beginButton;
private TextButton back;
private Image loadingCircle;
private long startTime, endTime;
private Thread mapGenThread;
private GameScreen gameScreen;
private RhythmBullet core;
public AnalyzePage(RhythmBullet core) {
super("Results", core.getDefaultSkin());
this.skin = core.getDefaultSkin();
this.core = core;
songInfo = new Table(skin);
songInfo.align(Align.top);
songInfo.pad(15f);
songInfo.setBackground(skin.getDrawable("large-pane"));
addActor(songInfo);
difficultyTable = new Table(skin);
difficultyTable.setBackground(skin.getDrawable("large-pane"));
addActor(difficultyTable);
diffTitle = new Label("Difficulty", skin);
difficultyTable.add(diffTitle).expandX().left();
difficultyTable.row();
sensitivityRating = new Slider(0f, 1f, 0.01f, false, skin);
sensitivityRating.setValue(0f);
sensitivityRating.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
sensitivityRatingTitle.setText("Base Difficulty: " + MathUtils.round(sensitivityRating.getValue()*100) + "%");
}
});
sensitivityRatingTitle = new Label("Base Difficulty: " + sensitivityRating.getValue(), skin, "sub-font", skin.getColor("default"));
difficultyTable.add(sensitivityRatingTitle);
difficultyTable.row();
difficultyTable.add(sensitivityRating).fillX();
difficultyTable.row();
speedModifier = new Slider(1f, 3f, 0.25f, false, skin);
speedModifier.setValue(1f);
speedModifier.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
speedModifierTitle.setText("Speed Modifier: x" + speedModifier.getValue());
}
});
speedModifierTitle = new Label("Speed Modifier: x" + speedModifier.getValue(), skin, "sub-font", skin.getColor("default"));
difficultyTable.add(speedModifierTitle);
difficultyTable.row();
difficultyTable.add(speedModifier).fillX();
difficultyTable.row();
healthModifier = new Slider(0f, 5f, 1f, false, skin);
healthModifier.setValue(0f);
healthModifier.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
healthModifierTitle.setText("Health modifier: +" + healthModifier.getValue());
}
});
healthModifierTitle = new Label("Health modifier: +" + healthModifier.getValue(), skin, "sub-font", skin.getColor("default"));
difficultyTable.add(healthModifierTitle);
difficultyTable.row();
difficultyTable.add(healthModifier).fillX().spaceBottom(15f);
difficultyTable.row();
confirmDiffButton = new TextButton("Confirm", skin);
confirmDiffButton.setDisabled(true);
confirmDiffButton.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
info[2].setText("Confirmed.");
confirmed = true;
confirmDiffButton.setDisabled(true);
sensitivityRating.setDisabled(true);
speedModifier.setDisabled(true);
healthModifier.setDisabled(true);
if (audioAnalyzer.containsData() ) {
finalizeData();
}
}
});
difficultyTable.add(confirmDiffButton);
difficultyTable.pack();
beginTable = new Table(skin);
beginTable.pad(15f);
beginButton = new TextButton("Begin", skin);
beginTable.add(beginButton);
beginTable.setBackground(skin.getDrawable("large-pane"));
beginTable.pack();
addActor(beginTable);
loadingCircle = new Image(core.getAssetManager().get("cybercircle1.png", Texture.class));
loadingCircle.setPosition((getWidth()-loadingCircle.getWidth())/2, (getHeightBelowTitle()-loadingCircle.getHeight())/2);
loadingCircle.setColor(0.8f,0.8f,0.8f,0.7f);
loadingCircle.setOrigin(loadingCircle.getWidth()/2, loadingCircle.getHeight()/2);
loadingCircle.addAction(Actions.forever(Actions.rotateBy(-360f, 4f)));
addActor(loadingCircle);
loadingCircle.toBack();
back = new TextButton("Back", skin);
back.setPosition(getWidth()-back.getWidth()-15f, getHeightBelowTitle());
back.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
miniSender.send(MiniEvents.BACK);
if (audioAnalyzer != null) {
audioAnalyzer.stop();
}
}
});
info = new Label[6];
for (int i = 0; i < info.length; i++) {
info[i] = new Label(null, skin, "sub-font", skin.getColor("default"));
}
addActor(back);
}
public void setSong(MusicManager music, SongInfo audioInfo, MiniListener listener) {
confirmed = false;
confirmDiffButton.setDisabled(false);
sensitivityRating.setDisabled(false);
speedModifier.setDisabled(false);
healthModifier.setDisabled(false);
songInfo.clear();
songInfo.defaults().align(Align.left | Align.top);
this.music = music;
audioAnalyzer = new AudioAnalyzer(music);
audioAnalyzer.sender.addListener(this);
songInfo.add(new ScrollText(audioInfo.getMusicName(), null, skin, true, false)).expandX().fillX().spaceBottom(20f);
for (int i = 0; i < info.length; i++) {
info[i].setColor(1f, 1f, 1f, 0f);
info[i].setText(null);
songInfo.row();
songInfo.add(info[i]);
}
songInfo.pack();
songInfo.setWidth(getWidth()/2f);
songInfo.setPosition((getWidth()-songInfo.getWidth())/2f, (getHeightBelowTitle()-songInfo.getHeight())/2f);
difficultyTable.setPosition(songInfo.getX(), -difficultyTable.getHeight());
difficultyTable.setWidth(songInfo.getWidth());
beginTable.setPosition(difficultyTable.getX(), -beginTable.getHeight());
beginTable.setWidth(difficultyTable.getWidth());
startTime = System.currentTimeMillis();
info[0].addAction(Actions.color(Color.BLACK, 2.5f));
}
@Override
public void act(float delta) {
super.act(delta);
}
public boolean hasAudioData() {
if (music != null) {
return true;
} else {
return false;
}
}
public void clearAudioData() {
music = null;
}
@Override
public synchronized void handle(MiniEvents ID) {
switch (ID) {
case ANALYZER_ITERATED:
if (audioAnalyzer.getProgress() == 50) {
songInfo.addAction(Actions.moveTo(songInfo.getX(), getHeight()/2f, 0.75f, Interpolation.linear));
difficultyTable.addAction(Actions.moveTo(songInfo.getX(), getHeight()/2f-difficultyTable.getHeight()-10,0.8f, Interpolation.linear));
info[2].setText("Awaiting confirmation...");
info[2].addAction(Actions.color(Color.BLACK, 0.75f));
confirmDiffButton.setDisabled(false);
}
info[0].setText("Initial analysis: " + audioAnalyzer.getProgress() + "%");
break;
case SPECTRAL_FLUX_DONE:
endTime = System.currentTimeMillis();
info[1].setText("Done. Analyze time: " + ((endTime - startTime)/1000f) + "s");
info[1].addAction(Actions.color(Color.BLACK, 0.75f));
if (confirmed) {
finalizeData();
}
break;
case MUSIC_DATA_CLEANED:
info[3].setText("data cleaning done.");
info[4].addAction(Actions.color(Color.BLACK, 0.75f));
Gdx.app.postRunnable(new Runnable() {
@Override
public void run() {
gameScreen = new GameScreen(core, core.getScreen());
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();
}
});
startTime = System.currentTimeMillis();
break;
case MAPGEN_ITERATED:
info[4].setText("Generating map: " + mapGenAlgorithm.getProgress() + "%");
break;
case MAP_GENERATED:
endTime = System.currentTimeMillis();
info[5].setText("Done. Generation time: " + ((endTime - startTime)/1000f) + "s");
beginButton.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
gameScreen.setGamePlayMap(mapGenAlgorithm.getMap());
core.setScreen(gameScreen);
miniSender.send(MiniEvents.BACK);
}
});
info[5].addAction(Actions.color(Color.BLACK, 0.75f));
songInfo.addAction(Actions.moveTo(songInfo.getX(), getHeight()-songInfo.getHeight()-10, 0.55f, Interpolation.linear));
difficultyTable.addAction(Actions.sequence(Actions.delay(0.3f), Actions.moveTo(songInfo.getX(), getHeight()-songInfo.getHeight()-10-difficultyTable.getHeight()-5f,0.8f, Interpolation.linear)));
beginTable.addAction(Actions.sequence(Actions.delay(0.5f), Actions.moveTo(difficultyTable.getX(), getHeight()-songInfo.getHeight()-10-difficultyTable.getHeight()-beginTable.getHeight()-10f,0.8f, Interpolation.linear)));
default:
break;
}
}
private void finalizeData() {
Gdx.app.debug("analyze", "confirmed data finalization.");
audioAnalyzer.runThresholdCleaning();
info[3].setText("finalizing data...");
info[3].addAction(Actions.color(Color.BLACK, 0.75f));
}
public GamePlayMap getMap() {
return mapGenAlgorithm.getMap();
}
@Override
public void dispose() {
if (audioAnalyzer != null) {
audioAnalyzer.stop();
audioAnalyzer = null;
}
}
}

View File

@ -23,7 +23,6 @@ import com.badlogic.gdx.scenes.scene2d.ui.ScrollPane;
import com.badlogic.gdx.scenes.scene2d.ui.Skin; import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.scenes.scene2d.ui.Table; import com.badlogic.gdx.scenes.scene2d.ui.Table;
import com.badlogic.gdx.scenes.scene2d.ui.TextButton; import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
import com.badlogic.gdx.scenes.scene2d.ui.VerticalGroup;
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener; import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable; import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable;
import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.Array;
@ -64,7 +63,7 @@ public class MusicSelectionPage extends Page implements Observer {
private TextButton beginButton; private TextButton beginButton;
private float scrollTimer, scrollDelay = 0.2f, scrollDelMod, songSelectionTimer; private float scrollTimer, scrollDelay = 0.2f, scrollDelMod, songSelectionTimer;
public MusicSelectionPage(Skin skin, MusicListController musicList, AssetManager assetManager, Vector3 cameraTarget) { public MusicSelectionPage(Skin skin, MusicListController musicList, AssetManager assetManager, Vector3 cameraTarget, AnalysisPage ap) {
setTextureBackground(assetManager.get("gradients.atlas", TextureAtlas.class).findRegion("red-round")); setTextureBackground(assetManager.get("gradients.atlas", TextureAtlas.class).findRegion("red-round"));
this.skin = skin; this.skin = skin;
this.mc = musicList; this.mc = musicList;
@ -130,6 +129,13 @@ public class MusicSelectionPage extends Page implements Observer {
ratedDifficulty = new Label(null, skin, "sub-font", skin.getColor("default")); ratedDifficulty = new Label(null, skin, "sub-font", skin.getColor("default"));
albumCover = new Image(assetManager.get("defaultCover.png", Texture.class)); albumCover = new Image(assetManager.get("defaultCover.png", Texture.class));
beginButton = new TextButton("Begin", skin); beginButton = new TextButton("Begin", skin);
beginButton.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
cameraTarget.x = 2.5f*getWidth();
ap.processSong(mc.getMusicList().getAudioData(getSelectedMusic()));
}
});
} }
@Override @Override

View File

@ -1,14 +1,11 @@
package zero1hd.rhythmbullet.graphics.ui.pages; package zero1hd.rhythmbullet.graphics.ui.pages;
import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.graphics.g2d.TextureAtlas; import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.Preferences; import com.badlogic.gdx.Preferences;
import com.badlogic.gdx.math.MathUtils; import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.math.Vector3; import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.scenes.scene2d.Actor; import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.InputListener;
import com.badlogic.gdx.scenes.scene2d.ui.Label; import com.badlogic.gdx.scenes.scene2d.ui.Label;
import com.badlogic.gdx.scenes.scene2d.ui.ProgressBar; import com.badlogic.gdx.scenes.scene2d.ui.ProgressBar;
import com.badlogic.gdx.scenes.scene2d.ui.Slider; import com.badlogic.gdx.scenes.scene2d.ui.Slider;
@ -19,8 +16,6 @@ import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
import zero1hd.rhythmbullet.RhythmBullet; import zero1hd.rhythmbullet.RhythmBullet;
import zero1hd.rhythmbullet.audio.MusicListController; import zero1hd.rhythmbullet.audio.MusicListController;
import zero1hd.rhythmbullet.screens.CreativeScreen;
import zero1hd.rhythmbullet.screens.MainMenu;
public class OptionsPage extends Page { public class OptionsPage extends Page {
Table optionsTable; Table optionsTable;
@ -117,13 +112,6 @@ public class OptionsPage extends Page {
optionsTable.row(); optionsTable.row();
Label debugCodeLabel = new Label("Debug Code: ", core.getDefaultSkin());
optionsTable.add(debugCodeLabel);
final TextField debugCodeField = new TextField(null, core.getDefaultSkin());
optionsTable.add(debugCodeField).fillX();
optionsTable.row();
TextButton keybindSettings = new TextButton("Set Controls", core.getDefaultSkin()); TextButton keybindSettings = new TextButton("Set Controls", core.getDefaultSkin());
keybindSettings.addListener(new ChangeListener() { keybindSettings.addListener(new ChangeListener() {
@Override @Override
@ -143,19 +131,6 @@ public class OptionsPage extends Page {
} }
}); });
optionsTable.add(graphicsSettings).colspan(2).fillX(); optionsTable.add(graphicsSettings).colspan(2).fillX();
addListener(new InputListener() {
@Override
public boolean keyUp(InputEvent event, int keycode) {
if (keycode == Keys.ENTER) {
Gdx.app.debug("Debug Field", debugCodeField.getText());
if (debugCodeField.getText().equals("creative")) {
Gdx.app.debug("Debug Field", "going to creative test room...");
core.setScreen(new CreativeScreen(core, (MainMenu) core.getScreen(), sc.getMusicList()));
}
}
return super.keyUp(event, keycode);
}
});
optionsTable.row(); optionsTable.row();

View File

@ -1,46 +0,0 @@
package zero1hd.rhythmbullet.screens;
import com.badlogic.gdx.Preferences;
import zero1hd.rhythmbullet.RhythmBullet;
import zero1hd.rhythmbullet.audio.MusicList;
import zero1hd.rhythmbullet.stages.CreativeHUD;
public class CreativeScreen extends GameScreen {
CreativeHUD chud;
Preferences prefs;
public CreativeScreen(RhythmBullet core, MainMenu mainMenu, MusicList sl) {
super(core, mainMenu);
chud = new CreativeHUD(core, mainMenu, gameArea, gameHUD, sl);
inputs.addProcessor(chud);
this.prefs = core.getPrefs();
}
@Override
public void show() {
super.show();
}
@Override
public void render(float delta) {
super.render(delta);
chud.getViewport().apply();
chud.act();
chud.draw();
}
@Override
public void resize(int width, int height) {
super.resize(width, height);
}
@Override
public void dispose() {
dispose();
super.dispose();
}
}

View File

@ -21,6 +21,7 @@ import com.badlogic.gdx.utils.viewport.ScreenViewport;
import zero1hd.rhythmbullet.RhythmBullet; import zero1hd.rhythmbullet.RhythmBullet;
import zero1hd.rhythmbullet.audio.MusicList; import zero1hd.rhythmbullet.audio.MusicList;
import zero1hd.rhythmbullet.audio.MusicListController; import zero1hd.rhythmbullet.audio.MusicListController;
import zero1hd.rhythmbullet.graphics.ui.pages.AnalysisPage;
import zero1hd.rhythmbullet.graphics.ui.pages.CreditsPage; import zero1hd.rhythmbullet.graphics.ui.pages.CreditsPage;
import zero1hd.rhythmbullet.graphics.ui.pages.KeybindOptionsPage; import zero1hd.rhythmbullet.graphics.ui.pages.KeybindOptionsPage;
import zero1hd.rhythmbullet.graphics.ui.pages.MainPage; import zero1hd.rhythmbullet.graphics.ui.pages.MainPage;
@ -39,7 +40,7 @@ public class MainMenu extends ScreenAdapter implements TransitionAdapter {
private KeybindOptionsPage keybindPage; private KeybindOptionsPage keybindPage;
private VideoOptionsPage graphicsPage; private VideoOptionsPage graphicsPage;
private MusicSelectionPage musicSelectionPage; private MusicSelectionPage musicSelectionPage;
private AnalysisPage analysisPage;
private RhythmBullet core; private RhythmBullet core;
private MusicListController mlc; private MusicListController mlc;
@ -99,10 +100,13 @@ public class MainMenu extends ScreenAdapter implements TransitionAdapter {
creditsPage.setPosition(0, Gdx.graphics.getHeight()); creditsPage.setPosition(0, Gdx.graphics.getHeight());
stage.addActor(creditsPage); stage.addActor(creditsPage);
musicSelectionPage = new MusicSelectionPage(core.getDefaultSkin(), mlc, core.getAssetManager(), cameraPosition); analysisPage = new AnalysisPage(core.getDefaultSkin(),core.getAssetManager());
analysisPage.setPosition(2*Gdx.graphics.getWidth(), 0f);
stage.addActor(analysisPage);
musicSelectionPage = new MusicSelectionPage(core.getDefaultSkin(), mlc, core.getAssetManager(), cameraPosition, analysisPage);
musicSelectionPage.setPosition(1f*Gdx.graphics.getWidth(), 0f); musicSelectionPage.setPosition(1f*Gdx.graphics.getWidth(), 0f);
stage.addActor(musicSelectionPage); stage.addActor(musicSelectionPage);
stage.addListener(new InputListener() { stage.addListener(new InputListener() {
@Override @Override
public boolean keyUp(InputEvent event, int keycode) { public boolean keyUp(InputEvent event, int keycode) {

View File

@ -1,111 +0,0 @@
package zero1hd.rhythmbullet.screens;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.ScreenAdapter;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.utils.viewport.ScreenViewport;
import zero1hd.rhythmbullet.RhythmBullet;
import zero1hd.rhythmbullet.audio.MusicListController;
import zero1hd.rhythmbullet.graphics.ui.pages.AnalyzePage;
import zero1hd.rhythmbullet.graphics.ui.pages.MusicSelectionPage;
import zero1hd.rhythmbullet.util.MiniEvents;
import zero1hd.rhythmbullet.util.MiniListener;
import zero1hd.rhythmbullet.util.TransitionAdapter;
@Deprecated
public class PreGameScreen extends ScreenAdapter implements TransitionAdapter, MiniListener {
Stage stage;
MusicSelectionPage ms;
public AnalyzePage ap;
private Vector3 cameraPos;
private RhythmBullet core;
private MusicListController songListController;
public PreGameScreen(RhythmBullet core, MusicListController songList) {
stage = new Stage(new ScreenViewport());
cameraPos = new Vector3(stage.getCamera().position);
this.core = core;
this.songListController = songList;
postTransition();
}
@Override
public void render(float delta) {
Gdx.gl.glClearColor(0f, 0f, 0f, 1f);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
stage.getViewport().apply();
try {
stage.act();
stage.draw();
} catch (NullPointerException e) {
e.printStackTrace();
}
if (stage.getCamera().position.x != cameraPos.x) {
stage.getCamera().position.lerp(cameraPos, 0.25f);
}
super.render(delta);
}
@Override
public void resize(int width, int height) {
stage.getViewport().update(width, height, true);
cameraPos.set(stage.getCamera().position);
super.resize(width, height);
}
@Override
public void handle(MiniEvents ID) {
switch (ID) {
case MUSIC_SELECTED:
cameraPos.x = 1.5f*Gdx.graphics.getWidth();
ap.setSong(songListController.getMusicList().getAudioData(ms.getSelectedMusic()), ms.getSelectedMusicInfo(), this);
break;
case BACK:
if (cameraPos.x == 1.5f*Gdx.graphics.getWidth()) {
cameraPos.x = 0.5f*Gdx.graphics.getWidth();
} else {
core.setScreen(new MainMenu(core));
}
break;
default:
break;
}
}
@Override
public void preTransition() {
stage.clear();
ap.dispose();
ms.dispose();
}
@Override
public void postTransition() {
ms = new MusicSelectionPage(core.getDefaultSkin(), songListController, core.getAssetManager(), cameraPos);
ms.miniSender.addListener(this);
stage.addActor(ms);
ap = new AnalyzePage(core);
ap.miniSender.addListener(this);
ap.setPosition(Gdx.graphics.getWidth(), 0);
stage.addActor(ap);
}
@Override
public void show() {
Gdx.input.setInputProcessor(stage);
super.show();
}
@Override
public void dispose() {
stage.dispose();
super.dispose();
}
}

View File

@ -1,288 +0,0 @@
package zero1hd.rhythmbullet.stages;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.InputListener;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.ui.CheckBox;
import com.badlogic.gdx.scenes.scene2d.ui.ScrollPane;
import com.badlogic.gdx.scenes.scene2d.ui.Table;
import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
import com.badlogic.gdx.scenes.scene2d.ui.Window;
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
import zero1hd.rhythmbullet.RhythmBullet;
import zero1hd.rhythmbullet.audio.AudioAnalyzer;
import zero1hd.rhythmbullet.audio.AudioDataPackage;
import zero1hd.rhythmbullet.audio.MusicList;
import zero1hd.rhythmbullet.audio.map.RhythmMapAlgorithm;
import zero1hd.rhythmbullet.graphics.ui.components.AudioGraph;
import zero1hd.rhythmbullet.graphics.ui.windows.BeatViewer;
import zero1hd.rhythmbullet.graphics.ui.windows.DifficultyWindow;
import zero1hd.rhythmbullet.graphics.ui.windows.FPSWindow;
import zero1hd.rhythmbullet.graphics.ui.windows.MusicController;
import zero1hd.rhythmbullet.graphics.ui.windows.MusicSelector;
import zero1hd.rhythmbullet.graphics.ui.windows.SpawnerWindow;
import zero1hd.rhythmbullet.graphics.ui.windows.VolumeWindow;
import zero1hd.rhythmbullet.screens.MainMenu;
import zero1hd.rhythmbullet.util.MiniEvents;
import zero1hd.rhythmbullet.util.MiniListener;
public class CreativeHUD extends Stage implements MiniListener {
MusicController musicPlayBackControls;
MusicSelector musicSelector;
FPSWindow fpsViewer;
BeatViewer beatViewer;
AudioGraph bassUMgraphWindow;
AudioGraph mGraphWindow;
VolumeWindow volumeWindow;
SpawnerWindow spawnerWindow;
DifficultyWindow diffWindow;
AudioAnalyzer analyzer;
RhythmMapAlgorithm mapGen;
Window toolbox;
GamePlayArea gpa;
GameHUD ghud;
public CreativeHUD(final RhythmBullet core, final MainMenu mainMenu, final GamePlayArea gpa, GameHUD ghud, MusicList sl) {
this.gpa = gpa;
this.ghud = ghud;
musicSelector = new MusicSelector("Select Audio File", core.getDefaultSkin(), core.getPrefs().getString("music dir"), sl);
musicSelector.miniSender.addListener(this);
musicSelector.refresh();
fpsViewer = new FPSWindow("FPS", core.getDefaultSkin());
beatViewer = new BeatViewer("Beat", core.getDefaultSkin());
bassUMgraphWindow = new AudioGraph(512, 256);
bassUMgraphWindow.setPosition(getWidth() - bassUMgraphWindow.getWidth(), 0);
mGraphWindow = new AudioGraph(512, 256);
mGraphWindow.setPosition(getWidth() - mGraphWindow.getWidth(), bassUMgraphWindow.getHeight());
volumeWindow = new VolumeWindow("Volume adjustments", core.getDefaultSkin(), core.getPrefs());
spawnerWindow = new SpawnerWindow("Spawn Tool", core.getDefaultSkin(), gpa.em, gpa.cm, gpa);
diffWindow = new DifficultyWindow(core.getDefaultSkin());
toolbox = new Window("Tools", core.getDefaultSkin(), "tinted");
toolbox.defaults().pad(5f);
Table toolboxToolSet = new Table(core.getDefaultSkin());
toolboxToolSet.defaults().space(5f).left();
//Back button
TextButton backButton = new TextButton("Back", core.getDefaultSkin(), "window");
backButton.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
dispose();
core.setScreen(mainMenu);
}
});
toolboxToolSet.add(backButton);
toolboxToolSet.row();
final CheckBox musicSelectorCheckbox = new CheckBox(" Music selector", core.getDefaultSkin());
musicSelectorCheckbox.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
if (musicSelectorCheckbox.isChecked()) {
addActor(musicSelector);
} else {
musicSelector.remove();
}
}
});
toolboxToolSet.add(musicSelectorCheckbox);
toolboxToolSet.row();
musicPlayBackControls = new MusicController(core.getDefaultSkin());
final CheckBox musicPlayBackCheckbox = new CheckBox(" Playback controls", core.getDefaultSkin());
musicPlayBackCheckbox.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
if (musicPlayBackCheckbox.isChecked()) {
addActor(musicPlayBackControls);
} else {
musicPlayBackControls.remove();
}
}
});
toolboxToolSet.add(musicPlayBackCheckbox);
toolboxToolSet.row();
final CheckBox beatViewerCheckbox = new CheckBox(" Beat viewer", core.getDefaultSkin());
beatViewerCheckbox.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
if (beatViewerCheckbox.isChecked()) {
addActor(beatViewer);
} else {
beatViewer.remove();
}
}
});
toolboxToolSet.add(beatViewerCheckbox);
toolboxToolSet.row();
final CheckBox fpsViewerCheckbox = new CheckBox(" FPS", core.getDefaultSkin());
fpsViewerCheckbox.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
if (fpsViewerCheckbox.isChecked()) {
addActor(fpsViewer);
} else {
fpsViewer.remove();
}
}
});
toolboxToolSet.add(fpsViewerCheckbox);
toolboxToolSet.row();
final CheckBox peakGraphCheckbox = new CheckBox(" Peak Graphs", core.getDefaultSkin());
peakGraphCheckbox.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
if (peakGraphCheckbox.isChecked()) {
addActor(bassUMgraphWindow);
addActor(mGraphWindow);
} else {
bassUMgraphWindow.remove();
mGraphWindow.remove();
}
}
});
toolboxToolSet.add(peakGraphCheckbox);
toolboxToolSet.row();
final CheckBox volumeMixerCheckbox = new CheckBox(" Volume", core.getDefaultSkin());
volumeMixerCheckbox.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
if (volumeMixerCheckbox.isChecked()) {
addActor(volumeWindow);
} else {
volumeWindow.remove();
}
}
});
toolboxToolSet.add(volumeMixerCheckbox);
toolboxToolSet.row();
final CheckBox spawnToolCheckBox = new CheckBox(" Spawn Tool", core.getDefaultSkin());
spawnToolCheckBox.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
if (spawnToolCheckBox.isChecked()) {
addActor(spawnerWindow);
} else {
spawnerWindow.remove();
}
}
});
toolboxToolSet.add(spawnToolCheckBox);
toolboxToolSet.row();
final CheckBox diffAdjusterCheckBox = new CheckBox(" Difficulty", core.getDefaultSkin());
diffAdjusterCheckBox.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
if (diffAdjusterCheckBox.isChecked()) {
addActor(diffWindow);
} else {
diffWindow.remove();
}
}
});
toolboxToolSet.add(diffAdjusterCheckBox);
ScrollPane scroller = new ScrollPane(toolboxToolSet, core.getDefaultSkin());
toolbox.add(scroller).height(250f).width(150f);
addActor(toolbox);
addListener(new InputListener() {
@Override
public boolean keyUp(InputEvent event, int keycode) {
if (keycode == Keys.ENTER || keycode == Keys.ESCAPE) {
setKeyboardFocus(null);
}
return super.keyUp(event, keycode);
}
});
toolbox.pack();
}
@Override
public void act(float delta) {
super.act(delta);
}
@Override
public void dispose() {
if (analyzer != null) {
analyzer.getAudioDataPackage().getMusicInfo().dispose();
}
super.dispose();
}
@Override
public void handle(MiniEvents ID) {
switch (ID) {
case BACK:
break;
case MUSIC_SELECTED:
beatViewer.setMusic(null, null);
volumeWindow.setMusic(null);
bassUMgraphWindow.setGraphingData(null, null, null);
mGraphWindow.setGraphingData(null, null, null);
if (musicPlayBackControls.getAudiofile() != null) {
musicPlayBackControls.getAudiofile().dispose();
}
musicPlayBackControls.setAudiofile(null);
analyzer = new AudioAnalyzer(musicSelector.getSelectedMusic());
analyzer.sender.addListener(this);
ghud.setMusic(null);
break;
case SPECTRAL_FLUX_DONE:
analyzer.runThresholdCleaning();
break;
case MUSIC_DATA_CLEANED:
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();
break;
case MAP_GENERATED:
Gdx.app.debug("creative", "successfully generated map.");
AudioDataPackage adp = analyzer.getAudioDataPackage();
musicPlayBackControls.setAudiofile(adp.getMusicInfo());
volumeWindow.setMusic(adp.getMusicInfo());
beatViewer.setMusic(adp.getMusicInfo(), analyzer.getAudioDataPackage());
bassUMgraphWindow.setGraphingData(analyzer.getAudioDataPackage().getBassPeaks(), analyzer.getAudioDataPackage().getuMPeaks(), adp.getMusicInfo());
bassUMgraphWindow.avgG1 = adp.getBassAvg();
bassUMgraphWindow.normalDataG1 = adp.getBassMaxVal();
bassUMgraphWindow.avgG2 = adp.getuMAvg();
bassUMgraphWindow.normalDataG2 = adp.getuMMaxval();
mGraphWindow.setGraphingData(analyzer.getAudioDataPackage().getmPeaks(), null, adp.getMusicInfo());
mGraphWindow.normalDataG1 = adp.getmMaxVal();
mGraphWindow.avgG1 = adp.getmAvg();
gpa.setAudioMap(mapGen.getMap());
ghud.setMusic(adp.getMusicInfo());
break;
default:
break;
}
}
}