Skip to content

Commit cd9bf85

Browse files
authored
v1.3: better tap accuracy, hold transitions & more
1 parent 3a8cb2a commit cd9bf85

File tree

4 files changed

+84
-40
lines changed

4 files changed

+84
-40
lines changed

src/autostepper/AutoStepper.java

+25-14
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
1+
/*
2+
- nero the thrill seems to have a ~0.2 second position lag when hitting enter
3+
- does this happen in other song files?
4+
5+
*/
6+
17
package autostepper;
28

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

221228
public static float tappedOffset;
222229
public int getTappedBPM(String filename) {
223-
AudioPlayer ap = minim.loadFile(filename, 2048);
230+
// now we load the whole song so we don't have to worry about streaming a variable mp3 with timing inaccuracies
231+
System.out.println("Loading whole song for tapping...");
232+
AudioSample fullSong = minim.loadSample(filename);
224233
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********************************************************************");
225234
TFloatArrayList positions = new TFloatArrayList();
226235
Scanner in = new Scanner(System.in);
227236
try {
228237
in.nextLine();
229-
} catch(Exception e) { }
230-
long milli = System.nanoTime();
231-
ap.play();
232-
milli = (System.nanoTime() + milli) / 2;
238+
} catch(Exception e) { }
239+
// get the most accurate start time as possible
240+
long nano = System.nanoTime();
241+
fullSong.trigger();
242+
nano = (System.nanoTime() + nano) / 2;
233243
try {
234244
for(int i=0;i<30;i++) {
235-
while(System.in.available()==0) { }
245+
in.nextLine();
246+
// get two playtime values & average them together for accuracy
236247
long now = System.nanoTime();
237-
while(System.in.available()>0) { System.in.read(); }
238-
double time = ((double)(now - milli) / 1000000000.0);
239-
positions.add((float)time);
248+
// calculate the time difference
249+
// we note a consistent 0.11 second delay in input to song here
250+
double time = (double)((now - nano) / 1000000000.0) - 0.11;
251+
positions.add((float)time);
240252
System.out.println("#" + positions.size() + "/30: " + time + "s");
241253
}
242254
} catch(Exception e) { }
243-
ap.close();
244-
//TFloatArrayList diffs = calculateDifferences(positions, 60f / (MAX_BPM * 2f));
245-
//float mostCommon = getMostCommon(diffs, 0.025f);
255+
fullSong.stop();
256+
fullSong.close();
246257
float avg = ((positions.getQuick(positions.size()-1) - positions.getQuick(0)) / (positions.size() - 1));
247258
int BPM = (int)Math.floor(60f / avg);
248259
float timePerBeat = 60f / BPM;
249-
tappedOffset = -getBestOffset(timePerBeat, positions, 0.1f) + timePerBeat * 0.5f;
260+
tappedOffset = -getBestOffset(timePerBeat, positions, 0.1f);
250261
return BPM;
251262
}
252263

src/autostepper/GoogleImageSearch.java

+7-1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import org.jsoup.Jsoup;
1414
import org.jsoup.nodes.Document;
1515
import org.jsoup.nodes.Element;
16+
import org.jsoup.select.Elements;
1617

