Clicking the Recording / MIDI lane places a dashed mark (nothing else changes); the Pair box
shows both as editable times (m:ss.s or seconds), R / M drop a mark at the playhead, the ▶
buttons audition each track from its mark, Link (Enter) turns them into one manual anchor
(undoable; order conflicts with your anchors are explained and the marks kept), Esc clears.
The ruler sets the playback cursor; anchors are dragged by their handles. Recording and MIDI
volume sliders (0-150 %, Web Audio gain, remembered). Waveform pyramids are built in slices,
previews cached by anchors client-side, fit not re-requested when unchanged, debounce 200 ms.
Help panel updated.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The MIDI preview render (~2 s for a 5 min song) and auto-align ran synchronously on the
server's event loop, and each preview was a 12.4 MB WAV. Renders now run as 4 parallel time
chunks (2 s pre-roll, 10 ms cross-fade) on worker threads, auto-align on its own worker, and
previews are mono Ogg Opus 48 kb/s via ffmpeg (1.5 MB, same timing as the WAV in Chrome).
?format=wav keeps the PCM output. Swimming: render 2.0 s -> 0.65 s + 0.6 s encode; event loop
blocked 2.0 s -> <0.1 s per render.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
- Return an unchanged copy for a non-finite/zero grid (NaN downbeat used to
delete every guitar note).
- Skip an added note when a same-pitch note (bar, neighbouring bars or already
added) lies within tol; avoids near-duplicates across bar lines.
- bench run/real: --no-repeat-vote passes { repeatVote: false } to the pipeline.
- Tests: notes before a late downbeat, bpm 0 / NaN / Infinity, trailing partial
bar, half-tempo grid, neighbour-bar duplicate, pipeline-level on/off.
Eval unchanged: synthetic t1a 0.885 t1b 0.840 t1c 0.752 t1d 0.737, lnoe 0.507.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Bars whose transcriptions are similar (16th-slot occupancy cosine >= 0.6,
diagonal-smoothed, and exact pitch/onset match >= 0.3) are treated as repeats.
Notes recurring in < 15% of a bar's repeats are dropped; notes in >= 25% and
>= 3 repeats but missing from the bar are added. Default on for guitar.
Synthetic median guitar F1 t1a 0.866->0.885, t1b 0.814->0.840,
t1c 0.734->0.752, t1d 0.721->0.737; lnoe 0.403->0.507.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Demucs-6s scatters guitar energy across its guitar, piano and other stems.
Synthetic t1 median guitar F1 rises from 0.39-0.60 to 0.72-0.87; the real
'Last Night on Earth' reference goes 0.390 -> 0.403.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Fit flags on precision (<0.6) and chance-corrected lift (<0.25), null with <8
recording onsets; old match rate kept as audibleRate (info). Symbolic-chroma
beat/bar-shift check per window. Constant-offset baseline (-2..+2 s) replaces
DTW without manual anchors unless DTW precision is better by >=0.02. Stretch
warning counts in the fit summary. DTW: slope-limited steps, open begin/end
options; per-bar outlier rejection (1/4 beat, Theil-Sen-transported +-3 bar
median); no anchor in the final partial bar. bench real: saved/computed
source, baseline + method, corrupt alignment.json skipped. Parabolic onset
interpolation; warp extrapolation documented; spec amended.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
- server: collapse leading slashes so //host/x is never proxied off-host
or redirected cross-origin; 1 MB body limit; max 10k anchors; a corrupt
alignment.json no longer 500s /api/songs (song falls back to auto with
a warning); comments on cookie scope and the loopback inner server
- warp (ruling A6): adding/moving a manual anchor removes autos only
within 10 s (MIDI) of the new/old position, never past a manual, plus
any auto that would break audio monotonicity
- page: first anchor clamped at >= 0 s; ruler scrubbing seeks on release;
wording for the new auto-removal rule; removed-count excludes the
dragged anchor; shows server warnings
- manifest: unique tmp name for alignment.json; clear error for a
corrupt file
- resample test: speed asserted as a ratio to the direct path
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Token-protected Bun.serve server (bun run align [--host] [--port]
[--url-host] [--root]) with the layout-A page: recording and warped-MIDI
lanes on one zoomable timeline, draggable anchors (recording end / MIDI
end), stretch tempo labels with warnings, fit-flagged windows, Web Audio
playback with mix choice, auto-align, save, reset, undo. API per the task
brief; transcode/peaks cache under reference/<id>/. Adds bun run align
auto <id>, writeSmf (tests), encodeWav, recordingOnsets/fitFromOnsets,
fitSummary and stretch tempo helpers.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2:1 decimation (44.1k -> 22.05k, used to render the warped MIDI for the
alignment page) recomputed 65 windowed-sinc taps per output sample: ~17 s
for a 4.7 min stereo render. Outputs at integer input positions now reuse
one tap table; arithmetic is identical, so results are bit-identical.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The coarse-path fallback now expands each 10 Hz step to five 50 Hz steps so its
diagonals still yield bar anchors; fine band widths are injectable to test it.
Offset pooling is clipped to the current segment, and auto anchors need
audioSec > 0 unless midiSec is 0. Tests: forced fallback, wrong manual anchor,
p90 bound; debug output gated behind ALIGN_DEBUG.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Coarse (10 Hz) DTW per stretch between manual anchors, refined at 50 Hz in a
band that widens 0.5 -> 1 -> 2 s on unreachable end cells (coarse path as last
resort); one auto anchor per bar from median offsets of diagonal path steps.
Fit quality from raw-audio onset peaks vs warped scored-role MIDI onsets
(+-70 ms, 30 s windows, flagged on rate < 0.5 or median > 60 ms).
trackKeys moves to src/align/roles.ts (pure) and is re-exported by manifest.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Radix-2 FFT and torch-compatible stft/istft (hann, center, reflect,
normalized). HTDemucs-6s ONNX separator mirroring demucs apply_model:
whole-mix normalisation, 343980-sample centred segments, 25% overlap
with triangular weights, _spec/_ispec around the graph, spectral +
time branch sum. Brief's guitar/bass > 3 dB criterion is unmet by the
model on t1b/1 and is kept as test.failing pending a ruling.
Co-Authored-By: Claude Opus 5.5 <[email protected]>