@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.
- package/README.md +51 -20
- package/dist/index.d.ts +5416 -1
- package/dist/index.js +938 -583
- package/dist/index.js.map +1 -1
- package/dist/sonare.js +2 -2
- package/dist/sonare.wasm +0 -0
- package/dist/worklet.d.ts +1083 -5227
- package/dist/worklet.js +2683 -2451
- package/dist/worklet.js.map +1 -1
- package/package.json +4 -9
- package/src/clip_page_streamer.ts +298 -0
- package/src/effects_mastering.ts +85 -1089
- package/src/effects_transform.ts +286 -0
- package/src/effects_voice_change.ts +118 -0
- package/src/feature_music.ts +5 -2
- package/src/feature_spectrogram.ts +42 -2
- package/src/features.ts +1 -0
- package/src/index.ts +23 -0
- package/src/mastering_chain.ts +200 -0
- package/src/mastering_core.ts +248 -0
- package/src/mastering_dynamics.ts +105 -0
- package/src/mastering_repair.ts +161 -0
- package/src/mixer.ts +8 -0
- package/src/mixing_oneshot.ts +54 -0
- package/src/module_state.ts +1 -2
- package/src/project.ts +71 -1712
- package/src/project_class.ts +871 -0
- package/src/project_internal.ts +333 -0
- package/src/project_synth.ts +43 -0
- package/src/project_types.ts +570 -0
- package/src/public_types.ts +6 -1221
- package/src/public_types_acoustic.ts +115 -0
- package/src/public_types_mastering.ts +333 -0
- package/src/public_types_mixing.ts +97 -0
- package/src/public_types_music.ts +352 -0
- package/src/public_types_realtime.ts +163 -0
- package/src/public_types_spectral.ts +194 -0
- package/src/realtime_engine.ts +94 -0
- package/src/sonare.js.d.ts +117 -38
- package/src/stream_analyzer.ts +3 -0
- package/src/stream_types.ts +4 -0
- package/src/worklet/engine-automation.ts +73 -0
- package/src/worklet/engine-capture-facade.ts +80 -0
- package/src/worklet/engine-clips.ts +71 -0
- package/src/worklet/engine-markers.ts +93 -0
- package/src/worklet/engine-mixer-facade.ts +186 -0
- package/src/worklet/engine-node.ts +451 -0
- package/src/worklet/engine-offline.ts +162 -0
- package/src/worklet/engine-options.ts +13 -0
- package/src/worklet/engine-parameter-facade.ts +172 -0
- package/src/worklet/engine-processor.ts +764 -0
- package/src/worklet/engine-register.ts +136 -0
- package/src/worklet/engine-strips.ts +315 -0
- package/src/worklet/engine-sync.ts +94 -0
- package/src/worklet/engine-tempo-facade.ts +141 -0
- package/src/worklet/engine.ts +998 -0
- package/src/worklet/guards.ts +14 -1
- package/src/worklet/messages.ts +60 -20
- package/src/worklet/mixer-processor.ts +368 -0
- package/src/worklet/protocol.ts +3 -0
- package/src/worklet/voice-changer-processor.ts +246 -0
- package/src/worklet.ts +20 -3549
- package/dist/sonare-rt-module.js +0 -2
- package/dist/sonare-rt.js +0 -2
- package/dist/sonare-rt.wasm +0 -0
- package/src/sonare-rt.d.ts +0 -93
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
import { getSonareModule } from './module_state';
|
|
2
|
+
import type {
|
|
3
|
+
BuiltinSynthBinding,
|
|
4
|
+
ProjectAutomationPoint,
|
|
5
|
+
ProjectBounceOptions,
|
|
6
|
+
ProjectChordSymbol,
|
|
7
|
+
ProjectClipCompSegment,
|
|
8
|
+
ProjectClipDesc,
|
|
9
|
+
ProjectClipFade,
|
|
10
|
+
ProjectClipTake,
|
|
11
|
+
ProjectCompileResult,
|
|
12
|
+
ProjectKeySegment,
|
|
13
|
+
ProjectLoopMode,
|
|
14
|
+
ProjectLoopRecordingDesc,
|
|
15
|
+
ProjectLoopRecordingResult,
|
|
16
|
+
ProjectMarker,
|
|
17
|
+
ProjectMidiCcBinding,
|
|
18
|
+
ProjectMidiClipResult,
|
|
19
|
+
ProjectMidiEvent,
|
|
20
|
+
ProjectMidiRouteConfig,
|
|
21
|
+
ProjectMidiRouteResult,
|
|
22
|
+
ProjectNotePairValidation,
|
|
23
|
+
ProjectTempoSegment,
|
|
24
|
+
ProjectTimeSignatureSegment,
|
|
25
|
+
ProjectTrackKind,
|
|
26
|
+
ProjectWarpMapDesc,
|
|
27
|
+
ProjectWarpMode,
|
|
28
|
+
Sf2InstrumentConfig,
|
|
29
|
+
Sf2ProgramStatus,
|
|
30
|
+
SynthEnumTables,
|
|
31
|
+
SynthPatch,
|
|
32
|
+
} from './project_types';
|
|
33
|
+
|
|
34
|
+
// Embind handle for the C++ `ProjectWasm` class. The generated `SonareModule`
|
|
35
|
+
// type only gains `Project` / `projectAbiVersion` after a WASM rebuild, so the
|
|
36
|
+
// module is cast through this shape here.
|
|
37
|
+
export interface WasmProject {
|
|
38
|
+
toJson: () => string;
|
|
39
|
+
setSampleRate: (sampleRate: number) => void;
|
|
40
|
+
addTrack: (desc: { kind?: number | string; name?: string }) => number;
|
|
41
|
+
addClip: (desc: ProjectClipDesc) => number;
|
|
42
|
+
addLoopRecordingTakes: (desc: ProjectLoopRecordingDesc) => ProjectLoopRecordingResult;
|
|
43
|
+
addMidiClip: (startPpq: number, lengthPpq: number) => ProjectMidiClipResult;
|
|
44
|
+
splitClip: (clipId: number, splitPpq: number) => number;
|
|
45
|
+
trimClip: (clipId: number, newStartPpq: number, newLengthPpq: number) => void;
|
|
46
|
+
moveClip: (clipId: number, newStartPpq: number, newTrackId: number) => void;
|
|
47
|
+
setTrackKind: (trackId: number, kind: number) => void;
|
|
48
|
+
setClipWarpRef: (clipId: number, warpRefId: number) => void;
|
|
49
|
+
setClipWarpMode: (clipId: number, mode: number) => void;
|
|
50
|
+
setWarpMap: (map: ProjectWarpMapDesc) => void;
|
|
51
|
+
removeWarpMap: (warpRefId: number) => void;
|
|
52
|
+
setTrackMidiDestination: (trackId: number, destinationId: number) => void;
|
|
53
|
+
setTrackGain: (trackId: number, gain: number) => void;
|
|
54
|
+
setTrackMute: (trackId: number, mute: boolean) => void;
|
|
55
|
+
setTrackSolo: (trackId: number, solo: boolean) => void;
|
|
56
|
+
setTrackPan: (trackId: number, pan: number) => void;
|
|
57
|
+
undo: () => void;
|
|
58
|
+
redo: () => void;
|
|
59
|
+
setMidiEvents: (
|
|
60
|
+
clipId: number,
|
|
61
|
+
events: ReadonlyArray<ProjectMidiEvent | readonly [number, number, number]>,
|
|
62
|
+
) => void;
|
|
63
|
+
importSmf: (data: Uint8Array) => number;
|
|
64
|
+
exportSmf: () => Uint8Array;
|
|
65
|
+
importClipFile: (data: Uint8Array) => number;
|
|
66
|
+
exportClipFile: () => Uint8Array;
|
|
67
|
+
setProgram: (clipId: number, program: number, bank: number) => void;
|
|
68
|
+
setProgramOnChannel: (
|
|
69
|
+
clipId: number,
|
|
70
|
+
group: number,
|
|
71
|
+
channel: number,
|
|
72
|
+
program: number,
|
|
73
|
+
bank: number,
|
|
74
|
+
) => void;
|
|
75
|
+
bakeMidiFx: (clipId: number, configJson: string) => void;
|
|
76
|
+
setMidiFx: (clipId: number, configJson: string) => void;
|
|
77
|
+
validateMidiNotes: (clipId: number) => ProjectNotePairValidation;
|
|
78
|
+
autoTempo: (audio: Float32Array, sampleRate: number) => number;
|
|
79
|
+
snapToGrid: (ppq: number, strength: number) => number;
|
|
80
|
+
compile: () => ProjectCompileResult;
|
|
81
|
+
bounce: (options: ProjectBounceOptions) => Float32Array;
|
|
82
|
+
bounceWithBuiltinInstrument: (
|
|
83
|
+
bindings: BuiltinSynthBinding | ReadonlyArray<BuiltinSynthBinding> | undefined,
|
|
84
|
+
options: ProjectBounceOptions,
|
|
85
|
+
) => Float32Array;
|
|
86
|
+
bounceWithSynthInstrument: (
|
|
87
|
+
bindings: SynthPatch | string | ReadonlyArray<SynthPatch | string> | undefined,
|
|
88
|
+
options: ProjectBounceOptions,
|
|
89
|
+
) => Float32Array;
|
|
90
|
+
loadSoundFont: (data: Uint8Array) => void;
|
|
91
|
+
clearSoundFont: () => void;
|
|
92
|
+
soundFontPresetCount: () => number;
|
|
93
|
+
soundFontManifest: () => Sf2ProgramStatus[];
|
|
94
|
+
bounceWithSf2Instrument: (
|
|
95
|
+
bindings: Sf2InstrumentConfig | ReadonlyArray<Sf2InstrumentConfig> | undefined,
|
|
96
|
+
options: ProjectBounceOptions,
|
|
97
|
+
) => Float32Array;
|
|
98
|
+
removeClip: (clipId: number) => void;
|
|
99
|
+
setClipGain: (clipId: number, gain: number) => void;
|
|
100
|
+
setClipFade: (clipId: number, fadeIn: ProjectClipFade, fadeOut: ProjectClipFade) => void;
|
|
101
|
+
setClipTakes: (
|
|
102
|
+
clipId: number,
|
|
103
|
+
takes: ReadonlyArray<ProjectClipTake>,
|
|
104
|
+
activeTakeId: number,
|
|
105
|
+
) => void;
|
|
106
|
+
setClipCompSegments: (clipId: number, segments: ReadonlyArray<ProjectClipCompSegment>) => void;
|
|
107
|
+
setClipLoop: (
|
|
108
|
+
clipId: number,
|
|
109
|
+
loopMode: number,
|
|
110
|
+
loopLengthPpq: number,
|
|
111
|
+
loopCrossfadePpq: number,
|
|
112
|
+
) => void;
|
|
113
|
+
setClipSource: (clipId: number, sourceId: number) => void;
|
|
114
|
+
duplicateClip: (clipId: number, newStartPpq: number) => number;
|
|
115
|
+
removeTrack: (trackId: number) => void;
|
|
116
|
+
renameTrack: (trackId: number, name: string) => void;
|
|
117
|
+
setTrackRoute: (trackId: number, channelStripRef: string, outputTarget: string) => void;
|
|
118
|
+
addAutomationLane: (
|
|
119
|
+
trackId: number,
|
|
120
|
+
desc: { targetParamId: number; points: ReadonlyArray<ProjectAutomationPoint> },
|
|
121
|
+
) => number;
|
|
122
|
+
editAutomationLane: (
|
|
123
|
+
trackId: number,
|
|
124
|
+
laneIndex: number,
|
|
125
|
+
desc: { targetParamId: number; points: ReadonlyArray<ProjectAutomationPoint> },
|
|
126
|
+
) => void;
|
|
127
|
+
removeAutomationLane: (trackId: number, laneIndex: number) => void;
|
|
128
|
+
annotateKeys: (keys: ReadonlyArray<ProjectKeySegment>) => void;
|
|
129
|
+
annotateChords: (chords: ReadonlyArray<ProjectChordSymbol>) => void;
|
|
130
|
+
setAssistSidecar: (
|
|
131
|
+
moduleId: string,
|
|
132
|
+
schemaVersion: number,
|
|
133
|
+
targetTrackId: number,
|
|
134
|
+
regionStartPpq: number,
|
|
135
|
+
regionEndPpq: number,
|
|
136
|
+
payload: Uint8Array,
|
|
137
|
+
) => void;
|
|
138
|
+
assistSidecarCount: () => number;
|
|
139
|
+
getAssistSidecar: (index: number) => ProjectAssistSidecar;
|
|
140
|
+
setOverlapPolicy: (policy: number) => void;
|
|
141
|
+
getOverlapPolicy: () => number;
|
|
142
|
+
getSampleRate: () => number;
|
|
143
|
+
setMixerSceneJson: (sceneJson: string) => void;
|
|
144
|
+
setMarker: (markerId: number, ppq: number, name: string) => number;
|
|
145
|
+
setMarkerEx: (marker: ProjectMarker) => number;
|
|
146
|
+
markerByIndex: (index: number) => ProjectMarker;
|
|
147
|
+
markerCount: () => number;
|
|
148
|
+
trackCount: () => number;
|
|
149
|
+
clipCount: () => number;
|
|
150
|
+
sourceCount: () => number;
|
|
151
|
+
tempoSegmentCount: () => number;
|
|
152
|
+
timeSignatureCount: () => number;
|
|
153
|
+
setTempoSegments: (segments: ReadonlyArray<ProjectTempoSegment>) => void;
|
|
154
|
+
setTimeSignatures: (segments: ReadonlyArray<ProjectTimeSignatureSegment>) => void;
|
|
155
|
+
lastBounceCompileResult: () => ProjectCompileResult;
|
|
156
|
+
delete: () => void;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
export interface ProjectModule {
|
|
160
|
+
Project: {
|
|
161
|
+
new (): WasmProject;
|
|
162
|
+
fromJson: (json: string) => WasmProject;
|
|
163
|
+
fromJsonWithDiagnostics: (json: string) => { project: WasmProject; diagnostics: string };
|
|
164
|
+
};
|
|
165
|
+
projectAbiVersion: () => number;
|
|
166
|
+
synthPresetNames: () => string[];
|
|
167
|
+
synthPresetPatch: (name: string) => SynthPatch;
|
|
168
|
+
_synthEnumTables: () => SynthEnumTables;
|
|
169
|
+
_synthPatchRoundTrip: (patch: SynthPatch) => SynthPatch;
|
|
170
|
+
midiGmInstrumentName: (program: number) => string | null;
|
|
171
|
+
midiGmProgramForName: (name: string) => number;
|
|
172
|
+
midiGmFamilyName: (family: number) => string | null;
|
|
173
|
+
midiGmFamilyFirstProgram: (family: number) => number;
|
|
174
|
+
midiGm2InstrumentName: (bankLsb: number, program: number) => string | null;
|
|
175
|
+
midiGmDrumName: (note: number) => string | null;
|
|
176
|
+
midiGmDrumNoteForName: (name: string) => number;
|
|
177
|
+
midiGm2DrumSetName: (bankLsb: number) => string | null;
|
|
178
|
+
midiGm2DrumName: (bankLsb: number, note: number) => string | null;
|
|
179
|
+
midiCcName: (controller: number) => string | null;
|
|
180
|
+
midiCcIndexForName: (name: string) => number;
|
|
181
|
+
midiPerNoteControllerName: (index: number) => string | null;
|
|
182
|
+
midiBankProgram: (
|
|
183
|
+
ppq: number,
|
|
184
|
+
group: number,
|
|
185
|
+
channel: number,
|
|
186
|
+
bankMsb: number,
|
|
187
|
+
bankLsb: number,
|
|
188
|
+
program: number,
|
|
189
|
+
) => ProjectMidiEvent[];
|
|
190
|
+
midiRouteEvents: (
|
|
191
|
+
events: ReadonlyArray<ProjectMidiEvent>,
|
|
192
|
+
config: ProjectMidiRouteConfig,
|
|
193
|
+
) => ProjectMidiRouteResult;
|
|
194
|
+
midiCcLearn: (
|
|
195
|
+
events: ReadonlyArray<ProjectMidiEvent>,
|
|
196
|
+
paramId: number,
|
|
197
|
+
minValue: number,
|
|
198
|
+
maxValue: number,
|
|
199
|
+
minMovement: number,
|
|
200
|
+
) => ProjectMidiCcBinding | null;
|
|
201
|
+
midiCcToBreakpoint: (
|
|
202
|
+
bindings: ReadonlyArray<ProjectMidiCcBinding>,
|
|
203
|
+
event: ProjectMidiEvent,
|
|
204
|
+
) => ProjectAutomationPoint | null;
|
|
205
|
+
midiParamToCc: (
|
|
206
|
+
bindings: ReadonlyArray<ProjectMidiCcBinding>,
|
|
207
|
+
paramId: number,
|
|
208
|
+
unitValue: number,
|
|
209
|
+
group: number,
|
|
210
|
+
ppq: number,
|
|
211
|
+
) => ProjectMidiEvent | null;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
export function projectModule(): ProjectModule {
|
|
215
|
+
const candidate = getSonareModule() as unknown as Partial<ProjectModule>;
|
|
216
|
+
if (typeof candidate.projectAbiVersion !== 'function' || candidate.Project === undefined) {
|
|
217
|
+
throw new Error('libsonare was built without arrangement (headless DAW) support');
|
|
218
|
+
}
|
|
219
|
+
return candidate as ProjectModule;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
export function assertProjectU7(fnName: string, value: number, argName: string): number {
|
|
223
|
+
if (!Number.isInteger(value) || value < 0 || value > 127) {
|
|
224
|
+
throw new RangeError(`${fnName}: ${argName} must be an integer in [0, 127]`);
|
|
225
|
+
}
|
|
226
|
+
return value;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
export function assertProjectNibble(fnName: string, value: number, argName: string): number {
|
|
230
|
+
if (!Number.isInteger(value) || value < 0 || value > 15) {
|
|
231
|
+
throw new RangeError(`${fnName}: ${argName} must be an integer in [0, 15]`);
|
|
232
|
+
}
|
|
233
|
+
return value;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
export function projectMidi1Event(
|
|
237
|
+
fnName: string,
|
|
238
|
+
ppq: number,
|
|
239
|
+
group: number,
|
|
240
|
+
status: number,
|
|
241
|
+
channel: number,
|
|
242
|
+
data1: number,
|
|
243
|
+
data2 = 0,
|
|
244
|
+
): ProjectMidiEvent {
|
|
245
|
+
if (!Number.isFinite(ppq) || ppq < 0) {
|
|
246
|
+
throw new RangeError(`${fnName}: ppq must be a non-negative finite number`);
|
|
247
|
+
}
|
|
248
|
+
const g = assertProjectNibble(fnName, group, 'group');
|
|
249
|
+
const ch = assertProjectNibble(fnName, channel, 'channel');
|
|
250
|
+
const d1 = assertProjectU7(fnName, data1, 'data1');
|
|
251
|
+
const d2 = assertProjectU7(fnName, data2, 'data2');
|
|
252
|
+
// UMP MIDI-1.0 channel-voice word (message type 0x2). Canonical layout is
|
|
253
|
+
// sonare::midi::make_midi1_* (C-ABI sonare_midi_*, which Python delegates to);
|
|
254
|
+
// this hand-written copy is locked against those words by the golden vectors
|
|
255
|
+
// in project.test.ts (mirrored in the Node suite) so it cannot silently drift.
|
|
256
|
+
const word = ((0x2 << 28) | (g << 24) | (status << 20) | (ch << 16) | (d1 << 8) | d2) >>> 0;
|
|
257
|
+
return { ppq, data0: word, data1: 0 };
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
export function assertProjectU32(fnName: string, value: number, argName: string): void {
|
|
261
|
+
if (!Number.isInteger(value) || value < 0 || value > 0xffffffff) {
|
|
262
|
+
throw new RangeError(`${fnName}: ${argName} must be an integer in [0, 4294967295]`);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
export function assertProjectMidiEvents(
|
|
267
|
+
fnName: string,
|
|
268
|
+
events: ReadonlyArray<ProjectMidiEvent | readonly [number, number, number]>,
|
|
269
|
+
): void {
|
|
270
|
+
if (!Array.isArray(events)) {
|
|
271
|
+
throw new TypeError(`${fnName}: events must be an array`);
|
|
272
|
+
}
|
|
273
|
+
events.forEach((event, index) => {
|
|
274
|
+
const prefix = `events[${index}]`;
|
|
275
|
+
if (Array.isArray(event)) {
|
|
276
|
+
if (event.length < 3) {
|
|
277
|
+
throw new TypeError(`${fnName}: ${prefix} must contain [ppq, data0, data1]`);
|
|
278
|
+
}
|
|
279
|
+
if (!Number.isFinite(event[0]) || event[0] < 0) {
|
|
280
|
+
throw new RangeError(`${fnName}: ${prefix}.ppq must be a non-negative finite number`);
|
|
281
|
+
}
|
|
282
|
+
assertProjectU32(fnName, event[1], `${prefix}.data0`);
|
|
283
|
+
assertProjectU32(fnName, event[2], `${prefix}.data1`);
|
|
284
|
+
return;
|
|
285
|
+
}
|
|
286
|
+
if (event === null || typeof event !== 'object') {
|
|
287
|
+
throw new TypeError(`${fnName}: ${prefix} must be a MIDI event object or tuple`);
|
|
288
|
+
}
|
|
289
|
+
if (!Number.isFinite(event.ppq) || event.ppq < 0) {
|
|
290
|
+
throw new RangeError(`${fnName}: ${prefix}.ppq must be a non-negative finite number`);
|
|
291
|
+
}
|
|
292
|
+
assertProjectU32(fnName, event.data0, `${prefix}.data0`);
|
|
293
|
+
if (event.data1 !== undefined) {
|
|
294
|
+
assertProjectU32(fnName, event.data1, `${prefix}.data1`);
|
|
295
|
+
}
|
|
296
|
+
});
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
export function projectTrackKindValue(kind: ProjectTrackKind | undefined): number {
|
|
300
|
+
if (kind === undefined || kind === 'audio') {
|
|
301
|
+
return 0;
|
|
302
|
+
}
|
|
303
|
+
if (kind === 'midi') {
|
|
304
|
+
return 1;
|
|
305
|
+
}
|
|
306
|
+
if (kind === 'aux') {
|
|
307
|
+
return 2;
|
|
308
|
+
}
|
|
309
|
+
return kind;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
export function projectWarpModeValue(mode: ProjectWarpMode | undefined): number {
|
|
313
|
+
if (mode === undefined || mode === 'off') {
|
|
314
|
+
return 0;
|
|
315
|
+
}
|
|
316
|
+
if (mode === 'repitch') {
|
|
317
|
+
return 1;
|
|
318
|
+
}
|
|
319
|
+
if (mode === 'tempo-sync') {
|
|
320
|
+
return 2;
|
|
321
|
+
}
|
|
322
|
+
return mode;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
export function projectLoopModeValue(mode: ProjectLoopMode | undefined): number {
|
|
326
|
+
if (mode === undefined || mode === 'off') {
|
|
327
|
+
return 0;
|
|
328
|
+
}
|
|
329
|
+
if (mode === 'loop') {
|
|
330
|
+
return 1;
|
|
331
|
+
}
|
|
332
|
+
return mode;
|
|
333
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { projectModule } from './project_internal';
|
|
2
|
+
import type { SynthEnumTables, SynthPatch } from './project_types';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Runtime ABI version of the flat project POD layout exposed by this WASM
|
|
6
|
+
* build. Equals {@link EXPECTED_PROJECT_ABI_VERSION} when the arrangement
|
|
7
|
+
* subsystem is compiled in. Mirrors the C-ABI `sonare_project_abi_version`.
|
|
8
|
+
*/
|
|
9
|
+
export function projectAbiVersion(): number {
|
|
10
|
+
return projectModule().projectAbiVersion();
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* NativeSynth preset catalog names (`'sine'`, `'saw-lead'`, `'e-piano'`,
|
|
15
|
+
* `'drum-kit'`, ...). Use these to discover valid {@link SynthPatch} preset
|
|
16
|
+
* names instead of hardcoding magic strings.
|
|
17
|
+
*/
|
|
18
|
+
export function synthPresetNames(): string[] {
|
|
19
|
+
// Array.from re-roots embind's vector as a plain, structured-cloneable Array.
|
|
20
|
+
return Array.from(projectModule().synthPresetNames());
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Fetch a named catalog preset as a {@link SynthPatch} (the preset name plus
|
|
25
|
+
* the wrapper-section values), so hosts can inspect a preset and tweak fields
|
|
26
|
+
* before binding it. A `"va:"` routing prefix is accepted; unknown names
|
|
27
|
+
* throw.
|
|
28
|
+
*/
|
|
29
|
+
export function synthPresetPatch(name: string): SynthPatch {
|
|
30
|
+
// embind returns a val::object whose constructor is not this realm's Object, so a
|
|
31
|
+
// direct return is not structured-cloneable (breaks postMessage to a Worker).
|
|
32
|
+
// Spreading into a fresh literal re-roots it as a plain Object; modRoutings is
|
|
33
|
+
// already a plain member array.
|
|
34
|
+
return { ...projectModule().synthPresetPatch(name) };
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function synthEnumTables(): SynthEnumTables {
|
|
38
|
+
return projectModule()._synthEnumTables();
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function synthPatchRoundTripForTest(patch: SynthPatch): SynthPatch {
|
|
42
|
+
return projectModule()._synthPatchRoundTrip(patch);
|
|
43
|
+
}
|