@libraz/libsonare 1.3.2 → 1.4.0
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 +45 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +403 -70
- package/dist/index.js.map +1 -1
- package/dist/sonare-rt-module.js +2 -2
- package/dist/sonare-rt.js +2 -2
- package/dist/sonare-rt.wasm +0 -0
- package/dist/sonare.js +2 -2
- package/dist/sonare.wasm +0 -0
- package/dist/worklet.d.ts +907 -144
- package/dist/worklet.js +1803 -207
- package/dist/worklet.js.map +1 -1
- package/package.json +1 -1
- package/src/codes.ts +6 -1
- package/src/effects_mastering.ts +103 -1
- package/src/feature_music.ts +18 -4
- package/src/feature_spectral.ts +7 -1
- package/src/index.ts +27 -1
- package/src/mixer.ts +9 -0
- package/src/module_state.ts +82 -17
- package/src/opfs_clip_pages.ts +43 -9
- package/src/project.ts +74 -0
- package/src/public_types.ts +52 -0
- package/src/realtime_engine.ts +313 -109
- package/src/sonare.js.d.ts +140 -0
- package/src/stream_types.ts +7 -0
- package/src/validation.ts +7 -0
- package/src/web_midi.ts +15 -11
- package/src/worklet/audio_types.ts +2 -0
- package/src/worklet/guards.ts +146 -0
- package/src/worklet/messages.ts +461 -0
- package/src/worklet/protocol.ts +767 -0
- package/src/worklet.ts +1659 -888
package/src/public_types.ts
CHANGED
|
@@ -367,6 +367,40 @@ export interface NoteStretchOptions {
|
|
|
367
367
|
stretchRatio?: number;
|
|
368
368
|
}
|
|
369
369
|
|
|
370
|
+
/** How a `spectralEdit` region op modifies the masked bins. */
|
|
371
|
+
export type SpectralEditMode = 'gain' | 'attenuate' | 'mute' | 'heal';
|
|
372
|
+
|
|
373
|
+
/** Analysis/synthesis window used by `spectralEdit`. */
|
|
374
|
+
export type SpectralEditWindow = 'hann' | 'hamming' | 'blackman' | 'rectangular';
|
|
375
|
+
|
|
376
|
+
/** One time x frequency rectangle edit op for `spectralEdit`. */
|
|
377
|
+
export interface SpectralRegionOp {
|
|
378
|
+
/** Region time start (input samples); clamped to [0, length]. Default 0. */
|
|
379
|
+
startSample?: number;
|
|
380
|
+
/** Region time end, exclusive (input samples); clamped to [0, length]. Default = signal length. */
|
|
381
|
+
endSample?: number;
|
|
382
|
+
/** Region frequency low edge in Hz; clamped to [0, nyquist]. Default 0. */
|
|
383
|
+
lowHz?: number;
|
|
384
|
+
/** Region frequency high edge in Hz; <=0 or >= nyquist means nyquist. Default 0. */
|
|
385
|
+
highHz?: number;
|
|
386
|
+
/** Linear gain in dB for 'gain'/'attenuate'; ignored by 'mute'/'heal'. Default 0. */
|
|
387
|
+
gainDb?: number;
|
|
388
|
+
/** Edit mode. Default 'gain'. */
|
|
389
|
+
mode?: SpectralEditMode;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
/** STFT + heal parameters for `spectralEdit`. All fields are optional. */
|
|
393
|
+
export interface SpectralEditOptions {
|
|
394
|
+
/** FFT size; must be a power of two (>= 2). Default 2048. */
|
|
395
|
+
nFft?: number;
|
|
396
|
+
/** Hop length; must satisfy 0 < hop <= nFft/2. Default 512. */
|
|
397
|
+
hopLength?: number;
|
|
398
|
+
/** Analysis + synthesis window. Default 'hann'. */
|
|
399
|
+
window?: SpectralEditWindow;
|
|
400
|
+
/** Neighbour frames each side used by 'heal' (>= 1). Default 2. */
|
|
401
|
+
healRadiusFrames?: number;
|
|
402
|
+
}
|
|
403
|
+
|
|
370
404
|
/**
|
|
371
405
|
* Detected beat
|
|
372
406
|
*/
|
|
@@ -655,6 +689,24 @@ export type MasteringProcessorParams = Record<string, number | boolean>;
|
|
|
655
689
|
|
|
656
690
|
export type PanMode = 'balance' | 'stereoPan' | 'stereo-pan' | 'dualPan' | 'dual-pan' | number;
|
|
657
691
|
|
|
692
|
+
/**
|
|
693
|
+
* Surround pan position for a strip feeding a >2-channel bus. Phase 1 honors
|
|
694
|
+
* `azimuth`/`divergence`/`lfe`; `elevation`/`distance` are reserved. All fields
|
|
695
|
+
* are optional and default to a centered point source.
|
|
696
|
+
*/
|
|
697
|
+
export interface SurroundPan {
|
|
698
|
+
/** -180..180 deg, 0 = front-center, positive = right. */
|
|
699
|
+
azimuth?: number;
|
|
700
|
+
/** Reserved (no height beds in phase 1). */
|
|
701
|
+
elevation?: number;
|
|
702
|
+
/** 0 = point source, 1 = spread across the front. */
|
|
703
|
+
divergence?: number;
|
|
704
|
+
/** 0..1 scalar send into the LFE plane. */
|
|
705
|
+
lfe?: number;
|
|
706
|
+
/** Reserved (focus/spread), defaults to 1. */
|
|
707
|
+
distance?: number;
|
|
708
|
+
}
|
|
709
|
+
|
|
658
710
|
export interface MixOptions {
|
|
659
711
|
inputTrimDb?: number | number[];
|
|
660
712
|
faderDb?: number | number[];
|
package/src/realtime_engine.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
import { panLawCode, panModeCode, sendTimingCode } from './codes';
|
|
2
|
+
import { ErrorCode, SonareError } from './errors';
|
|
1
3
|
import { getSonareModule } from './module_state';
|
|
2
4
|
import type { SynthPatch } from './project';
|
|
5
|
+
import type { EqBand, PanLaw, PanMode, SendTiming } from './public_types';
|
|
3
6
|
import type {
|
|
4
7
|
WasmClipPageRequest,
|
|
5
8
|
WasmEngineAutomationPoint,
|
|
@@ -12,10 +15,14 @@ import type {
|
|
|
12
15
|
WasmEngineGraphSpec,
|
|
13
16
|
WasmEngineMarker,
|
|
14
17
|
WasmEngineMeterTelemetry,
|
|
18
|
+
WasmEngineMeterTelemetryWide,
|
|
15
19
|
WasmEngineMetronomeConfig,
|
|
16
20
|
WasmEngineParameterInfo,
|
|
17
21
|
WasmEngineProcessWithMonitorResult,
|
|
22
|
+
WasmEngineScopeTelemetry,
|
|
18
23
|
WasmEngineTelemetry,
|
|
24
|
+
WasmEngineTempoSegment,
|
|
25
|
+
WasmEngineTimeSignatureSegment,
|
|
19
26
|
WasmEngineTransportState,
|
|
20
27
|
WasmRealtimeEngine,
|
|
21
28
|
} from './sonare.js';
|
|
@@ -34,7 +41,75 @@ export type EngineFreezeOptions = WasmEngineFreezeOptions;
|
|
|
34
41
|
export type EngineFreezeResult = WasmEngineFreezeResult;
|
|
35
42
|
export type EngineTelemetry = WasmEngineTelemetry;
|
|
36
43
|
export type EngineMeterTelemetry = WasmEngineMeterTelemetry;
|
|
44
|
+
export type EngineMeterTelemetryWide = WasmEngineMeterTelemetryWide;
|
|
45
|
+
export type EngineScopeTelemetry = WasmEngineScopeTelemetry;
|
|
37
46
|
export type EngineTransportState = WasmEngineTransportState;
|
|
47
|
+
export type EngineTempoSegment = WasmEngineTempoSegment;
|
|
48
|
+
export type EngineTimeSignatureSegment = WasmEngineTimeSignatureSegment;
|
|
49
|
+
|
|
50
|
+
export interface EngineTrackSend {
|
|
51
|
+
busId: number;
|
|
52
|
+
levelDb?: number;
|
|
53
|
+
enabled?: boolean;
|
|
54
|
+
/**
|
|
55
|
+
* Pre/post-fader tap point. Defaults to post-fader when omitted, matching the
|
|
56
|
+
* historical lane-send behavior and the scene-JSON default.
|
|
57
|
+
*/
|
|
58
|
+
sendTiming?: SendTiming | number;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export interface EngineTrackLane {
|
|
62
|
+
trackId: number;
|
|
63
|
+
sends?: EngineTrackSend[];
|
|
64
|
+
/**
|
|
65
|
+
* Bus the lane's post-fader output sums into instead of the master mix
|
|
66
|
+
* (group/folder routing); 0 or absent keeps the lane on the master mix.
|
|
67
|
+
*/
|
|
68
|
+
outputBusId?: number;
|
|
69
|
+
/**
|
|
70
|
+
* Input channel layout of the source feeding this lane (`SonareChannelLayout`:
|
|
71
|
+
* 0 mono, 1 stereo, 2 5.1, 3 7.1). Absent defaults to stereo. Stored but inert
|
|
72
|
+
* until the surround DSP path lands.
|
|
73
|
+
*/
|
|
74
|
+
sourceChannelLayout?: number;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export interface EngineBus {
|
|
78
|
+
busId: number;
|
|
79
|
+
gainDb?: number;
|
|
80
|
+
/**
|
|
81
|
+
* Channel layout of the bus (`SonareChannelLayout`: 0 mono, 1 stereo, 2 5.1,
|
|
82
|
+
* 3 7.1). A surround layout makes this a surround group bus: lanes routed to
|
|
83
|
+
* it are surround-panned and it sums into the master plane-by-plane. Defaults
|
|
84
|
+
* to stereo.
|
|
85
|
+
*/
|
|
86
|
+
channelLayout?: number;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export interface EngineMidiEvent {
|
|
90
|
+
renderFrame: number;
|
|
91
|
+
word0?: number;
|
|
92
|
+
word1?: number;
|
|
93
|
+
word2?: number;
|
|
94
|
+
word3?: number;
|
|
95
|
+
wordCount?: number;
|
|
96
|
+
group?: number;
|
|
97
|
+
sysexHandle?: number;
|
|
98
|
+
data0?: number;
|
|
99
|
+
data1?: number;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export interface EngineMidiClipSchedule {
|
|
103
|
+
id?: number;
|
|
104
|
+
trackId?: number;
|
|
105
|
+
destinationId?: number;
|
|
106
|
+
startSample?: number;
|
|
107
|
+
startPpq?: number;
|
|
108
|
+
lengthSamples?: number;
|
|
109
|
+
loop?: boolean;
|
|
110
|
+
loopLengthSamples?: number;
|
|
111
|
+
events: EngineMidiEvent[];
|
|
112
|
+
}
|
|
38
113
|
|
|
39
114
|
export const EXPECTED_ENGINE_ABI_VERSION = 3;
|
|
40
115
|
|
|
@@ -75,91 +150,9 @@ export function engineCapabilities(): EngineCapabilities {
|
|
|
75
150
|
};
|
|
76
151
|
}
|
|
77
152
|
|
|
78
|
-
// Methods added to the embind RealtimeEngine that the generated `sonare.js`
|
|
79
|
-
// declarations only gain after a WASM rebuild. The native handle is cast to this
|
|
80
|
-
// shape so the wrapper can reach them without a stale type error.
|
|
81
|
-
interface WasmRealtimeEngineExt {
|
|
82
|
-
setBuiltinInstrument: (destinationId: number, config: object) => void;
|
|
83
|
-
setSynthInstrument: (destinationId: number, patch: object | string) => void;
|
|
84
|
-
loadSoundFont: (data: Uint8Array) => void;
|
|
85
|
-
setSf2Instrument: (destinationId: number, config: object) => void;
|
|
86
|
-
clearMidiInstrument: (destinationId: number) => void;
|
|
87
|
-
midiInstrumentCount: () => number;
|
|
88
|
-
bindMidiCc: (
|
|
89
|
-
channel: number,
|
|
90
|
-
controller: number,
|
|
91
|
-
paramId: number,
|
|
92
|
-
minValue: number,
|
|
93
|
-
maxValue: number,
|
|
94
|
-
) => void;
|
|
95
|
-
clearMidiCcBindings: () => void;
|
|
96
|
-
midiCcBindingCount: () => number;
|
|
97
|
-
setMidiFx: (destinationId: number, configJson: string) => void;
|
|
98
|
-
clearMidiFx: (destinationId: number) => void;
|
|
99
|
-
setMidiInputSource: (destinationId: number) => void;
|
|
100
|
-
clearMidiInputSource: () => void;
|
|
101
|
-
midiInputPendingCount: () => number;
|
|
102
|
-
createClipPageProvider: (numChannels: number, numSamples: number, pageFrames: number) => number;
|
|
103
|
-
supplyClipPage: (providerId: number, pageIndex: number, channels: Float32Array[]) => void;
|
|
104
|
-
clearClipPage: (providerId: number, pageIndex: number) => void;
|
|
105
|
-
destroyClipPageProvider: (providerId: number) => void;
|
|
106
|
-
popClipPageRequest: () => ClipPageRequest | null;
|
|
107
|
-
pushMidiInputNoteOn: (
|
|
108
|
-
group: number,
|
|
109
|
-
channel: number,
|
|
110
|
-
note: number,
|
|
111
|
-
velocity: number,
|
|
112
|
-
portTimeSamples: number,
|
|
113
|
-
) => void;
|
|
114
|
-
pushMidiInputNoteOff: (
|
|
115
|
-
group: number,
|
|
116
|
-
channel: number,
|
|
117
|
-
note: number,
|
|
118
|
-
velocity: number,
|
|
119
|
-
portTimeSamples: number,
|
|
120
|
-
) => void;
|
|
121
|
-
pushMidiInputCc: (
|
|
122
|
-
group: number,
|
|
123
|
-
channel: number,
|
|
124
|
-
controller: number,
|
|
125
|
-
value: number,
|
|
126
|
-
portTimeSamples: number,
|
|
127
|
-
) => void;
|
|
128
|
-
pushMidiNoteOn: (
|
|
129
|
-
destinationId: number,
|
|
130
|
-
group: number,
|
|
131
|
-
channel: number,
|
|
132
|
-
note: number,
|
|
133
|
-
velocity: number,
|
|
134
|
-
renderFrame: number,
|
|
135
|
-
) => void;
|
|
136
|
-
pushMidiNoteOff: (
|
|
137
|
-
destinationId: number,
|
|
138
|
-
group: number,
|
|
139
|
-
channel: number,
|
|
140
|
-
note: number,
|
|
141
|
-
velocity: number,
|
|
142
|
-
renderFrame: number,
|
|
143
|
-
) => void;
|
|
144
|
-
pushMidiCc: (
|
|
145
|
-
destinationId: number,
|
|
146
|
-
group: number,
|
|
147
|
-
channel: number,
|
|
148
|
-
controller: number,
|
|
149
|
-
value: number,
|
|
150
|
-
renderFrame: number,
|
|
151
|
-
) => void;
|
|
152
|
-
pushMidiPanic: (renderFrame: number) => void;
|
|
153
|
-
clearParameters: () => void;
|
|
154
|
-
}
|
|
155
|
-
|
|
156
153
|
export class RealtimeEngine {
|
|
157
154
|
private native: WasmRealtimeEngine;
|
|
158
155
|
|
|
159
|
-
private nativeExt(): WasmRealtimeEngineExt {
|
|
160
|
-
return this.native as unknown as WasmRealtimeEngineExt;
|
|
161
|
-
}
|
|
162
|
-
|
|
163
156
|
constructor(
|
|
164
157
|
sampleRate = 48000,
|
|
165
158
|
maxBlockSize = 128,
|
|
@@ -200,11 +193,19 @@ export class RealtimeEngine {
|
|
|
200
193
|
this.native.setParameterSmoothed(paramId, value, renderFrame);
|
|
201
194
|
}
|
|
202
195
|
|
|
196
|
+
setSoloMute(laneIndex: number, solo: boolean, mute: boolean, renderFrame = -1): void {
|
|
197
|
+
this.native.setSoloMute(laneIndex, solo, mute, renderFrame);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
setMidiClips(clips: readonly EngineMidiClipSchedule[]): void {
|
|
201
|
+
this.native.setMidiClips(clips);
|
|
202
|
+
}
|
|
203
|
+
|
|
203
204
|
setBuiltinInstrument(
|
|
204
205
|
config: { destinationId?: number } & Record<string, unknown> = {},
|
|
205
206
|
destinationId = config.destinationId ?? 0,
|
|
206
207
|
): void {
|
|
207
|
-
this.
|
|
208
|
+
this.native.setBuiltinInstrument(destinationId, config);
|
|
208
209
|
}
|
|
209
210
|
|
|
210
211
|
/**
|
|
@@ -220,7 +221,7 @@ export class RealtimeEngine {
|
|
|
220
221
|
patch: SynthPatch | string = {},
|
|
221
222
|
destinationId = (typeof patch === 'object' ? patch.destinationId : undefined) ?? 0,
|
|
222
223
|
): void {
|
|
223
|
-
this.
|
|
224
|
+
this.native.setSynthInstrument(destinationId, patch);
|
|
224
225
|
}
|
|
225
226
|
|
|
226
227
|
/**
|
|
@@ -230,7 +231,7 @@ export class RealtimeEngine {
|
|
|
230
231
|
* not referenced afterwards. Replaces any previously loaded SoundFont.
|
|
231
232
|
*/
|
|
232
233
|
loadSoundFont(data: Uint8Array): void {
|
|
233
|
-
this.
|
|
234
|
+
this.native.loadSoundFont(data);
|
|
234
235
|
}
|
|
235
236
|
|
|
236
237
|
/**
|
|
@@ -246,15 +247,15 @@ export class RealtimeEngine {
|
|
|
246
247
|
config: { destinationId?: number; gain?: number; polyphony?: number } = {},
|
|
247
248
|
destinationId = config.destinationId ?? 0,
|
|
248
249
|
): void {
|
|
249
|
-
this.
|
|
250
|
+
this.native.setSf2Instrument(destinationId, config);
|
|
250
251
|
}
|
|
251
252
|
|
|
252
253
|
clearMidiInstrument(destinationId = 0): void {
|
|
253
|
-
this.
|
|
254
|
+
this.native.clearMidiInstrument(destinationId);
|
|
254
255
|
}
|
|
255
256
|
|
|
256
257
|
midiInstrumentCount(): number {
|
|
257
|
-
return this.
|
|
258
|
+
return this.native.midiInstrumentCount();
|
|
258
259
|
}
|
|
259
260
|
|
|
260
261
|
/**
|
|
@@ -268,7 +269,7 @@ export class RealtimeEngine {
|
|
|
268
269
|
paramId: number,
|
|
269
270
|
options: MidiCcBindOptions = {},
|
|
270
271
|
): void {
|
|
271
|
-
this.
|
|
272
|
+
this.native.bindMidiCc(
|
|
272
273
|
channel,
|
|
273
274
|
controller,
|
|
274
275
|
paramId,
|
|
@@ -278,33 +279,33 @@ export class RealtimeEngine {
|
|
|
278
279
|
}
|
|
279
280
|
|
|
280
281
|
clearMidiCcBindings(): void {
|
|
281
|
-
this.
|
|
282
|
+
this.native.clearMidiCcBindings();
|
|
282
283
|
}
|
|
283
284
|
|
|
284
285
|
midiCcBindingCount(): number {
|
|
285
|
-
return this.
|
|
286
|
+
return this.native.midiCcBindingCount();
|
|
286
287
|
}
|
|
287
288
|
|
|
288
289
|
/** Install/replace a live non-destructive MIDI-FX insert for one destination. */
|
|
289
290
|
setMidiFx(destinationId: number, configJson: string): void {
|
|
290
|
-
this.
|
|
291
|
+
this.native.setMidiFx(destinationId, configJson);
|
|
291
292
|
}
|
|
292
293
|
|
|
293
294
|
clearMidiFx(destinationId = 0): void {
|
|
294
|
-
this.
|
|
295
|
+
this.native.clearMidiFx(destinationId);
|
|
295
296
|
}
|
|
296
297
|
|
|
297
298
|
/** Enable the engine-owned live MIDI input source for a destination. */
|
|
298
299
|
setMidiInputSource(destinationId = 0): void {
|
|
299
|
-
this.
|
|
300
|
+
this.native.setMidiInputSource(destinationId);
|
|
300
301
|
}
|
|
301
302
|
|
|
302
303
|
clearMidiInputSource(): void {
|
|
303
|
-
this.
|
|
304
|
+
this.native.clearMidiInputSource();
|
|
304
305
|
}
|
|
305
306
|
|
|
306
307
|
midiInputPendingCount(): number {
|
|
307
|
-
return this.
|
|
308
|
+
return this.native.midiInputPendingCount();
|
|
308
309
|
}
|
|
309
310
|
|
|
310
311
|
pushMidiInputNoteOn(
|
|
@@ -314,7 +315,7 @@ export class RealtimeEngine {
|
|
|
314
315
|
velocity: number,
|
|
315
316
|
portTimeSamples = 0,
|
|
316
317
|
): void {
|
|
317
|
-
this.
|
|
318
|
+
this.native.pushMidiInputNoteOn(group, channel, note, velocity, portTimeSamples);
|
|
318
319
|
}
|
|
319
320
|
|
|
320
321
|
pushMidiInputNoteOff(
|
|
@@ -324,7 +325,7 @@ export class RealtimeEngine {
|
|
|
324
325
|
velocity = 0,
|
|
325
326
|
portTimeSamples = 0,
|
|
326
327
|
): void {
|
|
327
|
-
this.
|
|
328
|
+
this.native.pushMidiInputNoteOff(group, channel, note, velocity, portTimeSamples);
|
|
328
329
|
}
|
|
329
330
|
|
|
330
331
|
pushMidiInputCc(
|
|
@@ -334,7 +335,7 @@ export class RealtimeEngine {
|
|
|
334
335
|
value: number,
|
|
335
336
|
portTimeSamples = 0,
|
|
336
337
|
): void {
|
|
337
|
-
this.
|
|
338
|
+
this.native.pushMidiInputCc(group, channel, controller, value, portTimeSamples);
|
|
338
339
|
}
|
|
339
340
|
|
|
340
341
|
pushMidiNoteOn(
|
|
@@ -345,7 +346,7 @@ export class RealtimeEngine {
|
|
|
345
346
|
velocity: number,
|
|
346
347
|
renderFrame = -1,
|
|
347
348
|
): void {
|
|
348
|
-
this.
|
|
349
|
+
this.native.pushMidiNoteOn(destinationId, group, channel, note, velocity, renderFrame);
|
|
349
350
|
}
|
|
350
351
|
|
|
351
352
|
pushMidiNoteOff(
|
|
@@ -356,7 +357,7 @@ export class RealtimeEngine {
|
|
|
356
357
|
velocity = 0,
|
|
357
358
|
renderFrame = -1,
|
|
358
359
|
): void {
|
|
359
|
-
this.
|
|
360
|
+
this.native.pushMidiNoteOff(destinationId, group, channel, note, velocity, renderFrame);
|
|
360
361
|
}
|
|
361
362
|
|
|
362
363
|
/**
|
|
@@ -373,7 +374,7 @@ export class RealtimeEngine {
|
|
|
373
374
|
value: number,
|
|
374
375
|
renderFrame = -1,
|
|
375
376
|
): void {
|
|
376
|
-
this.
|
|
377
|
+
this.native.pushMidiCc(destinationId, group, channel, controller, value, renderFrame);
|
|
377
378
|
}
|
|
378
379
|
|
|
379
380
|
/**
|
|
@@ -381,7 +382,7 @@ export class RealtimeEngine {
|
|
|
381
382
|
* `renderFrame` (-1 = immediate). Mirrors the C-ABI `pushMidiPanic`.
|
|
382
383
|
*/
|
|
383
384
|
pushMidiPanic(renderFrame = -1): void {
|
|
384
|
-
this.
|
|
385
|
+
this.native.pushMidiPanic(renderFrame);
|
|
385
386
|
}
|
|
386
387
|
|
|
387
388
|
/**
|
|
@@ -389,7 +390,7 @@ export class RealtimeEngine {
|
|
|
389
390
|
* only; not realtime-safe. Mirrors the C-ABI `clearParameters`.
|
|
390
391
|
*/
|
|
391
392
|
clearParameters(): void {
|
|
392
|
-
this.
|
|
393
|
+
this.native.clearParameters();
|
|
393
394
|
}
|
|
394
395
|
|
|
395
396
|
/** Read back the current transport state snapshot. */
|
|
@@ -409,6 +410,16 @@ export class RealtimeEngine {
|
|
|
409
410
|
this.native.seekSample(timelineSample, renderFrame);
|
|
410
411
|
}
|
|
411
412
|
|
|
413
|
+
/**
|
|
414
|
+
* Snaps every in-flight parameter ramp (engine-level smoothed params, mixer
|
|
415
|
+
* lane fader/pan/gate, bus gains) to its target value. Offline renders call
|
|
416
|
+
* this after a priming process() block so the first audible block renders at
|
|
417
|
+
* settled values instead of ramping in from defaults.
|
|
418
|
+
*/
|
|
419
|
+
settleParameters(): void {
|
|
420
|
+
this.native.settleParameters();
|
|
421
|
+
}
|
|
422
|
+
|
|
412
423
|
seekPpq(ppq: number, renderFrame = -1): void {
|
|
413
424
|
this.native.seekPpq(ppq, renderFrame);
|
|
414
425
|
}
|
|
@@ -417,10 +428,22 @@ export class RealtimeEngine {
|
|
|
417
428
|
this.native.setTempo(bpm);
|
|
418
429
|
}
|
|
419
430
|
|
|
431
|
+
setTempoSegments(segments: readonly EngineTempoSegment[]): void {
|
|
432
|
+
this.native.setTempoSegments([...segments]);
|
|
433
|
+
}
|
|
434
|
+
|
|
420
435
|
setTimeSignature(numerator: number, denominator: number): void {
|
|
421
436
|
this.native.setTimeSignature(numerator, denominator);
|
|
422
437
|
}
|
|
423
438
|
|
|
439
|
+
setTimeSignatureSegments(segments: readonly EngineTimeSignatureSegment[]): void {
|
|
440
|
+
this.native.setTimeSignatureSegments([...segments]);
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
sampleAtPpq(ppq: number): number {
|
|
444
|
+
return Number(this.native.sampleAtPpq(ppq));
|
|
445
|
+
}
|
|
446
|
+
|
|
424
447
|
setLoop(startPpq: number, endPpq: number, enabled = true): void {
|
|
425
448
|
this.native.setLoop(startPpq, endPpq, enabled);
|
|
426
449
|
}
|
|
@@ -513,29 +536,183 @@ export class RealtimeEngine {
|
|
|
513
536
|
return this.native.clipCount();
|
|
514
537
|
}
|
|
515
538
|
|
|
539
|
+
setTrackLanes(lanes: Array<number | EngineTrackLane>): void {
|
|
540
|
+
this.native.setTrackLanes(
|
|
541
|
+
lanes.map((lane) => {
|
|
542
|
+
if (typeof lane === 'number') {
|
|
543
|
+
return { trackId: lane };
|
|
544
|
+
}
|
|
545
|
+
if (!lane.sends) {
|
|
546
|
+
return lane;
|
|
547
|
+
}
|
|
548
|
+
// Normalize each send's pre/post tap point to the integer the native
|
|
549
|
+
// layer reads (defaults to post-fader when omitted).
|
|
550
|
+
return {
|
|
551
|
+
...lane,
|
|
552
|
+
sends: lane.sends.map((send) => ({
|
|
553
|
+
...send,
|
|
554
|
+
// Post-fader (0) is the default for an omitted sendTiming.
|
|
555
|
+
sendTiming: send.sendTiming === undefined ? 0 : sendTimingCode(send.sendTiming),
|
|
556
|
+
})),
|
|
557
|
+
};
|
|
558
|
+
}),
|
|
559
|
+
);
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
/**
|
|
563
|
+
* Keys one insert of a lane strip from another lane's post-strip audio
|
|
564
|
+
* (ducking/sidechainRouter inserts). sourceTrackId 0 removes the binding.
|
|
565
|
+
*/
|
|
566
|
+
setLaneSidechain(trackId: number, insertIndex: number, sourceTrackId: number): void {
|
|
567
|
+
this.native.setLaneSidechain(trackId, insertIndex, sourceTrackId);
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
setTrackBuses(buses: EngineBus[]): void {
|
|
571
|
+
this.native.setTrackBuses(buses);
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
setBusStripJson(busId: number, sceneJson: string): void {
|
|
575
|
+
try {
|
|
576
|
+
JSON.parse(sceneJson);
|
|
577
|
+
} catch (error) {
|
|
578
|
+
const message = error instanceof Error ? error.message : 'invalid bus strip JSON';
|
|
579
|
+
throw new SonareError(ErrorCode.InvalidFormat, 'InvalidFormat', message);
|
|
580
|
+
}
|
|
581
|
+
this.native.setBusStripJson(busId, sceneJson);
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
setTrackStripJson(trackId: number, sceneJson: string): void {
|
|
585
|
+
try {
|
|
586
|
+
JSON.parse(sceneJson);
|
|
587
|
+
} catch (error) {
|
|
588
|
+
const message = error instanceof Error ? error.message : 'invalid track strip JSON';
|
|
589
|
+
throw new SonareError(ErrorCode.InvalidFormat, 'InvalidFormat', message);
|
|
590
|
+
}
|
|
591
|
+
this.native.setTrackStripJson(trackId, sceneJson);
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
setTrackStripEqBand(trackId: number, bandIndex: number, band: EqBand | string): void {
|
|
595
|
+
this.native.setTrackStripEqBandJson(
|
|
596
|
+
trackId,
|
|
597
|
+
bandIndex,
|
|
598
|
+
typeof band === 'string' ? band : JSON.stringify(band),
|
|
599
|
+
);
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
setTrackStripEqBandJson(trackId: number, bandIndex: number, bandJson: string): void {
|
|
603
|
+
this.native.setTrackStripEqBandJson(trackId, bandIndex, bandJson);
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
setTrackStripInsertBypassed(
|
|
607
|
+
trackId: number,
|
|
608
|
+
insertIndex: number,
|
|
609
|
+
bypassed: boolean,
|
|
610
|
+
resetOnBypass = false,
|
|
611
|
+
): void {
|
|
612
|
+
this.native.setTrackStripInsertBypassed(trackId, insertIndex, bypassed, resetOnBypass);
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
setMasterStripJson(sceneJson: string): void {
|
|
616
|
+
try {
|
|
617
|
+
JSON.parse(sceneJson);
|
|
618
|
+
} catch (error) {
|
|
619
|
+
const message = error instanceof Error ? error.message : 'invalid master strip JSON';
|
|
620
|
+
throw new SonareError(ErrorCode.InvalidFormat, 'InvalidFormat', message);
|
|
621
|
+
}
|
|
622
|
+
this.native.setMasterStripJson(sceneJson);
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
setMasterStripEqBand(bandIndex: number, band: EqBand | string): void {
|
|
626
|
+
this.native.setMasterStripEqBandJson(
|
|
627
|
+
bandIndex,
|
|
628
|
+
typeof band === 'string' ? band : JSON.stringify(band),
|
|
629
|
+
);
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
setMasterStripEqBandJson(bandIndex: number, bandJson: string): void {
|
|
633
|
+
this.native.setMasterStripEqBandJson(bandIndex, bandJson);
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
setMasterStripInsertBypassed(
|
|
637
|
+
insertIndex: number,
|
|
638
|
+
bypassed: boolean,
|
|
639
|
+
resetOnBypass = false,
|
|
640
|
+
): void {
|
|
641
|
+
this.native.setMasterStripInsertBypassed(insertIndex, bypassed, resetOnBypass);
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
/**
|
|
645
|
+
* Changes one track-strip insert parameter in realtime, addressed by the
|
|
646
|
+
* processor's JSON-key parameter name (see {@link masteringInsertParamInfo}).
|
|
647
|
+
* Applied at the next block head via the engine command queue; safe during
|
|
648
|
+
* playback. Throws if the track, insert, or name is unknown, the param is not
|
|
649
|
+
* realtime-safe, or the command queue is full.
|
|
650
|
+
*/
|
|
651
|
+
setTrackStripInsertParamByName(
|
|
652
|
+
trackId: number,
|
|
653
|
+
insertIndex: number,
|
|
654
|
+
paramName: string,
|
|
655
|
+
value: number,
|
|
656
|
+
): void {
|
|
657
|
+
this.native.setTrackStripInsertParamByName(trackId, insertIndex, paramName, value);
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
/** Master-strip counterpart of {@link setTrackStripInsertParamByName}. */
|
|
661
|
+
setMasterStripInsertParamByName(insertIndex: number, paramName: string, value: number): void {
|
|
662
|
+
this.native.setMasterStripInsertParamByName(insertIndex, paramName, value);
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
/** Sets a track lane strip's pan position in realtime (glitch-free). */
|
|
666
|
+
setTrackStripPan(trackId: number, pan: number): void {
|
|
667
|
+
this.native.setTrackStripPan(trackId, pan);
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
/** Sets a track lane strip's pan law in realtime. */
|
|
671
|
+
setTrackStripPanLaw(trackId: number, panLaw: PanLaw | number): void {
|
|
672
|
+
this.native.setTrackStripPanLaw(trackId, panLawCode(panLaw));
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
/** Sets a track lane strip's pan mode in realtime. */
|
|
676
|
+
setTrackStripPanMode(trackId: number, panMode: PanMode | number): void {
|
|
677
|
+
this.native.setTrackStripPanMode(trackId, panModeCode(panMode));
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
/** Sets a track lane strip's dual-pan left/right positions in realtime. */
|
|
681
|
+
setTrackStripDualPan(trackId: number, leftPan: number, rightPan: number): void {
|
|
682
|
+
this.native.setTrackStripDualPan(trackId, leftPan, rightPan);
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
/**
|
|
686
|
+
* Sets a track lane strip's inter-channel alignment delay (whole samples).
|
|
687
|
+
* Adjusts strip latency, so PDC and reported graph latency are refreshed.
|
|
688
|
+
*/
|
|
689
|
+
setTrackStripChannelDelaySamples(trackId: number, delaySamples: number): void {
|
|
690
|
+
this.native.setTrackStripChannelDelaySamples(trackId, delaySamples);
|
|
691
|
+
}
|
|
692
|
+
|
|
516
693
|
createClipPageProvider(
|
|
517
694
|
numChannels: number,
|
|
518
695
|
numSamples: number,
|
|
519
696
|
pageFrames: number,
|
|
520
697
|
): ClipPageProvider {
|
|
521
|
-
const id = this.
|
|
698
|
+
const id = this.native.createClipPageProvider(numChannels, numSamples, pageFrames);
|
|
522
699
|
return new ClipPageProvider(this, id);
|
|
523
700
|
}
|
|
524
701
|
|
|
525
702
|
supplyClipPage(providerId: number, pageIndex: number, channels: Float32Array[]): void {
|
|
526
|
-
this.
|
|
703
|
+
this.native.supplyClipPage(providerId, pageIndex, channels);
|
|
527
704
|
}
|
|
528
705
|
|
|
529
706
|
clearClipPage(providerId: number, pageIndex: number): void {
|
|
530
|
-
this.
|
|
707
|
+
this.native.clearClipPage(providerId, pageIndex);
|
|
531
708
|
}
|
|
532
709
|
|
|
533
710
|
destroyClipPageProvider(providerId: number): void {
|
|
534
|
-
this.
|
|
711
|
+
this.native.destroyClipPageProvider(providerId);
|
|
535
712
|
}
|
|
536
713
|
|
|
537
714
|
popClipPageRequest(): ClipPageRequest | null {
|
|
538
|
-
return this.
|
|
715
|
+
return this.native.popClipPageRequest();
|
|
539
716
|
}
|
|
540
717
|
|
|
541
718
|
setCaptureBuffer(numChannels: number, capacityFrames: number): void {
|
|
@@ -630,6 +807,33 @@ export class RealtimeEngine {
|
|
|
630
807
|
return this.native.drainMeterTelemetry(maxRecords);
|
|
631
808
|
}
|
|
632
809
|
|
|
810
|
+
/**
|
|
811
|
+
* Drains pending meter telemetry as per-plane (wide) records for a surround
|
|
812
|
+
* target. Use this for a surround mix target; {@link drainMeterTelemetry}
|
|
813
|
+
* stays the stereo fast path. The two share one queue — call only one per
|
|
814
|
+
* target. The live AudioWorklet path owns the queue via the stereo drain, so
|
|
815
|
+
* this wide drain is for an offline (non-worklet) engine instance; per-plane
|
|
816
|
+
* surround meters are not delivered over the live worklet meter ring.
|
|
817
|
+
*/
|
|
818
|
+
drainMeterTelemetryWide(maxRecords = 1024): EngineMeterTelemetryWide[] {
|
|
819
|
+
return this.native.drainMeterTelemetryWide(maxRecords);
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
/**
|
|
823
|
+
* Enables per-target spectrum + vectorscope capture. @param intervalFrames is
|
|
824
|
+
* the minimum render-frame gap between snapshots (0 disables). @param bandCount
|
|
825
|
+
* is the FFT band resolution (1..64); changing it re-prepares the tap. Returns
|
|
826
|
+
* the band count actually applied.
|
|
827
|
+
*/
|
|
828
|
+
configureScopeTelemetry(intervalFrames: number, bandCount: number): number {
|
|
829
|
+
return this.native.configureScopeTelemetry(intervalFrames, bandCount);
|
|
830
|
+
}
|
|
831
|
+
|
|
832
|
+
/** Drains pending spectrum + vectorscope snapshots (per mix target). */
|
|
833
|
+
drainScopeTelemetry(maxRecords = 1024): EngineScopeTelemetry[] {
|
|
834
|
+
return this.native.drainScopeTelemetry(maxRecords);
|
|
835
|
+
}
|
|
836
|
+
|
|
633
837
|
destroy(): void {
|
|
634
838
|
this.native.delete();
|
|
635
839
|
}
|