map algorithm and analysis page progress

This commit is contained in:
Harrison Deng 2017-07-10 23:54:49 -05:00
parent 1573884e99
commit 0cf0609442
5 changed files with 148 additions and 32 deletions

View File

@ -50,7 +50,7 @@ public class AudioAnalyzer {
int PUID; int PUID;
boolean work; boolean work;
private volatile int progress; private volatile int progress;
private float secondsPerFrame; private float secondsPerWindow;
public AudioAnalyzer() { public AudioAnalyzer() {
sender = new MiniSender(); sender = new MiniSender();
@ -190,7 +190,7 @@ public class AudioAnalyzer {
} }
Gdx.app.debug("Audio Analyzer", "Data prunned."); Gdx.app.debug("Audio Analyzer", "Data prunned.");
secondsPerFrame = audioData.getReadWindowSize()/audioData.getFormat().getSampleRate(); secondsPerWindow = audioData.getReadWindowSize()/audioData.getFormat().getSampleRate();
//peak detection //peak detection
int lastID = 0; int lastID = 0;
@ -225,7 +225,7 @@ public class AudioAnalyzer {
} }
//then we minus one from the beats so it actually works out //then we minus one from the beats so it actually works out
avgBPS -= UMPrunned.size-lastID; avgBPS -= UMPrunned.size-lastID;
avgBPS *= secondsPerFrame; avgBPS *= secondsPerWindow;
avgBPS = beats/avgBPS; avgBPS = beats/avgBPS;
} }
@ -266,9 +266,9 @@ public class AudioAnalyzer {
analyticalThread.start(); analyticalThread.start();
} }
public void runThresholdCleaning(float baseThresholdMultiplier, float UMThresholdMultiplier) { public void runThresholdCleaning(float rangeModifier) {
this.bassThresholdMultiplier = baseThresholdMultiplier; this.bassThresholdMultiplier += rangeModifier;
this.UMThresholdMultiplier = UMThresholdMultiplier; this.UMThresholdMultiplier += rangeModifier;
work = true; work = true;
Thread thresholdClean = new Thread(thresholdCalculator); Thread thresholdClean = new Thread(thresholdCalculator);
thresholdClean.start(); thresholdClean.start();
@ -339,7 +339,7 @@ public class AudioAnalyzer {
return avgBPS; return avgBPS;
} }
public float getsecondsPerFrame() { public float getsecondsPerWindow() {
return secondsPerFrame; return secondsPerWindow;
} }
} }

View File

