fix(pipeline): repeat-vote review fixes

- 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]>
This commit is contained in:
Lucas Winther
2026-10-30 21:21:00 +01:00
co-authored by Claude Opus 5.5
parent 79130c0aca
commit 48ae9780a6
6 changed files with 87 additions and 12 deletions
+3 -1
View File
@@ -25,11 +25,13 @@ async function sha256(bytes: Uint8Array): Promise<string> {
export async function runBench(opts: {
tiers: TierId[]; seeds: number[]; modes: string[]; runId: string; root: string; out: string; resultsDir?: string;
/** Guitar repetition voting (default on); false = --no-repeat-vote. */
repeatVote?: boolean;
}): Promise<BenchRun> {
for (const m of opts.modes) if (!Object.hasOwn(MODES, m)) throw new Error(`unknown mode: ${m}`);
const demucs = new Uint8Array(await Bun.file(MODEL_PATHS.demucs).arrayBuffer());
const basicPitch = new Uint8Array(await Bun.file(MODEL_PATHS.basicPitch).arrayBuffer());
const pipeline = await createPipeline({ demucs, basicPitch }); // model load once per run
const pipeline = await createPipeline({ demucs, basicPitch }, { repeatVote: opts.repeatVote ?? true }); // model load once per run
const run: BenchRun = {
runId: opts.runId,
date: new Date().toISOString(),