#12 (order the set into a BPM arc) has been blocked on three tempo questions, and
they were framed as things PLN had to decide. Two of them are measurable.
FIRST, ONE DISSOLVED ON INSPECTION. you_my_sunshine was recorded as "144 measured vs
166 written", a 22 BPM gap big enough to INVERT the planned rising finish
Mafia(160)->Sunshine(166). The file has two setcps lines and the 144 one is COMMENTED
OUT. The active tempo is 166, the backlog was right all along, and the "mismatch" was
a grep reading a comment. That is the parsers-over-copy lesson again: a parser miss
must never masquerade as a data conflict. (My own first re-extraction then mangled
every number by using `tr -d '/60'`, which deletes the digits 6 and 0 — 160 became 1.
Two parsing bugs in one sitting, on four-line shell one-liners.)
SECOND, THE REAL QUESTION NEEDS AUDIO. gimme_acid declares 80 while the backlog calls
it 160, and `setcps` cannot settle it: setcps(80/60/4) declares four beats per cycle
at 80, but whether that is HEARD as 80 or 160 depends on what the patterns put inside
the cycle. Half-time notation is standard in dnb. This decides whether the track sits
beside the 160 BPM peak or is the second-slowest thing in the set.
So: spectral-flux novelty curve -> autocorrelation -> the fastest pulse that explains
the signal, reported together with its half/double family, because tempo from audio
is only ever determined up to a factor of two and pretending otherwise is the error.
BUILT THE KATANA FIRST, and it needed four passes — every one caught on synthetic
click tracks of KNOWN tempo before the tool informed any decision:
1. Inter-onset-interval MODE. Failed on the first real track: gimme_acid's d1 is a
continuous 303 line whose flux peaks every ~80 ms of internal movement, so the
modal gap gave "750 events/min". Counting gaps between events cannot find a beat
when the events are not beats. -> autocorrelation, which asks about PERIODICITY
and is unbothered by extra onsets inside each period.
2. Octave errors: a clean 124 click read 61.9, a clean 160 read 80.0 — exactly half,
correlation 0.85+, confidently wrong. Cause: at 100 Hz frames the true lag 48.39
must round to 48, which misaligns every later beat, while exactly 2x landed on a
whole frame. -> 200 Hz frames + 15 ms Gaussian smoothing, so a fractional period
still matches itself.
3. A uniform +1.8% bias (~2 BPM at techno tempo — enough to swap a 124 and a 127 in
a set order). Suspected the unnormalised overlap in np.correlate, fixed that too,
and the bias did not budge. The actual cause: the shortest-lag-within-12% rule,
written to choose between octaves, was also sliding down the LEFT FLANK of the
correct peak — comparing points on one hill as if they were different hills.
-> candidates restricted to local maxima, plus parabolic interpolation.
Result: 13/13 synthetic cases within 0.03%, including jittered, noisy, offbeat-8ths,
and the half-time case (80 BPM with 16th kicks correctly reads 160 felt).
A tempo number that is 2% wrong looks perfectly reasonable, which is exactly why this
had to be calibrated against known truth instead of eyeballed against real audio.
| Name |
Last commit
|
Last update |
|---|---|---|
| .gitea/workflows | Loading commit data... | |
| armada | Loading commit data... | |
| blocks | Loading commit data... | |
| blog | Loading commit data... | |
| copycat | Loading commit data... | |
| docs | Loading commit data... | |
| gifts | Loading commit data... | |
| lib-parvagues | Loading commit data... | |
| live | Loading commit data... | |
| output | Loading commit data... | |
| releases | Loading commit data... | |
| sandbox | Loading commit data... | |
| study | Loading commit data... | |
| test | Loading commit data... | |
| tools | Loading commit data... | |
| utils | Loading commit data... | |
| visuals/slop | Loading commit data... | |
| viz | Loading commit data... | |
| .gitignore | Loading commit data... | |
| BootTidal.hs | Loading commit data... | |
| BootTidal.hs.broken | Loading commit data... | |
| BootTidal.visuals.broken.hs | Loading commit data... | |
| CLAUDE.md | Loading commit data... | |
| FOH_MASTER.md | Loading commit data... | |
| LICENSE | Loading commit data... | |
| PatchBay_MultiChannel.xml | Loading commit data... | |
| PatchBay_Perf.xml | Loading commit data... | |
| PatchBay_Perf5.1.xml | Loading commit data... | |
| README.md | Loading commit data... | |
| RUNBOOK.md | Loading commit data... | |
| SHOPPING_LIST.md | Loading commit data... | |
| backlog.md | Loading commit data... | |
| bullet_train.tidal | Loading commit data... | |
| collide.sh | Loading commit data... | |
| debug.tidal | Loading commit data... | |
| didacticpatternvisualizer.pde | Loading commit data... | |
| gig-up.sh | Loading commit data... | |
| gpu-mode.sh | Loading commit data... | |
| hello.sc | Loading commit data... | |
| init_midi.sh | Loading commit data... | |
| intro.md | Loading commit data... | |
| library.txt | Loading commit data... | |
| link_jack.sh | Loading commit data... | |
| link_samples.sh | Loading commit data... | |
| link_samples_all.txt | Loading commit data... | |
| main_fairbanks.scd | Loading commit data... | |
| notes.md | Loading commit data... | |
| parvagues-sc.service | Loading commit data... | |
| perf-audio.sudoers | Loading commit data... | |
| perf-tray.py | Loading commit data... | |
| perf.sh | Loading commit data... | |
| samples.txt | Loading commit data... | |
| setlist_opal2026.txt | Loading commit data... | |
| start_and_midi.scd | Loading commit data... | |
| test.tidal | Loading commit data... |