/ proof-of-concept / instrawave-compose
Sign in
proof-of-concept / instrawave-compose
instrawave-compose / src / render / types.ts
27 lines · 1.2 KBBlameHistoryRaw
1/**
2 * The seam between the analysis half and the sound half. Everything above
3 * this interface deals in NoteEvents (a time, a voice, a strength);
4 * everything below turns them into audio. A voice's binding names either a
5 * placeholder synth preset or an instrawave instrument with tuning
6 * overrides; the mixer in main.ts sends each event down the right path and
7 * touches the GPU only when at least one bound instrument is instrawave.
8 */
9export interface NoteEvent {
10 t: number; // seconds from the start of the take
11 voiceId: string;
12 gain: number; // linear, 0..1, from the hit's measured loudness
15export type SynthPreset = 'kick' | 'snare' | 'hat' | 'tom';
17export type Binding =
18 | { kind: 'synth'; preset: SynthPreset }
19 | { kind: 'iw'; instrument: string; set: Record<string, number> };
21/** Map a hit's peak level to a note strength. Levels are taken relative to
22 * the loudest hit in the take and compressed (0.5 exponent over a 30 dB
23 * window), so soft hits stay audible while the ordering is preserved. */
24export function gainFromPeakDb(peakDb: number, refDb: number): number {
25 const rel = Math.max(-30, Math.min(0, peakDb - refDb));
26 return Math.pow(10 ** (rel / 20), 0.5);
↑↓ move↵openescclose