import type { NoteInputEvent } from './webmidi.ts'; // Captures note input against the transport clock while recording. Times // are seconds on the song timeline; the store converts to ticks when the // take is committed. export interface CapturedNote { startSec: number; endSec: number; pitch: number; velocity: number; // 1..127 } export class Recorder { private active = false; private open = new Map(); private captured: CapturedNote[] = []; get isActive(): boolean { return this.active; } start(): void { this.active = true; this.open.clear(); this.captured = []; } noteEvent(e: NoteInputEvent, songSec: number): void { if (!this.active) return; if (e.on) { this.open.set(e.pitch, { startSec: songSec, velocity: e.velocity }); } else { const o = this.open.get(e.pitch); if (!o) return; this.open.delete(e.pitch); this.captured.push({ startSec: o.startSec, endSec: Math.max(o.startSec + 0.03, songSec), pitch: e.pitch, velocity: o.velocity }); } } stop(atSongSec: number): CapturedNote[] { for (const [pitch, o] of this.open) { this.captured.push({ startSec: o.startSec, endSec: Math.max(o.startSec + 0.03, atSongSec), pitch, velocity: o.velocity }); } this.open.clear(); this.active = false; const out = this.captured.sort((a, b) => a.startSec - b.startSec); this.captured = []; return out; } }