1718
public class GoogleImageSearch {
1819

@@ -23,7 +24,12 @@ public static void FindAndSaveImage(String question, String destination) {
2324
try {
2425
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";
2526
Document doc1 = Jsoup.connect(googleUrl).userAgent(ua).timeout(8 * 1000).get();
26-
Element media = doc1.select("[data-src]").first();
27+
Elements elems = doc1.select("[data-src]");
28+
if( elems.isEmpty() ) {
29+
System.out.println("Couldn't find any images for: " + question);
30+
return;
31+
}
32+
Element media = elems.first();
2733
String finUrl = media.attr("abs:data-src");
2834
saveImage(finUrl.replace("&quot", ""), destination);
2935
} catch (Exception e) {

src/autostepper/SMGenerator.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ public static void Complete(BufferedWriter smfile) {
104104

105105
public static BufferedWriter GenerateSM(float BPM, float startTime, File songfile, String outputdir) {
106106
String filename = songfile.getName();
107-
String songname = filename.replace(".mp3", " ").replace(".wav", " ").replace(".com", " ");
107+
String songname = filename.replace(".mp3", " ").replace(".wav", " ").replace(".com", " ").replace(".org", " ").replace(".info", " ");
108108
String shortName = songname.length() > 30 ? songname.substring(0, 30) : songname;
109109
File dir = new File(outputdir, filename + "_dir/");
110110
dir.mkdirs();

src/autostepper/StepGenerator.java

+51-24
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
package autostepper;
77

88
import gnu.trove.list.array.TFloatArrayList;
9+
import java.util.ArrayList;
910
import java.util.Random;
1011

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

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

84-
private static String getNoteLine(float time, int steps, int holds, boolean mines) {
85+
private static String getNoteLineIndex(int i) {
86+
if( i < 0 || i >= AllNoteLines.size() ) return "0000";
87+
return String.valueOf(AllNoteLines.get(i));
88+
}
89+
90+
private static String getLastNoteLine() {
91+
return getNoteLineIndex(AllNoteLines.size()-1);
92+
}
93+
94+
private static void makeNoteLine(String lastLine, float time, int steps, int holds, boolean mines) {
8595
if( steps == 0 ) {
86-
lastLine = String.valueOf(getHoldStops(getHoldCount(), time, holds));
87-
commaSeperator--;
88-
if( commaSeperator <= 0 ) {
89-
commaSeperator = commaSeperatorReset;
90-
return lastLine + "\n,\n";
91-
}
92-
return lastLine + "\n";
96+
char[] ret = getHoldStops(getHoldCount(), time, holds);
97+
AllNoteLines.add(ret);
98+
return;
9399
}
94100
if( steps > 1 && time - lastJumpTime < (mines ? 2f : 4f) ) steps = 1; // don't spam jumps
95101
if( steps >= 2 ) {
@@ -103,6 +109,22 @@ private static String getNoteLine(float time, int steps, int holds, boolean mine
103109
if( steps + currentHoldCount > 2 ) steps = 2 - currentHoldCount;
104110
// are we stopping holds?
105111
char[] noteLine = getHoldStops(currentHoldCount, time, holds);
112+
// if we are making a step, but just coming off a hold, move that hold end up to give proper
113+
// time to make move to new step
114+
if( steps > 0 && lastLine.contains("3") ) {
115+
int currentIndex = AllNoteLines.size()-1;
116+
char[] currentLine = AllNoteLines.get(currentIndex);
117+
for(int i=0;i<4;i++) {
118+
if( currentLine[i] == '3' ) {
119+
// got a hold stop here, lets move it up
120+
currentLine[i] = '0';
121+
char[] nextLineUp = AllNoteLines.get(currentIndex-1);
122+
if( nextLineUp[i] == '2' ) {
123+
nextLineUp[i] = '1';
124+
} else nextLineUp[i] = '3';
125+
}
126+
}
127+
}
106128
// ok, make the steps
107129
String completeLine;
108130
char[] orig = new char[4];
@@ -145,18 +167,12 @@ private static String getNoteLine(float time, int steps, int holds, boolean mine
145167
}
146168
}
147169
completeLine = String.valueOf(noteLine);
148-
} while( completeLine.equals(lastLine) && completeLine.equals("0000") == false );
170+
} while( completeLine.equals(String.valueOf(AllNoteLines.get(AllNoteLines.size()-1))) && completeLine.equals("0000") == false );
149171
if( willhold[0] > holding[0] ) holding[0] = willhold[0];
150172
if( willhold[1] > holding[1] ) holding[1] = willhold[1];
151173
if( willhold[2] > holding[2] ) holding[2] = willhold[2];
152174
if( willhold[3] > holding[3] ) holding[3] = willhold[3];
153-
lastLine = completeLine;
154-
commaSeperator--;
155-
if( commaSeperator <= 0 ) {
156-
completeLine += "\n,\n";
157-
commaSeperator = commaSeperatorReset;
158-
} else completeLine += "\n";
159-
return completeLine;
175+
AllNoteLines.add(noteLine);
160176
}
161177

162178
private static boolean isNearATime(float time, TFloatArrayList timelist, float threshold) {
@@ -204,26 +220,25 @@ public static String GenerateNotes(int stepGranularity, int skipChance,
204220
float timePerBeat, float timeOffset, float totalTime,
205221
boolean allowMines) {
206222
// reset variables
207-
lastLine = "0000";
223+
AllNoteLines.clear();
208224
lastJumpTime = -10f;
209225
holding[0] = 0f;
210226
holding[1] = 0f;
211227
holding[2] = 0f;
212228
holding[3] = 0f;
213229
lastKickTime = 0f;
214-
String AllNotes = "";
215230
commaSeperatorReset = 4 * stepGranularity;
216-
commaSeperator = commaSeperatorReset;
217231
float lastSkippedTime = -10f;
218232
int totalStepsMade = 0, timeIndex = 0;
219233
boolean skippedLast = false;
220234
float timeGranularity = timePerBeat / stepGranularity;
221235
for(float t = timeOffset; t <= totalTime; t += timeGranularity) {
222236
int steps = 0, holds = 0;
237+
String lastLine = getLastNoteLine();
223238
if( t > 0f ) {
224239
float fftavg = getFFT(t, FFTAverages, timePerFFT);
225240
float fftmax = getFFT(t, FFTMaxes, timePerFFT);
226-
boolean sustained = sustainedFFT(t, 0.75f, timeGranularity, timePerFFT, FFTMaxes, FFTAverages, 0.25f, 0.5f);
241+
boolean sustained = sustainedFFT(t, 0.75f, timeGranularity, timePerFFT, FFTMaxes, FFTAverages, 0.25f, 0.45f);
227242
boolean nearKick = isNearATime(t, fewTimes[AutoStepper.KICKS], timePerBeat / stepGranularity);
228243
boolean nearSnare = isNearATime(t, fewTimes[AutoStepper.SNARE], timePerBeat / stepGranularity);
229244
boolean nearEnergy = isNearATime(t, fewTimes[AutoStepper.ENERGY], timePerBeat / stepGranularity);
@@ -249,15 +264,27 @@ public static String GenerateNotes(int stepGranularity, int skipChance,
249264
}
250265
}
251266
if( AutoStepper.DEBUG_STEPS ) {
252-
AllNotes += getNoteLine(t, timeIndex % 2 == 0 ? 1 : 0, -2, allowMines);
253-
} else AllNotes += getNoteLine(t, steps, holds, allowMines);
267+
makeNoteLine(lastLine, t, timeIndex % 2 == 0 ? 1 : 0, -2, allowMines);
268+
} else makeNoteLine(lastLine, t, steps, holds, allowMines);
254269
totalStepsMade += steps;
255270
timeIndex++;
256271
}
272+
// ok, put together AllNotes
273+
String AllNotes = "";
274+
commaSeperator = commaSeperatorReset;
275+
for(int i=0;i<AllNoteLines.size();i++) {
276+
AllNotes += getNoteLineIndex(i) + "\n";
277+
commaSeperator--;
278+
if( commaSeperator == 0 ) {
279+
AllNotes += ",\n";
280+
commaSeperator = commaSeperatorReset;
281+
}
282+
}
257283
// fill out the last empties
258284
while( commaSeperator > 0 ) {
259-
AllNotes += "3333\n";
285+
AllNotes += "3333";
260286
commaSeperator--;
287+
if( commaSeperator > 0 ) AllNotes += "\n";
261288
}
262289
int _stepCount = AllNotes.length() - AllNotes.replace("1", "").length();
263290
int _holdCount = AllNotes.length() - AllNotes.replace("2", "").length();

0 commit comments

Comments
 (0)