@libraz/libsonare 1.4.1 → 1.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/README.md +51 -20
  2. package/dist/index.d.ts +5416 -1
  3. package/dist/index.js +938 -583
  4. package/dist/index.js.map +1 -1
  5. package/dist/sonare.js +2 -2
  6. package/dist/sonare.wasm +0 -0
  7. package/dist/worklet.d.ts +1083 -5227
  8. package/dist/worklet.js +2683 -2451
  9. package/dist/worklet.js.map +1 -1
  10. package/package.json +4 -9
  11. package/src/clip_page_streamer.ts +298 -0
  12. package/src/effects_mastering.ts +85 -1089
  13. package/src/effects_transform.ts +286 -0
  14. package/src/effects_voice_change.ts +118 -0
  15. package/src/feature_music.ts +5 -2
  16. package/src/feature_spectrogram.ts +42 -2
  17. package/src/features.ts +1 -0
  18. package/src/index.ts +23 -0
  19. package/src/mastering_chain.ts +200 -0
  20. package/src/mastering_core.ts +248 -0
  21. package/src/mastering_dynamics.ts +105 -0
  22. package/src/mastering_repair.ts +161 -0
  23. package/src/mixer.ts +8 -0
  24. package/src/mixing_oneshot.ts +54 -0
  25. package/src/module_state.ts +1 -2
  26. package/src/project.ts +71 -1712
  27. package/src/project_class.ts +871 -0
  28. package/src/project_internal.ts +333 -0
  29. package/src/project_synth.ts +43 -0
  30. package/src/project_types.ts +570 -0
  31. package/src/public_types.ts +6 -1221
  32. package/src/public_types_acoustic.ts +115 -0
  33. package/src/public_types_mastering.ts +333 -0
  34. package/src/public_types_mixing.ts +97 -0
  35. package/src/public_types_music.ts +352 -0
  36. package/src/public_types_realtime.ts +163 -0
  37. package/src/public_types_spectral.ts +194 -0
  38. package/src/realtime_engine.ts +94 -0
  39. package/src/sonare.js.d.ts +117 -38
  40. package/src/stream_analyzer.ts +3 -0
  41. package/src/stream_types.ts +4 -0
  42. package/src/worklet/engine-automation.ts +73 -0
  43. package/src/worklet/engine-capture-facade.ts +80 -0
  44. package/src/worklet/engine-clips.ts +71 -0
  45. package/src/worklet/engine-markers.ts +93 -0
  46. package/src/worklet/engine-mixer-facade.ts +186 -0
  47. package/src/worklet/engine-node.ts +451 -0
  48. package/src/worklet/engine-offline.ts +162 -0
  49. package/src/worklet/engine-options.ts +13 -0
  50. package/src/worklet/engine-parameter-facade.ts +172 -0
  51. package/src/worklet/engine-processor.ts +764 -0
  52. package/src/worklet/engine-register.ts +136 -0
  53. package/src/worklet/engine-strips.ts +315 -0
  54. package/src/worklet/engine-sync.ts +94 -0
  55. package/src/worklet/engine-tempo-facade.ts +141 -0
  56. package/src/worklet/engine.ts +998 -0
  57. package/src/worklet/guards.ts +14 -1
  58. package/src/worklet/messages.ts +60 -20
  59. package/src/worklet/mixer-processor.ts +368 -0
  60. package/src/worklet/protocol.ts +3 -0
  61. package/src/worklet/voice-changer-processor.ts +246 -0
  62. package/src/worklet.ts +20 -3549
  63. package/dist/sonare-rt-module.js +0 -2
  64. package/dist/sonare-rt.js +0 -2
  65. package/dist/sonare-rt.wasm +0 -0
  66. package/src/sonare-rt.d.ts +0 -93
