@libraz/libsonare 1.7.2 → 1.8.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/NOTICE +178 -0
- package/README.md +26 -203
- package/dist/_chain_config.d.ts +14 -0
- package/dist/_chain_config.d.ts.map +1 -0
- package/dist/_effects_common.d.ts +6 -0
- package/dist/_effects_common.d.ts.map +1 -0
- package/dist/_feature_validation.d.ts +8 -0
- package/dist/_feature_validation.d.ts.map +1 -0
- package/dist/_fft_options.d.ts +24 -0
- package/dist/_fft_options.d.ts.map +1 -0
- package/dist/align_take.d.ts +50 -0
- package/dist/align_take.d.ts.map +1 -0
- package/dist/analysis.d.ts +29 -5840
- package/dist/analysis.d.ts.map +1 -0
- package/dist/analysis.js +873 -722
- package/dist/analysis.js.map +1 -1
- package/dist/analysis_helpers.d.ts +9 -0
- package/dist/analysis_helpers.d.ts.map +1 -0
- package/dist/audio.d.ts +163 -0
- package/dist/audio.d.ts.map +1 -0
- package/dist/clip_page_streamer.d.ts +133 -0
- package/dist/clip_page_streamer.d.ts.map +1 -0
- package/dist/codes.d.ts +44 -0
- package/dist/codes.d.ts.map +1 -0
- package/dist/effects_mastering.d.ts +23 -0
- package/dist/effects_mastering.d.ts.map +1 -0
- package/dist/effects_note_ops.d.ts +477 -0
- package/dist/effects_note_ops.d.ts.map +1 -0
- package/dist/effects_percussive.d.ts +185 -0
- package/dist/effects_percussive.d.ts.map +1 -0
- package/dist/effects_separation.d.ts +65 -0
- package/dist/effects_separation.d.ts.map +1 -0
- package/dist/effects_spectral.d.ts +28 -0
- package/dist/effects_spectral.d.ts.map +1 -0
- package/dist/effects_timepitch.d.ts +129 -0
- package/dist/effects_timepitch.d.ts.map +1 -0
- package/dist/effects_voice_change.d.ts +53 -0
- package/dist/effects_voice_change.d.ts.map +1 -0
- package/dist/errors.d.ts +51 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/feature_core.d.ts +341 -0
- package/dist/feature_core.d.ts.map +1 -0
- package/dist/feature_decompose.d.ts +278 -0
- package/dist/feature_decompose.d.ts.map +1 -0
- package/dist/feature_inverse.d.ts +128 -0
- package/dist/feature_inverse.d.ts.map +1 -0
- package/dist/feature_loudness.d.ts +66 -0
- package/dist/feature_loudness.d.ts.map +1 -0
- package/dist/feature_music.d.ts +307 -0
- package/dist/feature_music.d.ts.map +1 -0
- package/dist/feature_pitch.d.ts +108 -0
- package/dist/feature_pitch.d.ts.map +1 -0
- package/dist/feature_resample.d.ts +16 -0
- package/dist/feature_resample.d.ts.map +1 -0
- package/dist/feature_spectral.d.ts +137 -0
- package/dist/feature_spectral.d.ts.map +1 -0
- package/dist/feature_spectrogram.d.ts +198 -0
- package/dist/feature_spectrogram.d.ts.map +1 -0
- package/dist/features.d.ts +10 -0
- package/dist/features.d.ts.map +1 -0
- package/dist/hrtf/default.shrf +0 -0
- package/dist/index.d.ts +74 -7431
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3758 -1362
- package/dist/index.js.map +1 -1
- package/dist/instrument_types.d.ts +517 -0
- package/dist/instrument_types.d.ts.map +1 -0
- package/dist/live_audio.d.ts +35 -0
- package/dist/live_audio.d.ts.map +1 -0
- package/dist/mastering_chain.d.ts +213 -0
- package/dist/mastering_chain.d.ts.map +1 -0
- package/dist/mastering_core.d.ts +457 -0
- package/dist/mastering_core.d.ts.map +1 -0
- package/dist/mastering_dynamics.d.ts +80 -0
- package/dist/mastering_dynamics.d.ts.map +1 -0
- package/dist/metering.d.ts +287 -0
- package/dist/metering.d.ts.map +1 -0
- package/dist/mixer.d.ts +464 -0
- package/dist/mixer.d.ts.map +1 -0
- package/dist/mixing_assistant.d.ts +62 -0
- package/dist/mixing_assistant.d.ts.map +1 -0
- package/dist/mixing_oneshot.d.ts +40 -0
- package/dist/mixing_oneshot.d.ts.map +1 -0
- package/dist/module_state.d.ts +15 -0
- package/dist/module_state.d.ts.map +1 -0
- package/dist/opfs_clip_pages.d.ts +28 -0
- package/dist/opfs_clip_pages.d.ts.map +1 -0
- package/dist/playback_renderer.d.ts +128 -0
- package/dist/playback_renderer.d.ts.map +1 -0
- package/dist/polyphony.d.ts +202 -0
- package/dist/polyphony.d.ts.map +1 -0
- package/dist/project.d.ts +8 -0
- package/dist/project.d.ts.map +1 -0
- package/dist/project_class.d.ts +562 -0
- package/dist/project_class.d.ts.map +1 -0
- package/dist/project_internal.d.ts +194 -0
- package/dist/project_internal.d.ts.map +1 -0
- package/dist/project_synth.d.ts +74 -0
- package/dist/project_synth.d.ts.map +1 -0
- package/dist/project_types.d.ts +652 -0
- package/dist/project_types.d.ts.map +1 -0
- package/dist/public_types.d.ts +185 -0
- package/dist/public_types.d.ts.map +1 -0
- package/dist/public_types_acoustic.d.ts +215 -0
- package/dist/public_types_acoustic.d.ts.map +1 -0
- package/dist/public_types_mastering.d.ts +510 -0
- package/dist/public_types_mastering.d.ts.map +1 -0
- package/dist/public_types_mixing.d.ts +436 -0
- package/dist/public_types_mixing.d.ts.map +1 -0
- package/dist/public_types_music.d.ts +619 -0
- package/dist/public_types_music.d.ts.map +1 -0
- package/dist/public_types_playback.d.ts +164 -0
- package/dist/public_types_playback.d.ts.map +1 -0
- package/dist/public_types_realtime.d.ts +174 -0
- package/dist/public_types_realtime.d.ts.map +1 -0
- package/dist/public_types_repair.d.ts +424 -0
- package/dist/public_types_repair.d.ts.map +1 -0
- package/dist/public_types_spectral.d.ts +697 -0
- package/dist/public_types_spectral.d.ts.map +1 -0
- package/dist/quick_analysis.d.ts +445 -0
- package/dist/quick_analysis.d.ts.map +1 -0
- package/dist/realtime_engine.d.ts +850 -0
- package/dist/realtime_engine.d.ts.map +1 -0
- package/dist/realtime_voice_changer.d.ts +158 -0
- package/dist/realtime_voice_changer.d.ts.map +1 -0
- package/dist/repair_dereverb.d.ts +187 -0
- package/dist/repair_dereverb.d.ts.map +1 -0
- package/dist/repair_impulsive.d.ts +186 -0
- package/dist/repair_impulsive.d.ts.map +1 -0
- package/dist/repair_noise.d.ts +239 -0
- package/dist/repair_noise.d.ts.map +1 -0
- package/dist/repair_trim.d.ts +123 -0
- package/dist/repair_trim.d.ts.map +1 -0
- package/dist/sample_bank.d.ts +84 -0
- package/dist/sample_bank.d.ts.map +1 -0
- package/dist/scale.d.ts +10 -0
- package/dist/scale.d.ts.map +1 -0
- package/dist/schemas/mixer-scene.schema.json +393 -0
- package/dist/schemas/playback-renderer-config.schema.json +392 -0
- package/dist/sonare-analysis.d.ts +8 -0
- package/dist/sonare-analysis.js +2 -2
- package/dist/sonare-analysis.wasm +0 -0
- package/dist/sonare.d.ts +3909 -0
- package/dist/sonare.js +2 -2
- package/dist/sonare.wasm +0 -0
- package/dist/stream_analyzer.d.ts +163 -0
- package/dist/stream_analyzer.d.ts.map +1 -0
- package/dist/stream_types.d.ts +214 -0
- package/dist/stream_types.d.ts.map +1 -0
- package/dist/streaming_mixing.d.ts +6 -0
- package/dist/streaming_mixing.d.ts.map +1 -0
- package/dist/streaming_processors.d.ts +335 -0
- package/dist/streaming_processors.d.ts.map +1 -0
- package/dist/transcribe.d.ts +77 -0
- package/dist/transcribe.d.ts.map +1 -0
- package/dist/validation.d.ts +140 -0
- package/dist/validation.d.ts.map +1 -0
- package/dist/web_midi.d.ts +77 -0
- package/dist/web_midi.d.ts.map +1 -0
- package/dist/worker.d.ts +5 -48
- package/dist/worker.d.ts.map +1 -0
- package/dist/worker.js +94 -41
- package/dist/worker.js.map +1 -1
- package/dist/worker_client.d.ts +96 -0
- package/dist/worker_client.d.ts.map +1 -0
- package/dist/worker_protocol.d.ts +43 -0
- package/dist/worker_protocol.d.ts.map +1 -0
- package/dist/worklet/audio_types.d.ts +21 -0
- package/dist/worklet/audio_types.d.ts.map +1 -0
- package/dist/worklet/engine-automation.d.ts +29 -0
- package/dist/worklet/engine-automation.d.ts.map +1 -0
- package/dist/worklet/engine-capture-facade.d.ts +35 -0
- package/dist/worklet/engine-capture-facade.d.ts.map +1 -0
- package/dist/worklet/engine-clips.d.ts +23 -0
- package/dist/worklet/engine-clips.d.ts.map +1 -0
- package/dist/worklet/engine-markers.d.ts +40 -0
- package/dist/worklet/engine-markers.d.ts.map +1 -0
- package/dist/worklet/engine-mixer-facade.d.ts +128 -0
- package/dist/worklet/engine-mixer-facade.d.ts.map +1 -0
- package/dist/worklet/engine-node.d.ts +81 -0
- package/dist/worklet/engine-node.d.ts.map +1 -0
- package/dist/worklet/engine-offline.d.ts +81 -0
- package/dist/worklet/engine-offline.d.ts.map +1 -0
- package/dist/worklet/engine-options.d.ts +12 -0
- package/dist/worklet/engine-options.d.ts.map +1 -0
- package/dist/worklet/engine-parameter-facade.d.ts +106 -0
- package/dist/worklet/engine-parameter-facade.d.ts.map +1 -0
- package/dist/worklet/engine-processor.d.ts +68 -0
- package/dist/worklet/engine-processor.d.ts.map +1 -0
- package/dist/worklet/engine-register.d.ts +2 -0
- package/dist/worklet/engine-register.d.ts.map +1 -0
- package/dist/worklet/engine-strips.d.ts +73 -0
- package/dist/worklet/engine-strips.d.ts.map +1 -0
- package/dist/worklet/engine-sync.d.ts +37 -0
- package/dist/worklet/engine-sync.d.ts.map +1 -0
- package/dist/worklet/engine-tempo-facade.d.ts +48 -0
- package/dist/worklet/engine-tempo-facade.d.ts.map +1 -0
- package/dist/worklet/engine.d.ts +397 -0
- package/dist/worklet/engine.d.ts.map +1 -0
- package/dist/worklet/guards.d.ts +47 -0
- package/dist/worklet/guards.d.ts.map +1 -0
- package/dist/worklet/messages.d.ts +710 -0
- package/dist/worklet/messages.d.ts.map +1 -0
- package/dist/worklet/mixer-processor.d.ts +46 -0
- package/dist/worklet/mixer-processor.d.ts.map +1 -0
- package/dist/worklet/playback-processor.d.ts +62 -0
- package/dist/worklet/playback-processor.d.ts.map +1 -0
- package/dist/worklet/protocol.d.ts +323 -0
- package/dist/worklet/protocol.d.ts.map +1 -0
- package/dist/worklet/voice-changer-processor.d.ts +41 -0
- package/dist/worklet/voice-changer-processor.d.ts.map +1 -0
- package/dist/worklet.d.ts +16 -2515
- package/dist/worklet.d.ts.map +1 -0
- package/dist/worklet.js +2763 -501
- package/dist/worklet.js.map +1 -1
- package/package.json +23 -12
- package/src/_effects_common.ts +17 -0
- package/src/_feature_validation.ts +34 -0
- package/src/_fft_options.ts +39 -0
- package/src/align_take.ts +64 -0
- package/src/analysis.ts +56 -3
- package/src/analysis_helpers.ts +7 -0
- package/src/audio.ts +106 -3
- package/src/codes.ts +39 -2
- package/src/effects_mastering.ts +97 -22
- package/src/effects_note_ops.ts +635 -0
- package/src/effects_percussive.ts +217 -0
- package/src/effects_separation.ts +150 -0
- package/src/effects_spectral.ts +60 -0
- package/src/effects_timepitch.ts +377 -0
- package/src/errors.ts +23 -1
- package/src/feature_core.ts +127 -2
- package/src/feature_decompose.ts +633 -0
- package/src/feature_inverse.ts +454 -0
- package/src/feature_loudness.ts +125 -0
- package/src/feature_music.ts +107 -14
- package/src/feature_pitch.ts +96 -1
- package/src/feature_spectral.ts +16 -611
- package/src/feature_spectrogram.ts +63 -450
- package/src/features.ts +36 -22
- package/src/index.ts +282 -30
- package/src/instrument_types.ts +645 -0
- package/src/live_audio.ts +27 -1
- package/src/mastering_chain.ts +184 -0
- package/src/mastering_core.ts +346 -32
- package/src/mastering_dynamics.ts +22 -11
- package/src/metering.ts +67 -24
- package/src/mixer.ts +212 -3
- package/src/mixing_assistant.ts +138 -0
- package/src/mixing_oneshot.ts +10 -5
- package/src/module_state.ts +24 -2
- package/src/playback_renderer.ts +252 -0
- package/src/polyphony.ts +279 -0
- package/src/project.ts +61 -24
- package/src/project_class.ts +450 -27
- package/src/project_internal.ts +149 -42
- package/src/project_synth.ts +67 -1
- package/src/project_types.ts +268 -270
- package/src/public_types.ts +122 -3
- package/src/public_types_acoustic.ts +112 -3
- package/src/public_types_mastering.ts +254 -73
- package/src/public_types_mixing.ts +363 -1
- package/src/public_types_music.ts +312 -2
- package/src/public_types_playback.ts +195 -0
- package/src/public_types_realtime.ts +39 -7
- package/src/public_types_repair.ts +446 -0
- package/src/public_types_spectral.ts +487 -1
- package/src/quick_analysis.ts +203 -26
- package/src/realtime_engine.ts +711 -28
- package/src/realtime_voice_changer.ts +55 -1
- package/src/repair_dereverb.ts +299 -0
- package/src/repair_impulsive.ts +395 -0
- package/src/repair_noise.ts +425 -0
- package/src/repair_trim.ts +226 -0
- package/src/sample_bank.ts +113 -0
- package/src/sonare.js.d.ts +1122 -30
- package/src/stream_analyzer.ts +36 -4
- package/src/stream_types.ts +37 -0
- package/src/streaming_mixing.ts +1 -1
- package/src/streaming_processors.ts +194 -10
- package/src/transcribe.ts +89 -0
- package/src/validation.ts +285 -11
- package/src/web_midi.ts +1 -6
- package/src/worker.ts +18 -2
- package/src/worklet/audio_types.ts +37 -0
- package/src/worklet/engine-mixer-facade.ts +444 -10
- package/src/worklet/engine-node.ts +78 -26
- package/src/worklet/engine-offline.ts +14 -8
- package/src/worklet/engine-parameter-facade.ts +21 -0
- package/src/worklet/engine-processor.ts +272 -83
- package/src/worklet/engine-register.ts +32 -18
- package/src/worklet/engine-strips.ts +280 -9
- package/src/worklet/engine-sync.ts +14 -6
- package/src/worklet/engine.ts +365 -31
- package/src/worklet/guards.ts +140 -44
- package/src/worklet/messages.ts +227 -2
- package/src/worklet/mixer-processor.ts +109 -47
- package/src/worklet/playback-processor.ts +300 -0
- package/src/worklet/protocol.ts +53 -3
- package/src/worklet/voice-changer-processor.ts +17 -11
- package/src/worklet.ts +17 -0
- package/src/effects_transform.ts +0 -718
- package/src/mastering_repair.ts +0 -273
|
@@ -9,6 +9,8 @@ import {
|
|
|
9
9
|
isEngineTransportResponseMessage,
|
|
10
10
|
isExternalMidiBatchMessage,
|
|
11
11
|
isMeterSnapshot,
|
|
12
|
+
requireChannelCount,
|
|
13
|
+
requireIntegerOption,
|
|
12
14
|
} from './guards';
|
|
13
15
|
import type {
|
|
14
16
|
SonareEngineCaptureRequestMessage,
|
|
@@ -29,6 +31,7 @@ import {
|
|
|
29
31
|
createSonareMeterRingBuffer,
|
|
30
32
|
createSonareScopeRingBuffer,
|
|
31
33
|
isRecord,
|
|
34
|
+
isUint32Slot,
|
|
32
35
|
pushSonareEngineCommandRingBuffer,
|
|
33
36
|
readSonareClipPageRequestRingBuffer,
|
|
34
37
|
readSonareEngineTelemetryRingBuffer,
|
|
@@ -63,13 +66,6 @@ function isTrackMonitorMode(value: number | bigint | undefined): boolean {
|
|
|
63
66
|
return typeof mode === 'number' && Number.isSafeInteger(mode) && mode >= 0 && mode <= 2;
|
|
64
67
|
}
|
|
65
68
|
|
|
66
|
-
/** A track-monitor command cannot infer a lane: its target is a uint32 index. */
|
|
67
|
-
function isTrackMonitorLaneIndex(value: number | undefined): boolean {
|
|
68
|
-
return (
|
|
69
|
-
typeof value === 'number' && Number.isSafeInteger(value) && value >= 0 && value <= 0xffff_ffff
|
|
70
|
-
);
|
|
71
|
-
}
|
|
72
|
-
|
|
73
69
|
function isValidCommandRecord(command: SonareEngineCommandRecord): boolean {
|
|
74
70
|
const type = Number(command.type);
|
|
75
71
|
if (
|
|
@@ -81,12 +77,15 @@ function isValidCommandRecord(command: SonareEngineCommandRecord): boolean {
|
|
|
81
77
|
return false;
|
|
82
78
|
}
|
|
83
79
|
return (
|
|
84
|
-
|
|
80
|
+
// The record writer refuses a targetId outside the slot by throwing, and
|
|
81
|
+
// this path answers false instead, so it must reject the same domain here.
|
|
82
|
+
(command.targetId === undefined || isUint32Slot(command.targetId)) &&
|
|
85
83
|
(command.argFloat === undefined || Number.isFinite(command.argFloat)) &&
|
|
86
84
|
isFiniteInteger(command.argInt) &&
|
|
87
85
|
isFiniteInteger(command.sampleTime) &&
|
|
86
|
+
// A track-monitor command cannot infer a lane: its target is required.
|
|
88
87
|
(type !== SonareEngineCommandType.SetTrackMonitorMode ||
|
|
89
|
-
(
|
|
88
|
+
(isUint32Slot(command.targetId) && isTrackMonitorMode(command.argInt)))
|
|
90
89
|
);
|
|
91
90
|
}
|
|
92
91
|
|
|
@@ -172,6 +171,12 @@ export class SonareRealtimeEngineNode {
|
|
|
172
171
|
this.resolveReady();
|
|
173
172
|
}
|
|
174
173
|
this.node.port.onmessage = (event: MessageEvent<unknown>) => {
|
|
174
|
+
// A host that kept its own reference to this handler (or a port
|
|
175
|
+
// implementation that ignores the detach in destroy()) must not be able
|
|
176
|
+
// to reach listeners of a node the host already disposed.
|
|
177
|
+
if (this.destroyed) {
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
175
180
|
const captureRequestId = engineCaptureResponseRequestId(event.data);
|
|
176
181
|
if (captureRequestId !== undefined) {
|
|
177
182
|
const pending = this.captureRequests.get(captureRequestId);
|
|
@@ -208,7 +213,7 @@ export class SonareRealtimeEngineNode {
|
|
|
208
213
|
} else if (isRecord(event.data) && event.data.type === 'syncError') {
|
|
209
214
|
const syncError: SonareEngineSyncErrorMessage = {
|
|
210
215
|
type: 'syncError',
|
|
211
|
-
syncType: String(event.data.syncType)
|
|
216
|
+
syncType: String(event.data.syncType),
|
|
212
217
|
message: String(event.data.message ?? 'AudioWorklet sync failed'),
|
|
213
218
|
};
|
|
214
219
|
for (const listener of this.syncErrorListeners) {
|
|
@@ -268,39 +273,80 @@ export class SonareRealtimeEngineNode {
|
|
|
268
273
|
);
|
|
269
274
|
}
|
|
270
275
|
|
|
276
|
+
// Resolved before the transport branch, so a capacity the ring could not
|
|
277
|
+
// hold is refused by name whichever transport the caller ends up with.
|
|
278
|
+
const commandRingCapacity = requireIntegerOption(
|
|
279
|
+
options.commandRingCapacity,
|
|
280
|
+
128,
|
|
281
|
+
'commandRingCapacity',
|
|
282
|
+
1,
|
|
283
|
+
);
|
|
284
|
+
if (commandRingCapacity > 65536) {
|
|
285
|
+
throw new RangeError('commandRingCapacity must be at most 65536');
|
|
286
|
+
}
|
|
287
|
+
const telemetryRingCapacity = requireIntegerOption(
|
|
288
|
+
options.telemetryRingCapacity,
|
|
289
|
+
128,
|
|
290
|
+
'telemetryRingCapacity',
|
|
291
|
+
1,
|
|
292
|
+
);
|
|
293
|
+
const meterRingCapacity = requireIntegerOption(
|
|
294
|
+
options.meterRingCapacity,
|
|
295
|
+
128,
|
|
296
|
+
'meterRingCapacity',
|
|
297
|
+
1,
|
|
298
|
+
);
|
|
299
|
+
const scopeRingCapacity = requireIntegerOption(
|
|
300
|
+
options.scopeRingCapacity,
|
|
301
|
+
64,
|
|
302
|
+
'scopeRingCapacity',
|
|
303
|
+
1,
|
|
304
|
+
);
|
|
305
|
+
const scopeBands = requireIntegerOption(options.scopeBands, 48, 'scopeBands', 1);
|
|
306
|
+
const clipPageRequestRingCapacity = requireIntegerOption(
|
|
307
|
+
options.clipPageRequestRingCapacity,
|
|
308
|
+
128,
|
|
309
|
+
'clipPageRequestRingCapacity',
|
|
310
|
+
1,
|
|
311
|
+
);
|
|
312
|
+
const externalMidiRingCapacity = requireIntegerOption(
|
|
313
|
+
options.externalMidiRingCapacity,
|
|
314
|
+
256,
|
|
315
|
+
'externalMidiRingCapacity',
|
|
316
|
+
1,
|
|
317
|
+
);
|
|
271
318
|
const commandRing =
|
|
272
|
-
mode === 'sab'
|
|
273
|
-
? createSonareEngineCommandRingBuffer(options.commandRingCapacity ?? 128)
|
|
274
|
-
: undefined;
|
|
319
|
+
mode === 'sab' ? createSonareEngineCommandRingBuffer(commandRingCapacity) : undefined;
|
|
275
320
|
const telemetryRing =
|
|
276
|
-
mode === 'sab'
|
|
277
|
-
? createSonareEngineTelemetryRingBuffer(options.telemetryRingCapacity ?? 128)
|
|
278
|
-
: undefined;
|
|
321
|
+
mode === 'sab' ? createSonareEngineTelemetryRingBuffer(telemetryRingCapacity) : undefined;
|
|
279
322
|
// Meter ring: the engine publishes meters into a SAB ring. Lock-free meter
|
|
280
323
|
// delivery matches the telemetry path and keeps the audio render callback
|
|
281
324
|
// allocation-free in SAB mode.
|
|
282
|
-
const meterRing =
|
|
283
|
-
mode === 'sab' ? createSonareMeterRingBuffer(options.meterRingCapacity ?? 128) : undefined;
|
|
325
|
+
const meterRing = mode === 'sab' ? createSonareMeterRingBuffer(meterRingCapacity) : undefined;
|
|
284
326
|
// Scope ring (FFT spectrum + goniometer): opt-in. The per-block FFT is
|
|
285
327
|
// heavier than the meter path, so it is created only when the caller
|
|
286
|
-
// requests scope telemetry via scopeIntervalFrames > 0.
|
|
287
|
-
|
|
328
|
+
// requests scope telemetry via scopeIntervalFrames > 0. Zero is the off
|
|
329
|
+
// switch, so the interval's floor is 0 rather than the capacities' 1.
|
|
330
|
+
const scopeIntervalFrames = requireIntegerOption(
|
|
331
|
+
options.scopeIntervalFrames,
|
|
332
|
+
0,
|
|
333
|
+
'scopeIntervalFrames',
|
|
334
|
+
0,
|
|
335
|
+
);
|
|
288
336
|
const scopeRing =
|
|
289
337
|
mode === 'sab' && scopeIntervalFrames > 0
|
|
290
|
-
? createSonareScopeRingBuffer(
|
|
338
|
+
? createSonareScopeRingBuffer(scopeRingCapacity, scopeBands)
|
|
291
339
|
: undefined;
|
|
292
340
|
// Paged-clip cache misses are a worklet-to-main-thread control signal. A
|
|
293
341
|
// dedicated SPSC SAB ring keeps process() free of both embind request
|
|
294
342
|
// objects and postMessage structured cloning.
|
|
295
343
|
const clipPageRequestRing =
|
|
296
344
|
mode === 'sab'
|
|
297
|
-
? createSonareClipPageRequestRingBuffer(
|
|
345
|
+
? createSonareClipPageRequestRingBuffer(clipPageRequestRingCapacity)
|
|
298
346
|
: undefined;
|
|
299
347
|
const externalMidiRing =
|
|
300
|
-
mode === 'sab'
|
|
301
|
-
|
|
302
|
-
: undefined;
|
|
303
|
-
const channelCount = Math.max(1, Math.floor(options.channelCount ?? 2));
|
|
348
|
+
mode === 'sab' ? createSonareExternalMidiRingBuffer(externalMidiRingCapacity) : undefined;
|
|
349
|
+
const channelCount = requireChannelCount(options.channelCount, 2);
|
|
304
350
|
const cueOutput = options.cueOutput === true;
|
|
305
351
|
const processorOptions: SonareRealtimeEngineWorkletProcessorOptions = {
|
|
306
352
|
sampleRate: options.sampleRate ?? context.sampleRate,
|
|
@@ -600,6 +646,12 @@ export class SonareRealtimeEngineNode {
|
|
|
600
646
|
this.scopeListeners.clear();
|
|
601
647
|
this.midiOutListeners.clear();
|
|
602
648
|
this.clipPageRequestListeners.clear();
|
|
649
|
+
this.syncErrorListeners.clear();
|
|
650
|
+
// The port outlives destroy(): the worklet tears itself down asynchronously
|
|
651
|
+
// after the 'destroy' message above, so a syncError already in flight would
|
|
652
|
+
// still be dispatched here. Detaching the handler is what makes the
|
|
653
|
+
// listener sets stay empty rather than being refilled by a late message.
|
|
654
|
+
this.node.port.onmessage = null;
|
|
603
655
|
}
|
|
604
656
|
|
|
605
657
|
private emitTelemetry(telemetry: SonareEngineTelemetryRecord): void {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { EngineCaptureStatus, EngineMarker, EngineTrackLane, RealtimeEngine } from '../index';
|
|
2
|
+
import { requireChannelCount, requireInteger, requireIntegerOption } from './guards';
|
|
2
3
|
import type { SonareEngineSyncCaptureMessage, SonareEngineTransportFacade } from './messages';
|
|
3
4
|
|
|
4
5
|
/** Capture configuration options accepted by the engine's `configureCapture`. */
|
|
@@ -12,20 +13,22 @@ export interface CaptureOptions {
|
|
|
12
13
|
|
|
13
14
|
/**
|
|
14
15
|
* Normalizes capture options into the resolved config carried by the
|
|
15
|
-
* `syncCapture` message, applying
|
|
16
|
+
* `syncCapture` message, applying defaults and refusing a non-integer count.
|
|
16
17
|
*
|
|
17
18
|
* @param options Raw capture options.
|
|
18
19
|
* @param defaultChannels Channel count to use when `options.channels` is unset.
|
|
20
|
+
* @throws RangeError if a frame count, channel count or offset is not an integer.
|
|
19
21
|
*/
|
|
20
22
|
export function buildCaptureConfig(
|
|
21
23
|
options: CaptureOptions,
|
|
22
24
|
defaultChannels: number,
|
|
23
25
|
): Omit<SonareEngineSyncCaptureMessage, 'type'> {
|
|
24
26
|
return {
|
|
25
|
-
bufferFrames
|
|
26
|
-
|
|
27
|
+
// bufferFrames has no default; NaN makes the guard refuse an absent value.
|
|
28
|
+
bufferFrames: requireIntegerOption(options.bufferFrames, Number.NaN, 'bufferFrames', 1),
|
|
29
|
+
channels: requireChannelCount(options.channels, defaultChannels),
|
|
27
30
|
source: options.source ?? 'output',
|
|
28
|
-
recordOffsetSamples:
|
|
31
|
+
recordOffsetSamples: requireInteger(options.recordOffsetSamples, 0, 'recordOffsetSamples'),
|
|
29
32
|
inputMonitor: {
|
|
30
33
|
enabled: Boolean(options.inputMonitor?.enabled),
|
|
31
34
|
gain: options.inputMonitor?.gain ?? 1,
|
|
@@ -111,7 +114,7 @@ export function normalizeTrackLanes(
|
|
|
111
114
|
const ids: number[] = [];
|
|
112
115
|
for (const entry of entries) {
|
|
113
116
|
if (!Number.isInteger(entry.trackId) || entry.trackId <= 0) {
|
|
114
|
-
throw new
|
|
117
|
+
throw new RangeError(`Invalid track id for mixer lane: ${String(entry.trackId)}`);
|
|
115
118
|
}
|
|
116
119
|
ids.push(entry.trackId);
|
|
117
120
|
}
|
|
@@ -145,12 +148,15 @@ export function resolveMarkerSet(
|
|
|
145
148
|
const seen = new Set<number>();
|
|
146
149
|
let counter = nextMarkerId;
|
|
147
150
|
for (const marker of markers) {
|
|
148
|
-
|
|
149
|
-
|
|
151
|
+
// Non-negative as well as finite, which is the domain the native setter
|
|
152
|
+
// enforces; checking only finiteness here hands a negative ppq on to be
|
|
153
|
+
// refused a layer down, under that layer's name for the argument.
|
|
154
|
+
if (!Number.isFinite(marker.ppq) || marker.ppq < 0) {
|
|
155
|
+
throw new RangeError(`Invalid marker ppq: ${String(marker.ppq)}`);
|
|
150
156
|
}
|
|
151
157
|
if (marker.id !== undefined) {
|
|
152
158
|
if (!Number.isInteger(marker.id) || marker.id <= 0) {
|
|
153
|
-
throw new
|
|
159
|
+
throw new RangeError(`Invalid marker id: ${String(marker.id)}`);
|
|
154
160
|
}
|
|
155
161
|
if (seen.has(marker.id)) {
|
|
156
162
|
throw new Error(`Duplicate marker id: ${marker.id}`);
|
|
@@ -190,6 +190,27 @@ export function resolveBusInsertAutomationId(
|
|
|
190
190
|
return ctx.offlineEngine.resolveBusInsertAutomationId(busId, insertIndex, paramName);
|
|
191
191
|
}
|
|
192
192
|
|
|
193
|
+
/**
|
|
194
|
+
* Resolves a hosted instrument's continuous parameter to its reserved
|
|
195
|
+
* instrument-automation id, so an instrument parameter is driven from a
|
|
196
|
+
* breakpoint lane at audio-block precision like a strip insert.
|
|
197
|
+
*
|
|
198
|
+
* The instrument must already be bound on the offline engine for the
|
|
199
|
+
* destination (the worklet mirrors every instrument sync onto it), otherwise
|
|
200
|
+
* the resolve returns -1.
|
|
201
|
+
*
|
|
202
|
+
* @param destinationId MIDI destination the instrument is bound to.
|
|
203
|
+
* @param paramName Instrument JSON-key parameter name (e.g. `cutoffHz`).
|
|
204
|
+
* @returns Reserved instrument-automation id, or -1 when destination/key unknown.
|
|
205
|
+
*/
|
|
206
|
+
export function resolveInstrumentAutomationId(
|
|
207
|
+
ctx: EngineParameterContext,
|
|
208
|
+
destinationId: number,
|
|
209
|
+
paramName: string,
|
|
210
|
+
): number {
|
|
211
|
+
return ctx.offlineEngine.resolveInstrumentAutomationId(destinationId, paramName);
|
|
212
|
+
}
|
|
213
|
+
|
|
193
214
|
/**
|
|
194
215
|
* Returns the number of automation lanes installed on the engine, including
|
|
195
216
|
* lanes whose breakpoint list is currently empty.
|