From db27f7dbae871171e58b16d7c50e036c945c8672 Mon Sep 17 00:00:00 2001 From: Recrown Date: Sun, 30 Jul 2017 18:22:24 -0500 Subject: [PATCH] added another frequency range on analyzer --- .../zero1hd/polyjet/audio/AudioAnalyzer.java | 150 ++++++++++++------ .../polyjet/audio/map/RhythmMapAlgorithm.java | 19 +-- .../polyjet/ui/builders/AudioGraph.java | 35 ++-- .../polyjet/ui/stages/CreativeHUD.java | 37 +++-- ...raphWindow.java => BassUMGraphWindow.java} | 6 +- .../polyjet/ui/windows/MGraphWindow.java | 37 +++++ 6 files changed, 196 insertions(+), 88 deletions(-) rename core/src/zero1hd/polyjet/ui/windows/{GraphWindow.java => BassUMGraphWindow.java} (83%) create mode 100755 core/src/zero1hd/polyjet/ui/windows/MGraphWindow.java diff --git a/core/src/zero1hd/polyjet/audio/AudioAnalyzer.java b/core/src/zero1hd/polyjet/audio/AudioAnalyzer.java index 8661b8f..ae568b9 100755 --- a/core/src/zero1hd/polyjet/audio/AudioAnalyzer.java +++ b/core/src/zero1hd/polyjet/audio/AudioAnalyzer.java @@ -28,23 +28,32 @@ public class AudioAnalyzer { private FloatArray bassPeaks = new FloatArray(); private float bassMaxValue; private float bassAvg; - - int UMBinBegin; - int UMBinEnd; + float bassThresholdMultiplier; + int bassThresholdCalcRange; + + 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; + int mThresholdCalcRange; + + 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 umMaxValue; private float umAvg; - - private FloatArray overlappedPeaks = new FloatArray(); - - float bassThresholdMultiplier; float umThresholdMultiplier; - int UMThresholdCalcRange; - int bassThresholdCalcRange; - + int umThresholdCalcRange; + + public volatile MiniSender sender; private float avgSPB; @@ -65,22 +74,28 @@ public class AudioAnalyzer { int totalTasks = audioData.getSampleCount()/audioData.getReadWindowSize(); bassThresholdMultiplier = 1.5f; + mThresholdMultiplier = 1.4f; umThresholdMultiplier = 1.4f; - bassBinBegin = 1; - bassBinEnd = 13; + bassBinBegin = 0; + bassBinEnd = 12; - UMBinBegin = 14; - UMBinEnd = 513; + mBinBegin = 100; + mBinEnd = 250; + + umBinBegin = 350; + umBinEnd = 513; bassThresholdCalcRange = thresholdRangeCalc(0.27f); - UMThresholdCalcRange = thresholdRangeCalc(0.4f); + mThresholdCalcRange = thresholdRangeCalc(0.4f); + umThresholdCalcRange = thresholdRangeCalc(0.4f); Gdx.app.debug("Read freq", String.valueOf(audioData.getFormat().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("Using following bin ranges", "\nBass freq begin: " + bassBinBegin + "\nBass freq end: " + bassBinEnd + "\nMain freq begin: " + umBinBegin + "\nMain freq end: " + umBinEnd); - Gdx.app.debug("Threshold Calc Range UM", String.valueOf(UMThresholdCalcRange)); + 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()); @@ -106,7 +121,7 @@ public class AudioAnalyzer { System.arraycopy(spectrum, 0, lastSpectrum, 0, spectrum.length); System.arraycopy(audioPCM, 0, spectrum, 0, spectrum.length); - float fluxVal = 0; + float fluxVal; //bass detection fluxVal = 0; for (int i = bassBinBegin; i < bassBinEnd && work; i++) { @@ -115,9 +130,17 @@ public class AudioAnalyzer { } bassSpectralFlux.add(fluxVal); - //main detection + //m detection fluxVal = 0; - for (int i = UMBinBegin; i < UMBinEnd && work; i++) { + 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]); } @@ -141,27 +164,31 @@ public class AudioAnalyzer { 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 UMStart = Math.max(0, i - UMThresholdCalcRange/2); - int UMEnd = Math.min(umSpectralFlux.size - 1, i + UMThresholdCalcRange/2); - - int bassStart = Math.max(0, i - bassThresholdCalcRange/2); - int bassEnd = Math.min(umSpectralFlux.size - 1, i + bassThresholdCalcRange/2); + int start = Math.max(0, i - umThresholdCalcRange/2); + int end = Math.min(umSpectralFlux.size - 1, i + umThresholdCalcRange/2); float average = 0; - for (int j = bassStart; j <= bassEnd; j++) { + for (int j = start; j <= end; j++) { average += bassSpectralFlux.get(j); } - average /= (bassEnd - bassStart); + average /= (end - start); bassThreshold.add(average * bassThresholdMultiplier); average = 0; - for (int j = UMStart; j <= UMEnd; j++) { + 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 /= (UMEnd - UMStart); + average /= (end - start); umThreshold.add(average*umThresholdMultiplier); } @@ -172,22 +199,25 @@ public class AudioAnalyzer { 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 = umSpectralFlux.get(i) - umThreshold.get(i); + 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."); @@ -196,6 +226,7 @@ public class AudioAnalyzer { int lastID = 0; float bassBeats = 0; + float mBeats = 0; float umBeats = 0; avgSPB = -1f; for (int i = 0; i < umPrunned.size-1 && work; i++) { @@ -204,18 +235,17 @@ public class AudioAnalyzer { bassMaxValue = bassPeaks.get(i); } - umPeaks.add((umPrunned.get(i) > umPrunned.get(i+1) ? umPrunned.get(i) : 0f)); - if (umPeaks.get(i) > UMMaxValue) { - UMMaxValue = umPeaks.get(i); + mPeaks.add((mPrunned.get(i) > mPrunned.get(i+1) ? mPrunned.get(i) : 0f)); + if (mPeaks.get(i) > mMaxValue) { + mMaxValue = mPeaks.get(i); } - //overlapping beats - if (bassPeaks.get(i) != 0 && umPeaks.get(i) != 0) { - overlappedPeaks.add((bassPeaks.get(i)+umPeaks.get(i))/2f); - } else { - overlappedPeaks.add(0); + 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) { @@ -232,6 +262,12 @@ public class AudioAnalyzer { bassBeats++; } + + if (mPeaks.get(i) != 0) { + mAvg += mPeaks.get(i); + mBeats++; + } + if (umPeaks.get(i) != 0) { umAvg += umPeaks.get(i); umBeats++; @@ -246,13 +282,13 @@ public class AudioAnalyzer { 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) { - Gdx.app.debug("Audio Analyzer", "overlapped beats checked."); - finalized = true; sender.send(MiniEvents.MUSIC_DATA_CLEANED); @@ -268,12 +304,15 @@ public class AudioAnalyzer { bassPrunned.shrink(); bassPeaks.shrink(); + mSpectralFlux.shrink(); + mThreshold.shrink(); + mPrunned.shrink(); + mPeaks.shrink(); + umSpectralFlux.shrink(); umThreshold.shrink(); umPrunned.shrink(); umPeaks.shrink(); - - overlappedPeaks.shrink(); } public void startAnalyticalThread(AudioData audiofile) { @@ -302,6 +341,9 @@ public class AudioAnalyzer { public FloatArray getBassPeaks() { return bassPeaks; } + public FloatArray getmPeaks() { + return mPeaks; + } public FloatArray getUMPeaks() { return umPeaks; } @@ -314,8 +356,12 @@ public class AudioAnalyzer { return bassMaxValue; } + public float getmMaxValue() { + return mMaxValue; + } + public float getUMMaxValue() { - return UMMaxValue; + return umMaxValue; } public int getReadIndex() { @@ -346,10 +392,6 @@ public class AudioAnalyzer { return PUID; } - public FloatArray getOverlappedPeaks() { - return overlappedPeaks; - } - public AudioData getAudioData() { return audioData; } @@ -369,4 +411,8 @@ public class AudioAnalyzer { public float getUmAvg() { return umAvg; } + + public float getmAvg() { + return mAvg; + } } diff --git a/core/src/zero1hd/polyjet/audio/map/RhythmMapAlgorithm.java b/core/src/zero1hd/polyjet/audio/map/RhythmMapAlgorithm.java index ca01e07..ccbf84d 100755 --- a/core/src/zero1hd/polyjet/audio/map/RhythmMapAlgorithm.java +++ b/core/src/zero1hd/polyjet/audio/map/RhythmMapAlgorithm.java @@ -15,8 +15,8 @@ public class RhythmMapAlgorithm implements Runnable { private MiniSender sender; private FloatArray bassPeaks; - private FloatArray UMPeaks; - private FloatArray overlappedPeaks; + private FloatArray mPeaks; + private FloatArray umPeaks; private MersenneTwister rand; private GamePlayMap map; @@ -34,9 +34,9 @@ public class RhythmMapAlgorithm implements Runnable { sender = new MiniSender(); bassPeaks = analyzer.getBassPeaks(); - UMPeaks = analyzer.getUMPeaks(); - overlappedPeaks = analyzer.getOverlappedPeaks(); - map = new GamePlayMap(analyzer.getAudioData(), UMPeaks.size); + 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(); @@ -58,7 +58,7 @@ public class RhythmMapAlgorithm implements Runnable { public void run() { map.beginBuild(); for (int index = 0; index < bassPeaks.size; index++) { - if (bassPeaks.get(index) != 0 || UMPeaks.get(index) != 0) { + if (bassPeaks.get(index) != 0 || umPeaks.get(index) != 0) { if (bassPeaks.get(index) != 0) { //If there is a value of some sorts that is not zero, we generate some beat for the map if (index > 1.5*windowPerSecond && bassPeaks.get(index) > avgBass) { @@ -80,8 +80,8 @@ public class RhythmMapAlgorithm implements Runnable { } } - if (UMPeaks.get(index) != 0) { - if (UMPeaks.get(index) >= avgUM) { + if (umPeaks.get(index) != 0) { + if (umPeaks.get(index) >= avgUM) { //If upper midrange peaks are greater than average, the: int spawnLocations = (Main.GAME_AREA_WIDTH-8)/8; @@ -101,9 +101,6 @@ public class RhythmMapAlgorithm implements Runnable { } } - if (overlappedPeaks.get(index) != 0) { - - } if (rand.nextFloat() < 0.15f) { switch(rand.nextInt(10)) { diff --git a/core/src/zero1hd/polyjet/ui/builders/AudioGraph.java b/core/src/zero1hd/polyjet/ui/builders/AudioGraph.java index 7426b78..60304af 100755 --- a/core/src/zero1hd/polyjet/ui/builders/AudioGraph.java +++ b/core/src/zero1hd/polyjet/ui/builders/AudioGraph.java @@ -40,6 +40,25 @@ public class AudioGraph extends Actor { public void act(float delta) { audioGraph.setColor(0f, 0f, 0f, 0.75f); audioGraph.fill(); + if (overlayGraph != null) { + if (Gdx.input.isKeyPressed(Keys.COMMA)) { + if (scale > 0.05f) { + scale -= 0.25f; + } + } else if (Gdx.input.isKeyPressed(Keys.PERIOD)) { + if (scale < audioGraph.getHeight()*2f) { + scale += 0.4f; + } + } + if (Gdx.input.isKeyJustPressed(Keys.M)) { + displayMode++; + if (displayMode != 3) { + Gdx.app.debug("Graph", "Switching to another graph."); + } else { + displayMode = 0; + } + } + } if (Gdx.input.isKeyPressed(Keys.COMMA)) { if (scale > 0.05f) { @@ -49,17 +68,10 @@ public class AudioGraph extends Actor { if (scale < audioGraph.getHeight()*2f) { scale += 0.4f; } - } - if (Gdx.input.isKeyJustPressed(Keys.M)) { - displayMode++; - if (displayMode != 3) { - Gdx.app.debug("Graph", "Switching to another graph."); - } else { - displayMode = 0; - } } else if (Gdx.input.isKeyJustPressed(Keys.SLASH)) { scale = audioGraph.getHeight(); } + switch (displayMode) { case 0: audioGraph.setColor(1f, 0f, 0f, 0.75f); @@ -93,8 +105,6 @@ public class AudioGraph extends Actor { break; } - - audioGraph.setColor(0f, 1f, 0f, 0.95f); audioGraph.drawLine(audioGraph.getWidth()/2, 0, audioGraph.getWidth()/2, audioGraph.getHeight()); @@ -111,6 +121,11 @@ public class AudioGraph extends Actor { public void setGraphingData(FloatArray dataSet1, FloatArray dataSet2) { this.mainGraph = dataSet1; this.overlayGraph = dataSet2; + if (dataSet2 == null) { + displayMode = 2; + } else { + displayMode = 0; + } } } diff --git a/core/src/zero1hd/polyjet/ui/stages/CreativeHUD.java b/core/src/zero1hd/polyjet/ui/stages/CreativeHUD.java index 16b6b88..f6b4316 100755 --- a/core/src/zero1hd/polyjet/ui/stages/CreativeHUD.java +++ b/core/src/zero1hd/polyjet/ui/stages/CreativeHUD.java @@ -20,7 +20,8 @@ import zero1hd.polyjet.screens.MainMenu; import zero1hd.polyjet.ui.windows.BeatViewer; import zero1hd.polyjet.ui.windows.DifficultyWindow; import zero1hd.polyjet.ui.windows.FPSWindow; -import zero1hd.polyjet.ui.windows.GraphWindow; +import zero1hd.polyjet.ui.windows.MGraphWindow; +import zero1hd.polyjet.ui.windows.BassUMGraphWindow; import zero1hd.polyjet.ui.windows.MusicController; import zero1hd.polyjet.ui.windows.MusicSelector; import zero1hd.polyjet.ui.windows.SpawnerWindow; @@ -33,7 +34,8 @@ public class CreativeHUD extends Stage implements MiniListener { MusicSelector musicSelector; FPSWindow fpsViewer; BeatViewer beatViewer; - GraphWindow graphViewer; + BassUMGraphWindow bassUMgraphWindow; + MGraphWindow mGraphWindow; VolumeWindow volumeWindow; SpawnerWindow spawnerWindow; DifficultyWindow diffWindow; @@ -51,7 +53,8 @@ public class CreativeHUD extends Stage implements MiniListener { fpsViewer = new FPSWindow("FPS", core.getDefaultSkin()); beatViewer = new BeatViewer("Beat", core.getDefaultSkin()); - graphViewer = new GraphWindow("Peak Values", core.getDefaultSkin()); + bassUMgraphWindow = new BassUMGraphWindow("Bass/UM Peak Values", core.getDefaultSkin()); + mGraphWindow = new MGraphWindow("Midrange Peak Values", core.getDefaultSkin()); volumeWindow = new VolumeWindow("Volume adjustments", core.getDefaultSkin(), core.getPrefs()); spawnerWindow = new SpawnerWindow("Spawn Tool", core.getDefaultSkin(), gpa.ec, gpa); diffWindow = new DifficultyWindow(core.getDefaultSkin()); @@ -137,14 +140,16 @@ public class CreativeHUD extends Stage implements MiniListener { toolboxToolSet.add(fpsViewerCheckbox); toolboxToolSet.row(); - final CheckBox peakGraphCheckbox = new CheckBox(" Peak Graph", core.getDefaultSkin()); + 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(graphViewer); + addActor(bassUMgraphWindow); + addActor(mGraphWindow); } else { - graphViewer.remove(); + bassUMgraphWindow.remove(); + mGraphWindow.remove(); } } @@ -208,6 +213,8 @@ public class CreativeHUD extends Stage implements MiniListener { return super.keyUp(event, keycode); } }); + toolboxToolSet.pack(); + toolbox.pack(); } @Override @@ -232,7 +239,8 @@ public class CreativeHUD extends Stage implements MiniListener { case MUSIC_SELECTED: beatViewer.setMusic(null, null); volumeWindow.setMusic(null); - graphViewer.setData(null, null, null); + bassUMgraphWindow.setData(null, null, null); + mGraphWindow.setData(null, null, null); if (musicPlayBackControls.getAudiofile() != null) { musicPlayBackControls.getAudiofile().dispose(); } @@ -258,11 +266,16 @@ public class CreativeHUD extends Stage implements MiniListener { musicPlayBackControls.setAudiofile(analyzer.getAudioData()); volumeWindow.setMusic(analyzer.getAudioData()); beatViewer.setMusic(analyzer.getAudioData(), analyzer); - graphViewer.setData(analyzer.getBassPeaks(), analyzer.getUMPeaks(), analyzer.getAudioData()); - graphViewer.getGraph().avgG1 = analyzer.getBassAvg(); - graphViewer.getGraph().normalDataG1 = analyzer.getBassMaxValue(); - graphViewer.getGraph().avgG2 = analyzer.getUmAvg(); - graphViewer.getGraph().normalDataG2 = analyzer.getUMMaxValue(); + + bassUMgraphWindow.setData(analyzer.getBassPeaks(), analyzer.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.getGraph().normalDataG1 = analyzer.getmMaxValue(); + mGraphWindow.getGraph().avgG1 = analyzer.getmAvg(); gpa.setAudioMap(mapGen.getMap()); break; default: diff --git a/core/src/zero1hd/polyjet/ui/windows/GraphWindow.java b/core/src/zero1hd/polyjet/ui/windows/BassUMGraphWindow.java similarity index 83% rename from core/src/zero1hd/polyjet/ui/windows/GraphWindow.java rename to core/src/zero1hd/polyjet/ui/windows/BassUMGraphWindow.java index 95c1bc8..ef0b3b1 100755 --- a/core/src/zero1hd/polyjet/ui/windows/GraphWindow.java +++ b/core/src/zero1hd/polyjet/ui/windows/BassUMGraphWindow.java @@ -7,15 +7,15 @@ import com.badlogic.gdx.utils.FloatArray; import zero1hd.polyjet.audio.AudioData; import zero1hd.polyjet.ui.builders.AudioGraph; -public class GraphWindow extends Window { +public class BassUMGraphWindow extends Window { AudioGraph graph; AudioData audioData; - public GraphWindow(String title, Skin skin) { + public BassUMGraphWindow(String title, Skin skin) { super(title, skin, "tinted"); graph = new AudioGraph(300, 150); add(graph); - setSize(305, 155); + pack(); } @Override diff --git a/core/src/zero1hd/polyjet/ui/windows/MGraphWindow.java b/core/src/zero1hd/polyjet/ui/windows/MGraphWindow.java new file mode 100755 index 0000000..5e8357b --- /dev/null +++ b/core/src/zero1hd/polyjet/ui/windows/MGraphWindow.java @@ -0,0 +1,37 @@ +package zero1hd.polyjet.ui.windows; + +import com.badlogic.gdx.scenes.scene2d.ui.Skin; +import com.badlogic.gdx.scenes.scene2d.ui.Window; +import com.badlogic.gdx.utils.FloatArray; + +import zero1hd.polyjet.audio.AudioData; +import zero1hd.polyjet.ui.builders.AudioGraph; + +public class MGraphWindow extends Window { + private AudioGraph graph; + private AudioData audioData; + + public MGraphWindow(String title, Skin skin) { + super(title, skin, "tinted"); + graph = new AudioGraph(300, 150); + add(graph); + pack(); + } + + @Override + public void act(float delta) { + if (audioData != null) { + graph.setAudioDataIndex(audioData.getReadIndex()); + } + super.act(delta); + } + + public AudioGraph getGraph() { + return graph; + } + + public void setData(FloatArray dataSet1, FloatArray dataSet2, AudioData audioData) { + this.audioData = audioData; + graph.setGraphingData(dataSet1, dataSet2); + } +}