feat: evaluation metrics

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
This commit is contained in:
Lucas Winther
2026-10-30 02:57:38 +01:00
co-authored by Claude Sonnet 5.5
parent 32d96cadcc
commit 6bd8ab9cee
6 changed files with 418 additions and 0 deletions
+21
View File
@@ -0,0 +1,21 @@
import { expect, test } from "bun:test";
import { alignGrid, rhythmScore } from "../../src/eval/rhythm.ts";
import type { ScoreNote } from "../../src/core/types.ts";
const sn = (a: number[][]): ScoreNote[] => a.map(([tick, dur, pitch]) => ({ tick: tick!, dur: dur!, pitch: pitch! }));
test("grid alignment: double tempo and one beat shift", () => {
const r = sn([[0, 240, 60], [960, 960, 62]]);
const e = sn([[960, 480, 60], [2880, 1920, 62]]);
expect(alignGrid(r, e)).toEqual({ factor: 2, beatOffset: 1 });
expect(rhythmScore(r, e, { factor: 2, beatOffset: 1 })).toEqual({ onBeat: 1, durationOk: 1 });
});
test("identity preferred and partial scores", () => {
const r = sn([[0, 480, 60], [960, 480, 62]]);
expect(alignGrid(r, r)).toEqual({ factor: 1, beatOffset: 0 });
const e = sn([[0, 480, 60], [1000, 240, 62]]);
expect(rhythmScore(r, e, { factor: 1, beatOffset: 0 })).toEqual({ onBeat: 0.5, durationOk: 0.5 });
});
test("no pitch matches -> null", () => {
expect(rhythmScore(sn([[0, 1, 60]]), sn([[0, 1, 61]]), { factor: 1, beatOffset: 0 })).toEqual({ onBeat: null, durationOk: null });
});