/ proof-of-concept / midiboot
Sign in
proof-of-concept / midiboot
midiboot / src / instruments / types.ts
91 lines · 3.1 KBBlameHistoryRaw
1// The track-render instrument contract shared between midiboot and the
2// instrument web apps. Each simulated-instrument repo carries its own
3// structurally identical copy of these types (there is no shared package;
4// TypeScript's structural typing keeps the copies interchangeable), and
5// midiboot's src/instruments/types.ts is the reference.
6//
7// An instrument receives an entire MIDI track per call: every note with
8// times already in seconds. It owns its rendering strategy end to end,
9// including any internal caching (per-note, per-stage, or none), progress
10// reporting, and cancellation. The optional fields at the bottom exist for
11// the instrument's own web app, which drives the full parameter surface
12// and live-edited MATLAB sources; midiboot never sets them.
14export interface NoteSpec {
15 timeSec: number;
16 durationSec: number;
17 pitch: number; // MIDI note number
18 velocity: number; // 0..1
21/** A user-editable instrument parameter, declared by the instrument. */
22export interface KnobSpec {
23 key: string;
24 label: string;
25 min: number;
26 max: number;
27 default: number;
28 step?: number;
29 scale?: 'log';
32/** One MATLAB source file, as numbl consumes it. */
33export interface MFile {
34 name: string;
35 source: string;
38export interface RenderProgress {
39 /** 0..1 through the whole request. */
40 frac: number;
41 /** Short human-readable stage label, e.g. "note 3/8: solve". */
42 stage: string;
45export interface TrackRenderRequest {
46 /** Every note of the track, sorted by timeSec. */
47 notes: NoteSpec[];
48 sampleRate: number;
49 /** Song length incl. tail, as a minimum: the returned buffer may be
50 * longer, so a ring that outlives the last note (a cymbal crash, a
51 * long bass tail) is kept in full; the host mixes buffers of unequal
52 * lengths. */
53 lengthSamples: number;
54 /** Fast preview for playback, full quality for export. */
55 quality: 'preview' | 'full';
56 /** Values for the instrument's knobs; missing keys mean the default. */
57 settings?: Record<string, number>;
58 /** Cooperative cancellation; checked between stages and notes. */
59 signal?: AbortSignal;
60 onProgress?: (p: RenderProgress) => void;
62 // --- fields used only by the instrument's own web app ---
64 /** Full model parameter overrides, applied after the defaults (and after
65 * any note mapping). midiboot never sets this. */
66 params?: Record<string, number | boolean>;
67 /** Live-edited MATLAB sources replacing the shipped ones. */
68 mfiles?: MFile[];
69 /** Also compute the instrument-specific diagnostics payload. */
70 wantDiagnostics?: boolean;
73export interface TrackRenderResult {
74 audio: Float32Array;
75 /** Instrument-specific diagnostics; present only when requested. */
76 diag?: unknown;
79export interface LiveVoice {
80 noteOff(): void; // begin release
81 cut(): void; // stop immediately
84export interface Instrument {
85 id: string;
86 name: string;
87 /** Curated editable parameters; tracks store their values in settings. */
88 knobs?: KnobSpec[];
89 renderTrack(req: TrackRenderRequest): Promise<TrackRenderResult>;
90 noteOn?(ctx: BaseAudioContext, dest: AudioNode, pitch: number, velocity: number, whenSec: number): LiveVoice;
↑↓ move↵openescclose