@ -16,15 +16,23 @@ public class RhythmMapAlgorithm implements Runnable {
private MersenneTwister rand; private MersenneTwister rand;
private GamePlayMap map; private GamePlayMap map;
private float avgBPS; private float avgBPS;
private float second;
public RhythmMapAlgorithm(AudioAnalyzer analyzer) { private float speedMod, healthMod;
private float windowPerSecond;
private volatile int progress;
public RhythmMapAlgorithm(AudioAnalyzer analyzer, float speedMod, float healthMod) {
bassPeaks = analyzer.getBassPeaks(); bassPeaks = analyzer.getBassPeaks();
UMPeaks = analyzer.getUMPeaks(); UMPeaks = analyzer.getUMPeaks();
overlappedPeaks = analyzer.getOverlappedPeaks(); overlappedPeaks = analyzer.getOverlappedPeaks();
map = new GamePlayMap(analyzer.getAudioData()); map = new GamePlayMap(analyzer.getAudioData());
rand = new MersenneTwister(analyzer.getPUID()); rand = new MersenneTwister(analyzer.getPUID());
avgBPS = analyzer.getAvgBPS(); avgBPS = analyzer.getAvgBPS();
second = analyzer.getsecondsPerFrame(); windowPerSecond = 1/analyzer.getsecondsPerWindow();
this.speedMod = speedMod;
this.healthMod = healthMod;
} }
@Override @Override
@ -32,22 +40,23 @@ public class RhythmMapAlgorithm implements Runnable {
map.beginBuild(); map.beginBuild();
for (int index = 0; index < bassPeaks.size; index++) { 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 (overlappedPeaks.get(index+3) != 0) { int warningTime = (int) ((3/speedMod)*windowPerSecond);
if (overlappedPeaks.get(index + warningTime) != 0) {
//TODO basic void circle spawning //TODO basic void circle spawning
float endRadius = rand.nextFloat()*Polyjet.GAME_AREA_WIDTH; float endRadius = overlappedPeaks.get(index+3)*Polyjet.GAME_AREA_WIDTH;
map.addToMap(Entities.VOID_CIRCLE, map.addToMap(Entities.VOID_CIRCLE,
endRadius, endRadius,
rand.nextFloat()*Polyjet.GAME_AREA_WIDTH, rand.nextFloat()*Polyjet.GAME_AREA_WIDTH,
rand.nextFloat()*Polyjet.GAME_AREA_HEIGHT, rand.nextFloat()*Polyjet.GAME_AREA_HEIGHT,
avgBPS, endRadius/avgBPS,
3f*second warningTime
); );
} }
if (bassPeaks.get(index) != 0) { if (bassPeaks.get(index) != 0) {
map.addToMap(Entities.BAR, map.addToMap(Entities.BAR,
MathUtils.round(rand.nextFloat()*Polyjet.GAME_AREA_WIDTH), MathUtils.round(rand.nextFloat()*Polyjet.GAME_AREA_WIDTH),
bassPeaks.get(index)*Polyjet.GAME_AREA_HEIGHT/avgBPS); ((Polyjet.GAME_AREA_HEIGHT-bassPeaks.get(index)*Polyjet.GAME_AREA_HEIGHT)/avgBPS)*speedMod);
} else { } else {
if (UMPeaks.get(index) != 0) { if (UMPeaks.get(index) != 0) {
//TODO basic pellet scatter spawn //TODO basic pellet scatter spawn
@ -57,6 +66,8 @@ public class RhythmMapAlgorithm implements Runnable {
} else { } else {
map.addRestToMap(); map.addRestToMap();
} }
progress = (int) (100f*index/bassPeaks.size);
} }
map.endBuild(); map.endBuild();
} }
@ -64,4 +75,8 @@ public class RhythmMapAlgorithm implements Runnable {
public synchronized GamePlayMap getMap() { public synchronized GamePlayMap getMap() {
return map; return map;
} }
public synchronized int getProgress() {
return progress;
}
} }

View File

@ -4,10 +4,8 @@ import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Screen; import com.badlogic.gdx.Screen;
import com.badlogic.gdx.ScreenAdapter; import com.badlogic.gdx.ScreenAdapter;
import com.badlogic.gdx.graphics.GL20; import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.math.Vector3; import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.scenes.scene2d.Stage; import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.ui.Image;
import com.badlogic.gdx.utils.viewport.ScreenViewport; import com.badlogic.gdx.utils.viewport.ScreenViewport;
import zero1hd.polyjet.Polyjet; import zero1hd.polyjet.Polyjet;
@ -80,12 +78,6 @@ public class PreGameScreen extends ScreenAdapter implements TransitionAdapter, M
@Override @Override
public Screen postTransition() { public Screen postTransition() {
Image circle1 = new Image(core.getAssetManager().get("cybercircle1.png", Texture.class));
circle1.setOrigin(circle1.getWidth()/2f, circle1.getHeight()/2f);
circle1.setPosition(Gdx.graphics.getWidth(), circle1.getHeight()/3);
stage.addActor(circle1);
ms = new MusicSelectionPage(core); ms = new MusicSelectionPage(core);
ms.miniSender.addListener(this); ms.miniSender.addListener(this);
ms.beginMusicSearch(); ms.beginMusicSearch();

View File

@ -1,5 +1,6 @@
package zero1hd.polyjet.ui.pages; package zero1hd.polyjet.ui.pages;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.assets.AssetManager; import com.badlogic.gdx.assets.AssetManager;
import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.Texture;
@ -18,6 +19,7 @@ import com.badlogic.gdx.utils.Align;
import zero1hd.polyjet.audio.AudioAnalyzer; import zero1hd.polyjet.audio.AudioAnalyzer;
import zero1hd.polyjet.audio.AudioData; import zero1hd.polyjet.audio.AudioData;
import zero1hd.polyjet.audio.AudioInfo; import zero1hd.polyjet.audio.AudioInfo;
import zero1hd.polyjet.audio.map.RhythmMapAlgorithm;
import zero1hd.polyjet.ui.builders.ScrollText; import zero1hd.polyjet.ui.builders.ScrollText;
import zero1hd.polyjet.util.MiniEvents; import zero1hd.polyjet.util.MiniEvents;
import zero1hd.polyjet.util.MiniListener; import zero1hd.polyjet.util.MiniListener;
@ -25,6 +27,7 @@ import zero1hd.polyjet.util.MiniListener;
public class AnalyzePage extends Page implements MiniListener { public class AnalyzePage extends Page implements MiniListener {
AudioAnalyzer audioAnalyzer; AudioAnalyzer audioAnalyzer;
AudioData music; AudioData music;
RhythmMapAlgorithm mapGenAlgorithm;
Table difficultyTable; Table difficultyTable;
private Label diffTitle; private Label diffTitle;
@ -34,6 +37,8 @@ public class AnalyzePage extends Page implements MiniListener {
private Label speedModifierTitle; private Label speedModifierTitle;
private Slider healthModifier; private Slider healthModifier;
private Label healthModifierTitle; private Label healthModifierTitle;
private TextButton confirmDiffButton;
private boolean confirmed;
private Skin skin; private Skin skin;
private TextButton back; private TextButton back;
@ -42,22 +47,100 @@ public class AnalyzePage extends Page implements MiniListener {
Table songInfo; Table songInfo;
private Label[] info; private Label[] info;
private Thread mapGenThread;
public AnalyzePage(Skin skin, AssetManager assets) { public AnalyzePage(Skin skin, AssetManager assets) {
super("Results", skin); super("Results", skin);
this.skin = skin; this.skin = skin;
difficultyTable = new Table(skin); difficultyTable = new Table(skin);
//TODO work on sliders and stuff difficultyTable.setBackground(skin.getDrawable("large-pane"));
addActor(difficultyTable);
diffTitle = new Label("Difficulty", skin);
difficultyTable.add(diffTitle).expandX().left();
difficultyTable.row();
sensitivityRating = new Slider(-5f, 5f, 1f, false, skin);
sensitivityRating.setValue(0f);
sensitivityRating.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
sensitivityRatingTitle.setText("Base Difficulty: " + sensitivityRating.getValue());
}
});
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: " + speedModifier.getValue());
if (audioAnalyzer.containsData()) {
audioAnalyzer.runThresholdCleaning(sensitivityRating.getValue());
}
}
});
speedModifierTitle = new Label("Speed Modifier: " + 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();
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);
if (audioAnalyzer.containsData()) {
finalizeData();
}
}
});
difficultyTable.add(confirmDiffButton);
difficultyTable.pack();
songInfo = new Table(skin); songInfo = new Table(skin);
songInfo.setBackground(skin.getDrawable("large-pane")); songInfo.setBackground(skin.getDrawable("large-pane"));
addActor(songInfo);
loadingCircle = new Image(assets.get("cybercircle1.png", Texture.class)); loadingCircle = new Image(assets.get("cybercircle1.png", Texture.class));
loadingCircle.setPosition((getWidth()-loadingCircle.getWidth())/2, (getHeightBelowTitle()-loadingCircle.getHeight())/2); loadingCircle.setPosition((getWidth()-loadingCircle.getWidth())/2, (getHeightBelowTitle()-loadingCircle.getHeight())/2);
loadingCircle.setColor(0.8f,0.8f,0.8f,0.7f); loadingCircle.setColor(0.8f,0.8f,0.8f,0.7f);
loadingCircle.setOrigin(loadingCircle.getWidth()/2, loadingCircle.getHeight()/2); loadingCircle.setOrigin(loadingCircle.getWidth()/2, loadingCircle.getHeight()/2);
loadingCircle.addAction(Actions.forever(Actions.rotateBy(-360f, 4f))); loadingCircle.addAction(Actions.forever(Actions.rotateBy(-360f, 4f)));
addActor(loadingCircle); addActor(loadingCircle);
loadingCircle.toBack();
back = new TextButton("Back", skin); back = new TextButton("Back", skin);
back.setPosition(getWidth()-back.getWidth()-15f, getHeightBelowTitle()); back.setPosition(getWidth()-back.getWidth()-15f, getHeightBelowTitle());
@ -75,7 +158,6 @@ public class AnalyzePage extends Page implements MiniListener {
} }
addActor(back); addActor(back);
addActor(songInfo);
} }
public void setSong(AudioData music, AudioInfo audioInfo, MiniListener listener) { public void setSong(AudioData music, AudioInfo audioInfo, MiniListener listener) {
@ -101,10 +183,11 @@ public class AnalyzePage extends Page implements MiniListener {
songInfo.pack(); songInfo.pack();
songInfo.setWidth(getWidth()/2f); songInfo.setWidth(getWidth()/2f);
songInfo.setPosition((getWidth()-songInfo.getWidth())/2f, (getHeightBelowTitle()-songInfo.getHeight())/2f); songInfo.setPosition((getWidth()-songInfo.getWidth())/2f, (getHeightBelowTitle()-songInfo.getHeight())/2f);
difficultyTable.setPosition(songInfo.getX(), -difficultyTable.getHeight());
difficultyTable.setWidth(songInfo.getWidth());
startTime = System.currentTimeMillis(); startTime = System.currentTimeMillis();
info[0].addAction(Actions.color(Color.BLACK, 2.5f)); info[0].addAction(Actions.color(Color.BLACK, 2.5f));
System.out.println(songInfo);
} }
@ -130,7 +213,11 @@ public class AnalyzePage extends Page implements MiniListener {
switch (ID) { switch (ID) {
case ANALYZER_ITERATED: case ANALYZER_ITERATED:
if (audioAnalyzer.getProgress() == 50) { if (audioAnalyzer.getProgress() == 50) {
songInfo.addAction(Actions.moveTo(40f, getHeightBelowTitle()-songInfo.getHeight()-25f, 0.75f, Interpolation.linear)); songInfo.addAction(Actions.moveTo(songInfo.getX(), getHeight()/2f, 0.75f, Interpolation.linear));
difficultyTable.addAction(Actions.moveTo(songInfo.getX(), songInfo.getY()-difficultyTable.getHeight(),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() + "%"); info[0].setText("Initial analysis: " + audioAnalyzer.getProgress() + "%");
break; break;
@ -138,10 +225,32 @@ public class AnalyzePage extends Page implements MiniListener {
endTime = System.currentTimeMillis(); endTime = System.currentTimeMillis();
info[1].setText("Done. Analyze time: " + ((endTime - startTime)/1000f) + "s"); info[1].setText("Done. Analyze time: " + ((endTime - startTime)/1000f) + "s");
info[1].addAction(Actions.color(Color.BLACK, 0.75f)); info[1].addAction(Actions.color(Color.BLACK, 0.75f));
if (confirmed) {
finalizeData();
}
break; break;
case MUSIC_DATA_CLEANED:
info[3].setText("data cleaning done.");
info[4].addAction(Actions.color(Color.BLACK, 0.75f));
mapGenAlgorithm = new RhythmMapAlgorithm(audioAnalyzer, speedModifier.getValue(), healthModifier.getValue());
mapGenThread = new Thread(mapGenAlgorithm);
mapGenThread.start();
break;
case MAPGEN_ITERATED:
info[4].setText("Generating map: " + mapGenAlgorithm.getProgress());
default: default:
break; break;
} }
} }
private void finalizeData() {
Gdx.app.debug("analyze", "confirmed data finalization.");
audioAnalyzer.runThresholdCleaning(sensitivityRating.getValue());
info[3].setText("finalizing data...");
info[3].addAction(Actions.color(Color.BLACK, 0.75f));
}
private void generateMap() {
}
} }

View File

@ -1,5 +1,5 @@
package zero1hd.polyjet.util; package zero1hd.polyjet.util;
public enum MiniEvents { public enum MiniEvents {
SPECTRAL_FLUX_DONE, MUSIC_DATA_CLEANED, MUSIC_SELECTED, BACK, MAP_GENERATED, ANALYZER_ITERATED; SPECTRAL_FLUX_DONE, MUSIC_DATA_CLEANED, MUSIC_SELECTED, BACK, MAP_GENERATED, ANALYZER_ITERATED, MAPGEN_ITERATED;
} }