You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The "+9ms or null" sync analysis also ended up in here. Oops!
1
+
# +9ms or Null?
2
+
## +9ms or Null? is a StepMania simfile unbiasing utility.
3
+
4
+
This utility can determine whether the sync bias of a simfile or a pack is +9ms (In The Groove) or null (general StepMania). A future version will also offer to unify it under one of those two options.
5
+
6
+
***It is not meant to perform a millisecond-perfect sync!*** Please don't depend on the exact value you get from it. Instrument attacks vary significantly, and the algorithm I'm using is not smart enough to know what to focus on.
7
+
8
+
You can read more about the origins of the +9ms sync bias here:
-[Ash's discussion of solutions @ meow.garden](https://meow.garden/killing-the-9ms-bias)
11
+
12
+
Needless to say, it's about time to put the nine millisecond nail in this coffin.
13
+
14
+
## How does it work?
15
+
I'll get into more detail on this elsewhere, but the seed concept is a visual representation first implemented (as far as I can tell) by beware, of beware's DDR Extreme fame.
16
+
1. Identify the time that each beat occurs - I used ashastral's excellent [`simfile`](https://simfile.readthedocs.io/en/latest/) library to do this.
17
+
1. Load the audio (`pydub`) and calculate its spectrogram (`numpy` & `scipy`).
18
+
1. Snip a small window around each beat time out of the spectrogram and stack them in some way - this becomes the **sync fingerprint**.
19
+
- Time will always be on the X axis for this exercise.
20
+
-**Beat digest**: Flatten the frequencies (after applying a simple filter to avoid ultra-high/-low bands) and let the Y coordinate be the index of the beat. The most helpful visual, and the original inspiration.
21
+
-**Accumulator**: Sum up the window and keep the frequency of the sound energy as the Y coordinate. Not as useful but a good sanity check.
22
+
1. Apply a time-domain convolution to identify the audio feature the simfile is sync'd to.
23
+
-**Rising edge**: This one seems like the most reliable.
24
+
-**Local loudness**: A more naive approach - and a bit easier to fool. But if you want to see what it does, it's here.
25
+
1. Take the time at the highest response of the convolution as the bias of the simfile's sync.
26
+
1. Decide whether the simfile was sync'd to the +9ms (In The Groove) or the null (StepMania) paradigm, or to neither in particular, by checking whether that bias lies within a small interval around +9ms or 0ms, respectively.
27
+
1. Visualize it all for the user (`matplotlib`).
28
+
29
+
## How to use
30
+
31
+
### Setting up the project
32
+
You have a couple options:
33
+
- Clone the repository and use `poetry` to set up the `nine-or-null` package.
34
+
1.`poetry install`
35
+
1. (CLI) `poetry run python -m nine_or_null "C:\Games\ITGmania\Songs\pack-name"`
36
+
1. (GUI) `poetry run python -m nine_or_null.gui` or `poetry run python -m nine_or_null`
37
+
- Download the executable (made with PyInstaller).
38
+
39
+
### Command-line interface (CLI)
40
+
It's not as configurable as the GUI yet but that's coming soon. For now you can just call the main routine of the `nine_or_null` package, and pass it the full path to the pack as a command-line argument. If you call it without a path, it'll invoke the GUI.
41
+
42
+
### Graphical user interface (GUI)
43
+

44
+
45
+
The intended workflow:
46
+
1. Select the path to the pack or simfile you want to check using the directory button in the upper-right corner (or manually enter in the text box next to it).
47
+
1. You can probably leave all the parameters alone for now.
48
+
1. Press the big button to **let that sync in**.
49
+
1. Let the GUI do some heavy lifting. It'll probably take a few seconds per simfile with the default settings - and it's probably gonna act like it's unresponsive. (There's some threading I could do to fix that, but I'll get to that later.)
50
+
1. Watch the status bar, results table, and sync fingerprint plots for updates.
51
+
- From top to bottom, the plots represent the frequency domain accumulator, the beat digest, and the convolved fingerprint.
52
+
- The red line indicates where the maximum kernel response lies, and thus the sync bias of this simfile. The white line is the kernel response for the whole fingerprint vs. local time.
53
+
1. Once the status bar indicates the job is "Done!", the number of paradigm-adherent simfiles will appear above the results table.
54
+
1. Feel free to "View logs", "View plots", or double-click on individual simfiles in the results table to reload plots in the neighboring pane.
55
+
1. In the future, the two arrows above the paradigm counts will allow you to batch adjust the sync bias on simfiles (either from +9ms to null, or vice versa). ***Again, not a millisecond-accurate sync utility! It's only offering to add or subtract 9ms.***
56
+
57
+
(If your computer starts really chugging during the bias check, bump the "Spectral step" up or the "Spectral window" down - both of these sacrifice a bit of spectrogram precision but the results are still generally good.)
58
+
59
+
## Future plans
60
+
- Batch adjust the sync bias on simfiles (either from +9ms to null, or vice versa)
61
+
- Handle split timing properly when it's present
62
+
- If a straight vertical line "fit" can identify bias, then a line fit with both local time and beat index dependence could also identify sync drift...hmm...
63
+
64
+
65
+
----
66
+
Also there's a little broom closet in this repo where I was doing some testing on rhythmic complexity algorithms. Don't worry about that for now ;)
label=re.sub('\n[ \t]+', '\n', """+9ms or Null? is a StepMania simfile sync bias utility.
26
+
label=re.sub('\n[ \t]+', '\n', """+9ms or Null? is a StepMania simfile unbiasing utility.
27
27
28
-
This utility can determine whether the sync bias of a simfile or a pack is +9ms (In The Groove) or null (general StepMania) and offer to unify it under one of those two options.
28
+
This utility can determine whether the sync bias of a simfile or a pack is +9ms (In The Groove) or null (general StepMania). A future version will also offer to unify it under one of those two options.
29
29
It is not meant to perform a millisecond-perfect sync!
30
30
31
31
You can read more about the origins of the +9ms sync bias here:"""),
0 commit comments