Skip to content

Commit

Permalink
v1.3: better tap accuracy, hold transitions & more
Browse files Browse the repository at this point in the history
  • Loading branch information
phr00t authored Mar 22, 2018
1 parent 3a8cb2a commit cd9bf85
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 40 deletions.
39 changes: 25 additions & 14 deletions src/autostepper/AutoStepper.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
/*
- nero the thrill seems to have a ~0.2 second position lag when hitting enter
- does this happen in other song files?
*/

package autostepper;

import ddf.minim.AudioPlayer;
import ddf.minim.AudioSample;
import ddf.minim.Minim;
import ddf.minim.MultiChannelBuffer;
import ddf.minim.analysis.BeatDetect;
Expand Down Expand Up @@ -69,7 +76,7 @@ public static void main(String[] args) {
minim = new Minim(myAS);
String outputDir, input;
float duration;
System.out.println("Starting AutoStepper by Phr00t's Software, v1.1 (See www.phr00t.com for more goodies!)");
System.out.println("Starting AutoStepper by Phr00t's Software, v1.3 (See www.phr00t.com for more goodies!)");
if( hasArg(args, "help") || hasArg(args, "h") || hasArg(args, "?") || hasArg(args, "-help") || hasArg(args, "-?") || hasArg(args, "-h") ) {
System.out.println("Argument usage (all fields are optional):\n"
+ "input=<file or dir> output=<songs dir> duration=<seconds to process> synctime=<offset start time in seconds> tap=<true/false> hard=<true/false>");
Expand Down Expand Up @@ -220,33 +227,37 @@ public void AddCommonBPMs(TFloatArrayList common, TFloatArrayList times, float d

public static float tappedOffset;
public int getTappedBPM(String filename) {
AudioPlayer ap = minim.loadFile(filename, 2048);
// now we load the whole song so we don't have to worry about streaming a variable mp3 with timing inaccuracies
System.out.println("Loading whole song for tapping...");
AudioSample fullSong = minim.loadSample(filename);
System.out.println("\n********************************************************************\n\nPress [ENTER] to start song, then press [ENTER] to tap to the beat.\nIt will complete after 30 entries.\nDon't worry about hitting the first beat, just start anytime.\n\n********************************************************************");
TFloatArrayList positions = new TFloatArrayList();
Scanner in = new Scanner(System.in);
try {
in.nextLine();
} catch(Exception e) { }
long milli = System.nanoTime();
ap.play();
milli = (System.nanoTime() + milli) / 2;
} catch(Exception e) { }
// get the most accurate start time as possible
long nano = System.nanoTime();
fullSong.trigger();
nano = (System.nanoTime() + nano) / 2;
try {
for(int i=0;i<30;i++) {
while(System.in.available()==0) { }
in.nextLine();
// get two playtime values & average them together for accuracy
long now = System.nanoTime();
while(System.in.available()>0) { System.in.read(); }
double time = ((double)(now - milli) / 1000000000.0);
positions.add((float)time);
// calculate the time difference
// we note a consistent 0.11 second delay in input to song here
double time = (double)((now - nano) / 1000000000.0) - 0.11;
positions.add((float)time);
System.out.println("#" + positions.size() + "/30: " + time + "s");
}
} catch(Exception e) { }
ap.close();
//TFloatArrayList diffs = calculateDifferences(positions, 60f / (MAX_BPM * 2f));
//float mostCommon = getMostCommon(diffs, 0.025f);
fullSong.stop();
fullSong.close();
float avg = ((positions.getQuick(positions.size()-1) - positions.getQuick(0)) / (positions.size() - 1));
int BPM = (int)Math.floor(60f / avg);
float timePerBeat = 60f / BPM;
tappedOffset = -getBestOffset(timePerBeat, positions, 0.1f) + timePerBeat * 0.5f;
tappedOffset = -getBestOffset(timePerBeat, positions, 0.1f);
return BPM;
}

Expand Down
8 changes: 7 additions & 1 deletion src/autostepper/GoogleImageSearch.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

public class GoogleImageSearch {

Expand All @@ -23,7 +24,12 @@ public static void FindAndSaveImage(String question, String destination) {
try {
String googleUrl = "https://www.google.com/search?as_st=y&tbm=isch&as_q=" + question.replace(",", "+").replace(" ", "+") + "&as_epq=&as_oq=&as_eq=&cr=&as_sitesearch=&safe=images&tbs=isz:lt,islt:vga,iar:w";
Document doc1 = Jsoup.connect(googleUrl).userAgent(ua).timeout(8 * 1000).get();
Element media = doc1.select("[data-src]").first();
Elements elems = doc1.select("[data-src]");
if( elems.isEmpty() ) {
System.out.println("Couldn't find any images for: " + question);
return;
}
Element media = elems.first();
String finUrl = media.attr("abs:data-src");
saveImage(finUrl.replace("&quot", ""), destination);
} catch (Exception e) {
Expand Down
2 changes: 1 addition & 1 deletion src/autostepper/SMGenerator.java
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ public static void Complete(BufferedWriter smfile) {

public static BufferedWriter GenerateSM(float BPM, float startTime, File songfile, String outputdir) {
String filename = songfile.getName();
String songname = filename.replace(".mp3", " ").replace(".wav", " ").replace(".com", " ");
String songname = filename.replace(".mp3", " ").replace(".wav", " ").replace(".com", " ").replace(".org", " ").replace(".info", " ");
String shortName = songname.length() > 30 ? songname.substring(0, 30) : songname;
File dir = new File(outputdir, filename + "_dir/");
dir.mkdirs();
Expand Down
75 changes: 51 additions & 24 deletions src/autostepper/StepGenerator.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
package autostepper;

import gnu.trove.list.array.TFloatArrayList;
import java.util.ArrayList;
import java.util.Random;

/**
Expand Down Expand Up @@ -44,7 +45,7 @@ static private int getRandomHold() {
// make a note line, with lots of checks, balances & filtering
static float[] holding = new float[4];
static float lastJumpTime;
static String lastLine = "0000";
static ArrayList<char[]> AllNoteLines = new ArrayList<>();
static float lastKickTime = 0f;
static int commaSeperator, commaSeperatorReset, mineCount;

Expand Down Expand Up @@ -81,15 +82,20 @@ private static char[] getHoldStops(int currentHoldCount, float time, int holds)
return holdstops;
}

private static String getNoteLine(float time, int steps, int holds, boolean mines) {
private static String getNoteLineIndex(int i) {
if( i < 0 || i >= AllNoteLines.size() ) return "0000";
return String.valueOf(AllNoteLines.get(i));
}

private static String getLastNoteLine() {
return getNoteLineIndex(AllNoteLines.size()-1);
}

private static void makeNoteLine(String lastLine, float time, int steps, int holds, boolean mines) {
if( steps == 0 ) {
lastLine = String.valueOf(getHoldStops(getHoldCount(), time, holds));
commaSeperator--;
if( commaSeperator <= 0 ) {
commaSeperator = commaSeperatorReset;
return lastLine + "\n,\n";
}
return lastLine + "\n";
char[] ret = getHoldStops(getHoldCount(), time, holds);
AllNoteLines.add(ret);
return;
}
if( steps > 1 && time - lastJumpTime < (mines ? 2f : 4f) ) steps = 1; // don't spam jumps
if( steps >= 2 ) {
Expand All @@ -103,6 +109,22 @@ private static String getNoteLine(float time, int steps, int holds, boolean mine
if( steps + currentHoldCount > 2 ) steps = 2 - currentHoldCount;
// are we stopping holds?
char[] noteLine = getHoldStops(currentHoldCount, time, holds);
// if we are making a step, but just coming off a hold, move that hold end up to give proper
// time to make move to new step
if( steps > 0 && lastLine.contains("3") ) {
int currentIndex = AllNoteLines.size()-1;
char[] currentLine = AllNoteLines.get(currentIndex);
for(int i=0;i<4;i++) {
if( currentLine[i] == '3' ) {
// got a hold stop here, lets move it up
currentLine[i] = '0';
char[] nextLineUp = AllNoteLines.get(currentIndex-1);
if( nextLineUp[i] == '2' ) {
nextLineUp[i] = '1';
} else nextLineUp[i] = '3';
}
}
}
// ok, make the steps
String completeLine;
char[] orig = new char[4];
Expand Down Expand Up @@ -145,18 +167,12 @@ private static String getNoteLine(float time, int steps, int holds, boolean mine
}
}
completeLine = String.valueOf(noteLine);
} while( completeLine.equals(lastLine) && completeLine.equals("0000") == false );
} while( completeLine.equals(String.valueOf(AllNoteLines.get(AllNoteLines.size()-1))) && completeLine.equals("0000") == false );
if( willhold[0] > holding[0] ) holding[0] = willhold[0];
if( willhold[1] > holding[1] ) holding[1] = willhold[1];
if( willhold[2] > holding[2] ) holding[2] = willhold[2];
if( willhold[3] > holding[3] ) holding[3] = willhold[3];
lastLine = completeLine;
commaSeperator--;
if( commaSeperator <= 0 ) {
completeLine += "\n,\n";
commaSeperator = commaSeperatorReset;
} else completeLine += "\n";
return completeLine;
AllNoteLines.add(noteLine);
}

private static boolean isNearATime(float time, TFloatArrayList timelist, float threshold) {
Expand Down Expand Up @@ -204,26 +220,25 @@ public static String GenerateNotes(int stepGranularity, int skipChance,
float timePerBeat, float timeOffset, float totalTime,
boolean allowMines) {
// reset variables
lastLine = "0000";
AllNoteLines.clear();
lastJumpTime = -10f;
holding[0] = 0f;
holding[1] = 0f;
holding[2] = 0f;
holding[3] = 0f;
lastKickTime = 0f;
String AllNotes = "";
commaSeperatorReset = 4 * stepGranularity;
commaSeperator = commaSeperatorReset;
float lastSkippedTime = -10f;
int totalStepsMade = 0, timeIndex = 0;
boolean skippedLast = false;
float timeGranularity = timePerBeat / stepGranularity;
for(float t = timeOffset; t <= totalTime; t += timeGranularity) {
int steps = 0, holds = 0;
String lastLine = getLastNoteLine();
if( t > 0f ) {
float fftavg = getFFT(t, FFTAverages, timePerFFT);
float fftmax = getFFT(t, FFTMaxes, timePerFFT);
boolean sustained = sustainedFFT(t, 0.75f, timeGranularity, timePerFFT, FFTMaxes, FFTAverages, 0.25f, 0.5f);
boolean sustained = sustainedFFT(t, 0.75f, timeGranularity, timePerFFT, FFTMaxes, FFTAverages, 0.25f, 0.45f);
boolean nearKick = isNearATime(t, fewTimes[AutoStepper.KICKS], timePerBeat / stepGranularity);
boolean nearSnare = isNearATime(t, fewTimes[AutoStepper.SNARE], timePerBeat / stepGranularity);
boolean nearEnergy = isNearATime(t, fewTimes[AutoStepper.ENERGY], timePerBeat / stepGranularity);
Expand All @@ -249,15 +264,27 @@ public static String GenerateNotes(int stepGranularity, int skipChance,
}
}
if( AutoStepper.DEBUG_STEPS ) {
AllNotes += getNoteLine(t, timeIndex % 2 == 0 ? 1 : 0, -2, allowMines);
} else AllNotes += getNoteLine(t, steps, holds, allowMines);
makeNoteLine(lastLine, t, timeIndex % 2 == 0 ? 1 : 0, -2, allowMines);
} else makeNoteLine(lastLine, t, steps, holds, allowMines);
totalStepsMade += steps;
timeIndex++;
}
// ok, put together AllNotes
String AllNotes = "";
commaSeperator = commaSeperatorReset;
for(int i=0;i<AllNoteLines.size();i++) {
AllNotes += getNoteLineIndex(i) + "\n";
commaSeperator--;
if( commaSeperator == 0 ) {
AllNotes += ",\n";
commaSeperator = commaSeperatorReset;
}
}
// fill out the last empties
while( commaSeperator > 0 ) {
AllNotes += "3333\n";
AllNotes += "3333";
commaSeperator--;
if( commaSeperator > 0 ) AllNotes += "\n";
}
int _stepCount = AllNotes.length() - AllNotes.replace("1", "").length();
int _holdCount = AllNotes.length() - AllNotes.replace("2", "").length();
Expand Down

0 comments on commit cd9bf85

Please sign in to comment.