diff --git a/core/src/zero1hd/polyjet/audio/AudioAnalyzer.java b/core/src/zero1hd/polyjet/audio/AudioAnalyzer.java index 140558f..f2b6fc5 100755 --- a/core/src/zero1hd/polyjet/audio/AudioAnalyzer.java +++ b/core/src/zero1hd/polyjet/audio/AudioAnalyzer.java @@ -11,7 +11,7 @@ public class AudioAnalyzer { private boolean containsData; private boolean finalized; FloatFFT_1D fft; - public AudioData audiofile; + public AudioData audioData; float[] audioPCM; float[] spectrum; @@ -45,8 +45,9 @@ public class AudioAnalyzer { public MiniSender sender; - int PUID; + private float avgBPS; + int PUID; boolean work; private volatile int progress; public AudioAnalyzer() { @@ -59,7 +60,7 @@ public class AudioAnalyzer { public void run() { progress = 0; int tasksDone = 0; - int totalTasks = audiofile.getSampleCount()/audiofile.getReadWindowSize(); + int totalTasks = audioData.getSampleCount()/audioData.getReadWindowSize(); bassThresholdMultiplier = 1.5f; UMThresholdMultiplier = 2f; @@ -73,16 +74,16 @@ public class AudioAnalyzer { UMThresholdCalcRange = thresholdRangeCalc(0.5f); bassThresholdCalcRange = thresholdRangeCalc(0.7f); - Gdx.app.debug("Read freq", String.valueOf(audiofile.getFormat().getSampleRate())); + 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("Threshold Calc Range UM", String.valueOf(UMThresholdCalcRange)); Gdx.app.debug("Threshold Calc Range Bass", String.valueOf(bassThresholdCalcRange)); - fft = new FloatFFT_1D(audiofile.getReadWindowSize()); + fft = new FloatFFT_1D(audioData.getReadWindowSize()); int seedDigit = 0; - while (audiofile.readSamples(audioPCM) > 0 && work) { + while (audioData.readSamples(audioPCM) > 0 && work) { fft.realForward(audioPCM); @@ -186,7 +187,10 @@ public class AudioAnalyzer { } Gdx.app.debug("Audio Analyzer", "Data prunned."); + float secondsUnit = audioData.getFormat().getSampleRate()/audioData.getReadWindowSize(); //peak detection + avgBPS = -1f; + int beats = 0; for (int i = 0; i < UMPrunned.size-1 && work; i++) { bassPeaks.add((bassPrunned.get(i) > bassPrunned.get(i+1) ? bassPrunned.get(i) : 0)); if (bassPeaks.get(i) > bassMaxValue) { @@ -197,19 +201,26 @@ public class AudioAnalyzer { if (UMPeaks.get(i) > UMMaxValue) { UMMaxValue = UMPeaks.get(i); } - } - - Gdx.app.debug("Audio Analyzer", "Found all peaks."); - - //overlapping beats - for (int i = 0; i < UMPeaks.size && work; i++) { + + //overlapping beats if (bassPeaks.get(i) != 0 && UMPeaks.get(i) != 0) { overlappedPeaks.add(bassPeaks.get(i)+UMPeaks.get(i)/2); } else { overlappedPeaks.add(0); } + + if (avgBPS == -1 && bassPeaks.get(i) != 0) { + avgBPS = 0; + } else if (bassPeaks.get(i) == 0) { + avgBPS ++; + } else { + beats ++; + } + avgBPS /= beats; + avgBPS /= secondsUnit; } + if (work) { Gdx.app.debug("Audio Analyzer", "overlapped beats checked."); @@ -240,7 +251,7 @@ public class AudioAnalyzer { audioPCM = new float[audiofile.getReadWindowSize()]; spectrum = new float[(audiofile.getReadWindowSize()/2)+1]; lastSpectrum = new float[(audiofile.getReadWindowSize()/2)+1]; - this.audiofile = audiofile; + this.audioData = audiofile; work = true; Thread analyticalThread = new Thread(analysisAlgorithm); analyticalThread.start(); @@ -267,7 +278,7 @@ public class AudioAnalyzer { } private int thresholdRangeCalc(float durationOfRange) { - float timePerWindow = (float)audiofile.getReadWindowSize()/audiofile.getFormat().getSampleRate(); + float timePerWindow = (float)audioData.getReadWindowSize()/audioData.getFormat().getSampleRate(); return (int) (durationOfRange/timePerWindow); } @@ -280,8 +291,8 @@ public class AudioAnalyzer { } public int getReadIndex() { - if (audiofile.getReadIndex() < UMPeaks.size) { - return audiofile.getReadIndex(); + if (audioData.getReadIndex() < UMPeaks.size) { + return audioData.getReadIndex(); } else { return 0; } @@ -310,4 +321,12 @@ public class AudioAnalyzer { public FloatArray getOverlappedPeaks() { return overlappedPeaks; } + + public AudioData getAudioData() { + return audioData; + } + + public float getAvgBPS() { + return avgBPS; + } } diff --git a/core/src/zero1hd/polyjet/audio/map/GamePlayMap.java b/core/src/zero1hd/polyjet/audio/map/GamePlayMap.java index 64521f6..de00693 100755 --- a/core/src/zero1hd/polyjet/audio/map/GamePlayMap.java +++ b/core/src/zero1hd/polyjet/audio/map/GamePlayMap.java @@ -20,6 +20,7 @@ public class GamePlayMap { public GamePlayMap(AudioData audioData) { playableClip = audioData.getPlaybackMusic(); playTime = audioData.getDuration(); + spawnList = new Array<>(); } /** @@ -41,14 +42,14 @@ public class GamePlayMap { /** * call this when beginning to build map */ - public void start() { + public void beginBuild() { building = true; } /** * call this when finishing building map */ - public void end() { + public void endBuild() { building = false; } diff --git a/core/src/zero1hd/polyjet/audio/map/RhythmMapAlgorithm.java b/core/src/zero1hd/polyjet/audio/map/RhythmMapAlgorithm.java index ec37f8f..77cbfb5 100755 --- a/core/src/zero1hd/polyjet/audio/map/RhythmMapAlgorithm.java +++ b/core/src/zero1hd/polyjet/audio/map/RhythmMapAlgorithm.java @@ -2,35 +2,59 @@ package zero1hd.polyjet.audio.map; import org.apache.commons.math3.random.MersenneTwister; +import com.badlogic.gdx.math.MathUtils; import com.badlogic.gdx.utils.FloatArray; +import zero1hd.polyjet.Polyjet; import zero1hd.polyjet.audio.AudioAnalyzer; +import zero1hd.polyjet.entity.Entities; public class RhythmMapAlgorithm implements Runnable { private FloatArray bassPeaks; private FloatArray UMPeaks; private FloatArray overlappedPeaks; private MersenneTwister rand; + private GamePlayMap map; + private float avgBPS; + public RhythmMapAlgorithm(AudioAnalyzer analyzer) { bassPeaks = analyzer.getBassPeaks(); UMPeaks = analyzer.getUMPeaks(); overlappedPeaks = analyzer.getOverlappedPeaks(); + map = new GamePlayMap(analyzer.getAudioData()); rand = new MersenneTwister(analyzer.getPUID()); + avgBPS = analyzer.getAvgBPS(); } @Override public void run() { + map.beginBuild(); for (int index = 0; index < bassPeaks.size; index++) { - if (overlappedPeaks.get(index) != 0) { - //TODO basic void spawning - } else if (bassPeaks.get(index) != 0) { - //TODO basic bar spawning - } else { - if (UMPeaks.get(index) != 0) { - //TODO basic pellet scatter spawn + if (bassPeaks.get(index) != 0 || UMPeaks.get(index) != 0) { + if (overlappedPeaks.get(index) != 0) { + //TODO basic void circle spawning + map.addToMap(Entities.VOID_CIRCLE, + overlappedPeaks.get(index)*Polyjet.GAME_AREA_WIDTH, + rand.nextFloat()*Polyjet.GAME_AREA_WIDTH, + rand.nextFloat()*Polyjet.GAME_AREA_HEIGHT); + } else if (bassPeaks.get(index) != 0) { + map.addToMap(Entities.BAR, + MathUtils.round(rand.nextFloat()*Polyjet.GAME_AREA_WIDTH), + bassPeaks.get(index)*Polyjet.GAME_AREA_HEIGHT/avgBPS); + } else { + if (UMPeaks.get(index) != 0) { + //TODO basic pellet scatter spawn + } + //TODO rest of the basic generation } - //TODO rest of the basic generation + } else { + map.addRestToMap(); } } + map.endBuild(); + } + + public synchronized GamePlayMap getMap() { + return map; } }