@@ -0,0 +1,570 @@
1
+ import type { Project } from './project_class';
2
+
3
+ // ============================================================================
4
+ // Headless DAW Project
5
+ // ============================================================================
6
+
7
+ /**
8
+ * Expected project ABI version. Mirrors `SONARE_PROJECT_ABI_VERSION` in
9
+ * `src/sonare_c_project.h`; checked against {@link projectAbiVersion} to detect
10
+ * a WASM build whose flat project POD layout has drifted from this wrapper.
11
+ */
12
+ export const EXPECTED_PROJECT_ABI_VERSION = 1;
13
+
14
+ /** Render options for {@link Project.bounce}. All fields are optional. */
15
+ export interface ProjectBounceOptions {
16
+ /** Render length in frames at the output sample rate. */
17
+ totalFrames?: number;
18
+ /** Render block size; <= 0 uses the engine default (128). */
19
+ blockSize?: number;
20
+ /** Output channel count; <= 0 uses the default (2). */
21
+ numChannels?: number;
22
+ /** Output sample rate; <= 0 uses the project sample rate. */
23
+ sampleRate?: number;
24
+ /** Host-instrument PDC (latency) fed to the compiler. */
25
+ instrumentLatencySamples?: number;
26
+ }
27
+
28
+ /**
29
+ * Marker kind ordinals. Mirrors `SonareMarkerKind` in `src/sonare_c_types.h`;
30
+ * the values are part of the ABI and must not be renumbered.
31
+ */
32
+ export const MarkerKind = {
33
+ marker: 0,
34
+ text: 1,
35
+ lyric: 2,
36
+ cuePoint: 3,
37
+ keySignature: 4,
38
+ } as const;
39
+
40
+ /** A project timeline marker with its kind and (for key signatures) the key. */
41
+ export interface ProjectMarker {
42
+ /** Stable marker id (0 when allocating a new id via {@link Project.setMarkerEx}). */
43
+ id: number;
44
+ /** Marker position in PPQ (quarter notes). */
45
+ ppq: number;
46
+ /** Marker label. */
47
+ name?: string;
48
+ /** {@link MarkerKind} ordinal (default 0 = marker). */
49
+ kind?: number;
50
+ /** Key signature only: -7..7 (sharps positive). */
51
+ keyFifths?: number;
52
+ /** Key signature only: false = major, true = minor. */
53
+ keyMinor?: boolean;
54
+ }
55
+
56
+ /** Oscillator waveform for the built-in synth. */
57
+ export type BuiltinSynthWaveform =
58
+ | 'sine'
59
+ | 'saw'
60
+ | 'sawtooth'
61
+ | 'square'
62
+ | 'triangle'
63
+ | 0
64
+ | 1
65
+ | 2
66
+ | 3;
67
+
68
+ /**
69
+ * Built-in synth patch + MIDI routing for
70
+ * {@link Project.bounceWithBuiltinInstrument}. Every field is optional; a
71
+ * non-positive (or omitted) numeric field falls back to the C-ABI default
72
+ * (gain 0.2, attack 5ms, decay 60ms, sustain 0.7, release 120ms, 16 voices),
73
+ * so `{}` is a usable default sine patch.
74
+ */
75
+ export interface BuiltinSynthBinding {
76
+ /** MIDI destination id this patch answers to (default 0; see {@link Project.setTrackMidiDestination}). */
77
+ destinationId?: number;
78
+ /** Oscillator waveform (default `'sine'`). */
79
+ waveform?: BuiltinSynthWaveform;
80
+ /** Master output gain, linear (0 => 0.2). */
81
+ gain?: number;
82
+ /** ADSR attack in ms (0 => 5). */
83
+ attackMs?: number;
84
+ /** ADSR decay in ms (0 => 60). */
85
+ decayMs?: number;
86
+ /** ADSR sustain level [0,1] (0 => 0.7). */
87
+ sustain?: number;
88
+ /** ADSR release in ms (0 => 120). */
89
+ releaseMs?: number;
90
+ /** Max simultaneous voices (0 => 16, clamped to [1, 64]). */
91
+ polyphony?: number;
92
+ }
93
+
94
+ /**
95
+ * Cross-binding alias of {@link BuiltinSynthBinding}. The same built-in-synth
96
+ * patch concept is named `BuiltinSynthConfig` in the Python binding; this alias
97
+ * lets portable code use that shared name on the WASM surface too.
98
+ */
99
+ export type BuiltinSynthConfig = BuiltinSynthBinding;
100
+
101
+ /**
102
+ * SoundFont (SF2) player patch + MIDI routing for
103
+ * {@link Project.bounceWithSf2Instrument}. Every field is optional; a
104
+ * non-positive (or omitted) numeric field falls back to the C-ABI default
105
+ * (gain 0.5, 48 voices), so `{}` is a usable default patch.
106
+ */
107
+ export interface Sf2InstrumentConfig {
108
+ /** MIDI destination id this player answers to (default 0; see {@link Project.setTrackMidiDestination}). */
109
+ destinationId?: number;
110
+ /** Master output gain, linear (0 => 0.5). */
111
+ gain?: number;
112
+ /** Max simultaneous voices (0 => 48, clamped to [1, 64]). */
113
+ polyphony?: number;
114
+ }
115
+
116
+ /** Source backend a resolved MIDI program renders through. */
117
+ export type SourceBackend = 'sf2' | 'synth';
118
+
119
+ /**
120
+ * One {@link Project.soundFontManifest} entry: a (channel, bank, program)
121
+ * combination the arrangement plays, with the backend it resolves to.
122
+ */
123
+ export interface Sf2ProgramStatus {
124
+ /** MIDI channel (0-15). */
125
+ channel: number;
126
+ /** Effective SF2 bank (drum channels report 128). */
127
+ bank: number;
128
+ /** Program number (0-127). */
129
+ program: number;
130
+ /** `'sf2'` when the loaded SoundFont covers the program, else `'synth'`. */
131
+ backend: SourceBackend;
132
+ /** Resolved SF2 preset name (GS fallback included); empty for `'synth'`. */
133
+ presetName: string;
134
+ }
135
+
136
+ export const SYNTH_ENGINE_MODES = [
137
+ 'default',
138
+ 'subtractive',
139
+ 'fm',
140
+ 'karplus-strong',
141
+ 'modal',
142
+ 'additive',
143
+ 'percussion',
144
+ 'piano',
145
+ 'pipe-organ',
146
+ 'bowed-string',
147
+ 'reed',
148
+ 'brass',
149
+ 'flute',
150
+ 'plucked-string',
151
+ 'vocal',
152
+ 'free-reed',
153
+ ] as const;
154
+ export const SYNTH_OSC_WAVEFORMS = [
155
+ 'default',
156
+ 'sine',
157
+ 'saw',
158
+ 'square',
159
+ 'triangle',
160
+ 'noise',
161
+ ] as const;
162
+ export const SYNTH_FILTER_MODELS = [
163
+ 'default',
164
+ 'svf',
165
+ 'moog-ladder',
166
+ 'diode-ladder',
167
+ 'sallen-key',
168
+ ] as const;
169
+ export const SYNTH_FILTER_OUTPUTS = ['default', 'lowpass', 'bandpass', 'highpass'] as const;
170
+ export const SYNTH_BODY_TYPES = [
171
+ 'default',
172
+ 'none',
173
+ 'guitar',
174
+ 'violin',
175
+ 'wood-tube',
176
+ 'brass-bell',
177
+ 'vocal',
178
+ ] as const;
179
+ export const SYNTH_MOD_SOURCES = [
180
+ 'none',
181
+ 'amp-env',
182
+ 'filter-env',
183
+ 'lfo1',
184
+ 'lfo2',
185
+ 'velocity',
186
+ 'key-track',
187
+ 'mod-wheel',
188
+ 'random',
189
+ ] as const;
190
+ export const SYNTH_MOD_DESTINATIONS = [
191
+ 'none',
192
+ 'pitch-cents',
193
+ 'cutoff-cents',
194
+ 'amp-gain',
195
+ 'pan-units',
196
+ ] as const;
197
+
198
+ export interface SynthEnumTables {
199
+ engineModes: string[];
200
+ waveforms: string[];
201
+ filterModels: string[];
202
+ filterOutputs: string[];
203
+ bodyTypes: string[];
204
+ modSources: string[];
205
+ modDestinations: string[];
206
+ }
207
+
208
+ /** NativeSynth engine selector ({@link SynthPatch}; `'default'` keeps the base patch's). */
209
+ export type SynthEngineMode = (typeof SYNTH_ENGINE_MODES)[number];
210
+
211
+ /** NativeSynth oscillator waveform (`'default'` keeps the base patch's). */
212
+ export type SynthOscWaveform = (typeof SYNTH_OSC_WAVEFORMS)[number];
213
+
214
+ /** NativeSynth filter model — the character core (`'default'` keeps the base patch's). */
215
+ export type SynthFilterModel = (typeof SYNTH_FILTER_MODELS)[number];
216
+
217
+ /** NativeSynth filter output (SVF only; `'default'` keeps the base patch's). */
218
+ export type SynthFilterOutput = (typeof SYNTH_FILTER_OUTPUTS)[number];
219
+
220
+ /** NativeSynth body/formant resonance voicing (`'default'` keeps the base patch's). */
221
+ export type SynthBodyType = (typeof SYNTH_BODY_TYPES)[number];
222
+
223
+ /** {@link SynthPatch} mod-matrix source. */
224
+ export type SynthModSource = (typeof SYNTH_MOD_SOURCES)[number];
225
+
226
+ /** {@link SynthPatch} mod-matrix destination. */
227
+ export type SynthModDestination = (typeof SYNTH_MOD_DESTINATIONS)[number];
228
+
229
+ /** One {@link SynthPatch} mod-matrix routing (name or C ordinal per field). */
230
+ export interface SynthModRouting {
231
+ source: SynthModSource | number;
232
+ destination: SynthModDestination | number;
233
+ /** Destination units at full source deflection. */
234
+ depth: number;
235
+ }
236
+
237
+ /**
238
+ * Versioned NativeSynth patch for {@link Project.bounceWithSynthInstrument}
239
+ * and {@link RealtimeEngine.setSynthInstrument}.
240
+ *
241
+ * The patch starts from a BASE — the named `preset` (see
242
+ * {@link synthPresetNames}; a `"va:"` routing prefix is accepted) or, when
243
+ * `preset` is omitted, the default subtractive patch. Every numeric field then
244
+ * uses "0 / omit => keep the base value" (non-zero values override, clamped to
245
+ * their audible ranges) and the enum fields reserve `'default'` as keep. The
246
+ * frozen C ABI has no per-field presence bits, so explicit zero numeric
247
+ * overrides (for example `ampSustain: 0`) cannot be represented; they keep the
248
+ * base value. A non-empty `modRoutings` REPLACES the base mod matrix.
249
+ *
250
+ * Mode-specific deep parameters (FM operator stacks, modal mode tables,
251
+ * drawbar registrations, kit pieces, piano strings) travel inside the named
252
+ * presets; the patch exposes the wrapper sections every engine shares.
253
+ */
254
+ export interface SynthPatch {
255
+ /**
256
+ * Optional binding convenience for JS realtime/offline helpers. It is not
257
+ * part of the NativeSynth patch itself; Python uses explicit
258
+ * `(destination_id, patch)` bindings instead. Defaults to `0`.
259
+ */
260
+ destinationId?: number;
261
+ /** Base preset name (see {@link synthPresetNames}); omit for the init patch. */
262
+ preset?: string;
263
+ engineMode?: SynthEngineMode | number;
264
+ waveform?: SynthOscWaveform | number;
265
+ /** Detuned-stack width [1, 7]. */
266
+ unison?: number;
267
+ detuneCents?: number;
268
+ /** Per-voice slow pitch drift depth (cents). */
269
+ driftCents?: number;
270
+ /** Pre-filter drive [0, 1]. */
271
+ drive?: number;
272
+ filterModel?: SynthFilterModel | number;
273
+ filterOutput?: SynthFilterOutput | number;
274
+ cutoffHz?: number;
275
+ resonanceQ?: number;
276
+ /** Cutoff keyboard tracking [0, 1]. */
277
+ keyTrack?: number;
278
+ envToCutoffCents?: number;
279
+ velToCutoffCents?: number;
280
+ ampAttackMs?: number;
281
+ ampDecayMs?: number;
282
+ /** 0 / omit keeps the base value; explicit zero sustain is not representable. */
283
+ ampSustain?: number;
284
+ ampReleaseMs?: number;
285
+ filterAttackMs?: number;
286
+ filterDecayMs?: number;
287
+ /** 0 / omit keeps the base value; explicit zero sustain is not representable. */
288
+ filterSustain?: number;
289
+ filterReleaseMs?: number;
290
+ lfoRateHz?: number;
291
+ lfoToPitchCents?: number;
292
+ lfo2RateHz?: number;
293
+ glideMs?: number;
294
+ body?: SynthBodyType | number;
295
+ /** Body resonance mix [0, 1]. */
296
+ bodyMix?: number;
297
+ /** Seeded per-voice pan scatter [0, 1]. */
298
+ stereoSpread?: number;
299
+ /** Mod matrix (at most 8 routings; REPLACES the base matrix when non-empty). */
300
+ modRoutings?: SynthModRouting[];
301
+ /** Master output gain (linear). */
302
+ gain?: number;
303
+ /** Max simultaneous voices [1, 64]. */
304
+ polyphony?: number;
305
+ /** Gain-neutral bus saturation [0, 1]. */
306
+ busDrive?: number;
307
+ }
308
+
309
+ /** Clip fade-curve for {@link Project.setClipFade}. */
310
+ export type ProjectFadeCurve =
311
+ | 'linear'
312
+ | 'equal-power'
313
+ | 'equal_power'
314
+ | 'equalPower'
315
+ | 'exponential'
316
+ | 'logarithmic'
317
+ | 0
318
+ | 1
319
+ | 2
320
+ | 3;
321
+
322
+ /** One clip fade region for {@link Project.setClipFade}. */
323
+ export interface ProjectClipFade {
324
+ /** Fade length in PPQ (>= 0; 0 = no fade). */
325
+ lengthPpq?: number;
326
+ /** Fade curve (default `'linear'`). */
327
+ curve?: ProjectFadeCurve;
328
+ }
329
+
330
+ /** One alternate take for {@link Project.setClipTakes}. */
331
+ export interface ProjectClipTake {
332
+ id: number;
333
+ sourceId?: number;
334
+ sourceOffsetPpq?: number;
335
+ name?: string;
336
+ }
337
+
338
+ /** One comp segment for {@link Project.setClipCompSegments}. */
339
+ export interface ProjectClipCompSegment {
340
+ startPpq: number;
341
+ endPpq: number;
342
+ takeId?: number;
343
+ }
344
+
345
+ /** Descriptor for {@link Project.addLoopRecordingTakes}. */
346
+ export interface ProjectLoopRecordingDesc {
347
+ trackId: number;
348
+ startPpq?: number;
349
+ loopLengthPpq: number;
350
+ audio: Float32Array;
351
+ audioChannels?: number;
352
+ audioSampleRate?: number;
353
+ }
354
+
355
+ /** Result returned by {@link Project.addLoopRecordingTakes}. */
356
+ export interface ProjectLoopRecordingResult {
357
+ clipId: number;
358
+ takeCount: number;
359
+ }
360
+
361
+ /** Clip loop mode for {@link Project.setClipLoop}. */
362
+ export type ProjectLoopMode = 'off' | 'loop' | 0 | 1;
363
+ export type ProjectWarpMode = 'off' | 'repitch' | 'tempo-sync' | 0 | 1 | 2;
364
+
365
+ /** Automation breakpoint interpolation for {@link ProjectAutomationPoint}. */
366
+ export type ProjectAutomationCurve = 'linear' | 'exponential' | 'hold' | 'scurve' | 0 | 1 | 2 | 3;
367
+
368
+ /** One automation breakpoint accepted by the automation-lane edit ops. */
369
+ export interface ProjectAutomationPoint {
370
+ /** Breakpoint position in PPQ. */
371
+ ppq: number;
372
+ /** Breakpoint value. */
373
+ value: number;
374
+ /** Curve to the next breakpoint (default `'linear'`). */
375
+ curve?: ProjectAutomationCurve;
376
+ }
377
+
378
+ /** Automation-lane descriptor for {@link Project.addAutomationLane}. */
379
+ export interface ProjectAutomationLaneDesc {
380
+ /** Host-defined id of the parameter the lane drives. */
381
+ targetParamId: number;
382
+ /** Breakpoints (stored verbatim). */
383
+ points: ReadonlyArray<ProjectAutomationPoint>;
384
+ }
385
+
386
+ /** One tempo segment for {@link Project.setTempoSegments}. */
387
+ export interface ProjectTempoSegment {
388
+ /** Segment start in PPQ. */
389
+ startPpq: number;
390
+ /** Tempo in beats per minute at the segment start. */
391
+ bpm: number;
392
+ /** Derived segment start in samples. Accepted for compatibility, ignored on input. */
393
+ startSample?: number;
394
+ /** Optional ramp end tempo in BPM (0 = constant tempo over the segment). */
395
+ endBpm?: number;
396
+ }
397
+
398
+ /** One time-signature segment for {@link Project.setTimeSignatures}. */
399
+ export interface ProjectTimeSignatureSegment {
400
+ /** Segment start in PPQ. */
401
+ startPpq: number;
402
+ /** Beats per bar (time-signature numerator). */
403
+ numerator: number;
404
+ /** Beat unit (time-signature denominator, e.g. 4 or 8). */
405
+ denominator: number;
406
+ }
407
+
408
+ /** Key segment for {@link Project.annotateKeys}. */
409
+ export interface ProjectKeySegment {
410
+ startPpq: number;
411
+ endPpq: number;
412
+ /** Tonic pitch class 0..11 (C=0) or 255 for unknown. */
413
+ tonicPc?: number;
414
+ /** KeyMode ordinal (0 unknown, 1 major, 2 minor, 3 dorian, ...). */
415
+ mode?: number;
416
+ }
417
+
418
+ /** Chord symbol for {@link Project.annotateChords}. */
419
+ export interface ProjectChordSymbol {
420
+ startPpq: number;
421
+ endPpq: number;
422
+ /** Root pitch class 0..11 (C=0) or 255 for unknown. */
423
+ rootPc?: number;
424
+ /** ChordQuality ordinal (0 unknown, 1 major, 2 minor, ...). */
425
+ quality?: number;
426
+ /** Extension semitone offsets (up to 8). */
427
+ extensions?: ReadonlyArray<number>;
428
+ /** Slash-bass pitch class 0..11 or 255 for none. */
429
+ slashBassPc?: number;
430
+ /** Optional roman-numeral label. */
431
+ romanNumeral?: string;
432
+ /** True at a modulation boundary. */
433
+ modulationBoundary?: boolean;
434
+ }
435
+
436
+ /** Assist sidecar snapshot returned by {@link Project.getAssistSidecar}. */
437
+ export interface ProjectAssistSidecar {
438
+ moduleId: string;
439
+ schemaVersion: number;
440
+ targetTrackId: number;
441
+ regionStartPpq: number;
442
+ regionEndPpq: number;
443
+ payload: Uint8Array;
444
+ }
445
+
446
+ /** Track kind for {@link Project.addTrack}. */
447
+ export type ProjectTrackKind = 'audio' | 'midi' | 'aux' | 0 | 1 | 2;
448
+
449
+ /** Descriptor for {@link Project.addTrack}. */
450
+ export interface ProjectTrackDesc {
451
+ kind?: ProjectTrackKind;
452
+ name?: string;
453
+ }
454
+
455
+ export interface ProjectWarpAnchor {
456
+ warpSample: number;
457
+ sourceSample: number;
458
+ }
459
+
460
+ export interface ProjectWarpMapDesc {
461
+ id: number;
462
+ name?: string;
463
+ anchors: ProjectWarpAnchor[];
464
+ }
465
+
466
+ /** Descriptor for {@link Project.addClip}. */
467
+ export interface ProjectClipDesc {
468
+ trackId: number;
469
+ isMidi?: boolean;
470
+ startPpq?: number;
471
+ lengthPpq: number;
472
+ sourceOffsetPpq?: number;
473
+ gain?: number;
474
+ audio?: Float32Array;
475
+ audioChannels?: number;
476
+ audioSampleRate?: number;
477
+ sourceUri?: string;
478
+ }
479
+
480
+ /** Result returned by {@link Project.addMidiClip}. */
481
+ export interface ProjectMidiClipResult {
482
+ trackId: number;
483
+ clipId: number;
484
+ }
485
+
486
+ /** Flat MIDI event accepted by {@link Project.setMidiEvents}. */
487
+ export interface ProjectMidiEvent {
488
+ ppq: number;
489
+ data0: number;
490
+ data1?: number;
491
+ }
492
+
493
+ /** Options for {@link Project.midiRouteEvents}. `null`/omitted filter fields mean any/no remap. */
494
+ export interface ProjectMidiRouteConfig {
495
+ filterGroup?: number | null;
496
+ filterChannel?: number | null;
497
+ remapChannel?: number | null;
498
+ thru?: boolean;
499
+ }
500
+
501
+ /** Result of {@link Project.midiRouteEvents}. */
502
+ export interface ProjectMidiRouteResult {
503
+ events: ProjectMidiEvent[];
504
+ overflowed: boolean;
505
+ overflowCount: number;
506
+ }
507
+
508
+ export type ProjectMidiCcBindingKind = 0 | 1 | 2 | 3;
509
+
510
+ /** Options for {@link Project.midiCcLearn}. All fields are optional. */
511
+ export interface MidiCcLearnOptions {
512
+ /** Lower end of the mapped parameter range. Default `0`. */
513
+ minValue?: number;
514
+ /** Upper end of the mapped parameter range. Default `1`. */
515
+ maxValue?: number;
516
+ /** Minimum normalized CC movement required to learn a binding. Default `0`. */
517
+ minMovement?: number;
518
+ }
519
+
520
+ /** MIDI CC <-> automation binding descriptor used by CC learn/conversion helpers. */
521
+ export interface ProjectMidiCcBinding {
522
+ ccNumber: number;
523
+ /** MIDI channel 0..15, or 255 for any channel. */
524
+ channel: number;
525
+ /** 0 = 7-bit CC, 1 = 14-bit CC, 2 = RPN, 3 = NRPN. */
526
+ kind: ProjectMidiCcBindingKind;
527
+ ccLsbNumber?: number;
528
+ selectorMsb?: number;
529
+ selectorLsb?: number;
530
+ paramId: number;
531
+ minValue: number;
532
+ maxValue: number;
533
+ }
534
+
535
+ /** Result of {@link Project.validateMidiNotes}. */
536
+ export interface ProjectNotePairValidation {
537
+ /** True when every note-on has a matching note-off (and vice versa). */
538
+ ok: boolean;
539
+ /** Count of note-ons that never received a matching note-off. */
540
+ unmatchedNoteOns: number;
541
+ /** Count of note-offs with no preceding matching note-on. */
542
+ unmatchedNoteOffs: number;
543
+ }
544
+
545
+ /** One compile diagnostic (mirrors SonareProjectDiagnostic). */
546
+ export interface ProjectDiagnostic {
547
+ code: number;
548
+ /** 0 = error, 1 = warning. */
549
+ severity: number;
550
+ /** Affected clip / track / source id (0 = n/a). */
551
+ targetId: number;
552
+ /** Human-readable message for this diagnostic. */
553
+ message: string;
554
+ }
555
+
556
+ /** Diagnostics summary returned by {@link Project.compile}. */
557
+ export interface ProjectCompileResult {
558
+ /** Number of diagnostics surfaced by the compile. Kept for backward compatibility. */
559
+ diagnosticCount: number;
560
+ /** True when compilation produced a renderable timeline (no error diagnostics). */
561
+ hasTimeline: boolean;
562
+ /** Newline-joined human-readable detail of every diagnostic. */
563
+ messages: string;
564
+ diagnostics: ProjectDiagnostic[];
565
+ }
566
+
567
+ export interface ProjectDeserializeResult {
568
+ project: Project;
569
+ diagnostics: string;
570
+ }