import { test, expect } from "bun:test"; import { avgBpm, stretchInfo, stretchLabel } from "../../src/align/tempo.ts"; import type { Stretch } from "../../src/align/warp.ts"; const map = [{ sec: 0, bpm: 120 }, { sec: 10, bpm: 60 }]; test("avgBpm: beats over seconds across tempo changes", () => { expect(avgBpm(map, 0, 10)).toBeCloseTo(120, 9); expect(avgBpm(map, 10, 20)).toBeCloseTo(60, 9); expect(avgBpm(map, 5, 15)).toBeCloseTo((10 + 5) / 10 * 60, 9); // 10 beats + 5 beats in 10 s = 90 bpm expect(avgBpm([], 0, 4)).toBeCloseTo(120, 9); // implicit 120 expect(avgBpm(map, 3, 3)).toBeCloseTo(120, 9); // empty span: tempo at that point }); test("stretchInfo: effective bpm = MIDI bpm / ratio, signed percent", () => { const s: Stretch[] = [{ fromMidi: 0, toMidi: 10, ratio: 120 / 121.68, warn: false }, { fromMidi: 10, toMidi: 20, ratio: 60 / 55, warn: true }]; const [a, b] = stretchInfo(s, map); expect(a!.midiBpm).toBeCloseTo(120, 9); expect(a!.bpm).toBeCloseTo(121.68, 6); expect(a!.pct).toBeCloseTo(1.4, 6); expect(b!.bpm).toBeCloseTo(55, 6); expect(stretchLabel(a!)).toBe("120.0 → 121.7 bpm (+1.4%)"); expect(stretchLabel(b!)).toBe("60.0 → 55.0 bpm (−8.3%) ⚠"); expect(stretchLabel({ ...a!, bpm: 120, pct: 0.01 })).toBe("120.0 → 120.0 bpm"); });