@libraz/libsonare 1.5.4 → 1.6.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 +109 -20
- package/dist/analysis.d.ts +5730 -0
- package/dist/analysis.js +2464 -0
- package/dist/analysis.js.map +1 -0
- package/dist/index.d.ts +873 -63
- package/dist/index.js +1037 -265
- package/dist/index.js.map +1 -1
- package/dist/schemas/realtime-voice-changer-preset-pack.schema.json +27 -0
- package/dist/schemas/realtime-voice-changer-preset.schema.json +140 -0
- package/dist/sonare-analysis.js +2 -0
- package/dist/sonare-analysis.wasm +0 -0
- package/dist/sonare.js +1 -1
- package/dist/sonare.wasm +0 -0
- package/dist/worker.d.ts +65 -0
- package/dist/worker.js +707 -0
- package/dist/worker.js.map +1 -0
- package/dist/worklet.d.ts +596 -86
- package/dist/worklet.js +1658 -235
- package/dist/worklet.js.map +1 -1
- package/package.json +23 -11
- package/src/_chain_config.ts +5 -23
- package/src/analysis.ts +137 -0
- package/src/analysis_helpers.ts +29 -0
- package/src/audio.ts +5 -3
- package/src/clip_page_streamer.ts +62 -8
- package/src/codes.ts +51 -64
- package/src/effects_mastering.ts +1 -0
- package/src/effects_transform.ts +12 -6
- package/src/errors.ts +1 -0
- package/src/feature_core.ts +159 -3
- package/src/feature_music.ts +35 -16
- package/src/feature_pitch.ts +75 -6
- package/src/feature_spectral.ts +234 -8
- package/src/feature_spectrogram.ts +186 -5
- package/src/features.ts +16 -1
- package/src/index.ts +104 -7
- package/src/mastering_chain.ts +20 -8
- package/src/mastering_core.ts +7 -0
- package/src/mastering_dynamics.ts +7 -1
- package/src/metering.ts +51 -5
- package/src/mixer.ts +14 -1
- package/src/opfs_clip_pages.ts +26 -1
- package/src/project.ts +7 -0
- package/src/project_class.ts +74 -13
- package/src/project_internal.ts +24 -29
- package/src/project_types.ts +69 -10
- package/src/public_types.ts +68 -0
- package/src/public_types_mastering.ts +28 -0
- package/src/public_types_mixing.ts +11 -2
- package/src/public_types_music.ts +13 -0
- package/src/public_types_spectral.ts +43 -3
- package/src/quick_analysis.ts +48 -12
- package/src/realtime_engine.ts +162 -4
- package/src/realtime_voice_changer.ts +51 -77
- package/src/sonare-analysis.js.d.ts +8 -0
- package/src/sonare.js.d.ts +305 -9
- package/src/streaming_processors.ts +22 -1
- package/src/validation.ts +6 -0
- package/src/web_midi.ts +36 -4
- package/src/worker.ts +196 -0
- package/src/worker_client.ts +352 -0
- package/src/worker_protocol.ts +59 -0
- package/src/worklet/engine-automation.ts +2 -1
- package/src/worklet/engine-capture-facade.ts +13 -4
- package/src/worklet/engine-clips.ts +12 -3
- package/src/worklet/engine-node.ts +212 -4
- package/src/worklet/engine-offline.ts +7 -2
- package/src/worklet/engine-parameter-facade.ts +26 -5
- package/src/worklet/engine-processor.ts +383 -42
- package/src/worklet/engine-register.ts +8 -0
- package/src/worklet/engine-strips.ts +17 -1
- package/src/worklet/engine-sync.ts +2 -6
- package/src/worklet/engine-tempo-facade.ts +8 -6
- package/src/worklet/engine.ts +380 -13
- package/src/worklet/guards.ts +22 -1
- package/src/worklet/messages.ts +141 -9
- package/src/worklet/protocol.ts +303 -17
- package/src/worklet/voice-changer-processor.ts +12 -15
- package/src/worklet.ts +20 -1
package/src/index.ts
CHANGED
|
@@ -19,7 +19,12 @@
|
|
|
19
19
|
*/
|
|
20
20
|
|
|
21
21
|
import { setSonareModule } from './module_state';
|
|
22
|
-
import type {
|
|
22
|
+
import type {
|
|
23
|
+
CapabilityCatalog,
|
|
24
|
+
RealtimeVoiceChangerPodConfig,
|
|
25
|
+
SonareCapabilities,
|
|
26
|
+
VoicePresetId,
|
|
27
|
+
} from './public_types';
|
|
23
28
|
import type {
|
|
24
29
|
SonareModule,
|
|
25
30
|
WasmDecomposeResult,
|
|
@@ -32,9 +37,11 @@ export { Audio } from './audio';
|
|
|
32
37
|
export type {
|
|
33
38
|
ClipPageStreamerEngine,
|
|
34
39
|
ClipPageStreamerOptions,
|
|
40
|
+
ClipPageStreamerRequest,
|
|
35
41
|
ClipPageStreamSource,
|
|
36
42
|
OpfsClipStream,
|
|
37
43
|
OpfsClipStreamOptions,
|
|
44
|
+
WorkletOpfsClipStreamHost,
|
|
38
45
|
} from './clip_page_streamer';
|
|
39
46
|
export { attachOpfsClipStream, ClipPageStreamer } from './clip_page_streamer';
|
|
40
47
|
export type {
|
|
@@ -61,6 +68,7 @@ export type {
|
|
|
61
68
|
MasteringProcessorCatalogEntry,
|
|
62
69
|
MasteringProcessRequest,
|
|
63
70
|
MasteringProcessStereoRequest,
|
|
71
|
+
MasteringRealtimeCost,
|
|
64
72
|
MasteringRepairDeclickRequest,
|
|
65
73
|
MasteringRepairDeclipRequest,
|
|
66
74
|
MasteringRepairDecrackleRequest,
|
|
@@ -151,18 +159,22 @@ export type {
|
|
|
151
159
|
} from './effects_transform';
|
|
152
160
|
export { ErrorCode, isSonareError, SonareError } from './errors';
|
|
153
161
|
export type {
|
|
162
|
+
ChirpRequest,
|
|
163
|
+
ClicksRequest,
|
|
154
164
|
CyclicTempogramRequest,
|
|
155
165
|
DbConversionRequest,
|
|
156
166
|
EmphasisRequest,
|
|
157
167
|
FixFramesRequest,
|
|
158
168
|
FixLengthRequest,
|
|
159
169
|
FrameSignalRequest,
|
|
170
|
+
OnsetBacktrackRequest,
|
|
160
171
|
PadCenterRequest,
|
|
161
172
|
PcenRequest,
|
|
162
173
|
PeakPickRequest,
|
|
163
174
|
PlpRequest,
|
|
164
175
|
SilenceRequest,
|
|
165
176
|
TempogramRequest,
|
|
177
|
+
ToneRequest,
|
|
166
178
|
TonnetzRequest,
|
|
167
179
|
VectorNormalizeRequest,
|
|
168
180
|
} from './feature_core';
|
|
@@ -181,7 +193,12 @@ export type {
|
|
|
181
193
|
VqtRequest,
|
|
182
194
|
VqtToAudioRequest,
|
|
183
195
|
} from './feature_music';
|
|
184
|
-
export type {
|
|
196
|
+
export type {
|
|
197
|
+
NoteSegmentsRequest,
|
|
198
|
+
PiptrackRequest,
|
|
199
|
+
PitchPyinRequest,
|
|
200
|
+
PitchYinRequest,
|
|
201
|
+
} from './feature_pitch';
|
|
185
202
|
export type { ResampleRequest } from './feature_resample';
|
|
186
203
|
export type {
|
|
187
204
|
DecomposeRequest,
|
|
@@ -195,6 +212,13 @@ export type {
|
|
|
195
212
|
PitchTuningRequest,
|
|
196
213
|
PolyFeaturesRequest,
|
|
197
214
|
RemixRequest,
|
|
215
|
+
SegmentAgglomerativeRequest,
|
|
216
|
+
SegmentCrossSimilarityRequest,
|
|
217
|
+
SegmentLagToRecurrenceRequest,
|
|
218
|
+
SegmentPathEnhanceRequest,
|
|
219
|
+
SegmentRecurrenceMatrixRequest,
|
|
220
|
+
SegmentRecurrenceToLagRequest,
|
|
221
|
+
SegmentSubsegmentRequest,
|
|
198
222
|
SpectralContrastRequest,
|
|
199
223
|
SpectralFrameRequest,
|
|
200
224
|
SpectralRolloffRequest,
|
|
@@ -203,12 +227,15 @@ export type {
|
|
|
203
227
|
} from './feature_spectral';
|
|
204
228
|
export type {
|
|
205
229
|
ChromaSpectrogramRequest,
|
|
230
|
+
GriffinLimRequest,
|
|
231
|
+
MelDeltaRequest,
|
|
206
232
|
MelSpectrogramRequest,
|
|
207
233
|
MelToAudioRequest,
|
|
208
234
|
MelToStftRequest,
|
|
209
235
|
MfccRequest,
|
|
210
236
|
MfccToAudioRequest,
|
|
211
237
|
MfccToMelRequest,
|
|
238
|
+
ReassignedSpectrogramRequest,
|
|
212
239
|
SpectrogramRequest,
|
|
213
240
|
TrimRequest,
|
|
214
241
|
} from './feature_spectrogram';
|
|
@@ -217,9 +244,11 @@ export {
|
|
|
217
244
|
analyzeMelody,
|
|
218
245
|
analyzeSections,
|
|
219
246
|
bassChroma,
|
|
247
|
+
chirp,
|
|
220
248
|
chroma,
|
|
221
249
|
chromaCens,
|
|
222
250
|
chromaCqt,
|
|
251
|
+
clicks,
|
|
223
252
|
cqt,
|
|
224
253
|
cqtToAudio,
|
|
225
254
|
cyclicTempogram,
|
|
@@ -236,6 +265,7 @@ export {
|
|
|
236
265
|
frameSignal,
|
|
237
266
|
framesToSamples,
|
|
238
267
|
framesToTime,
|
|
268
|
+
griffinLim,
|
|
239
269
|
hpssWithResidual,
|
|
240
270
|
hybridCqt,
|
|
241
271
|
hzToMel,
|
|
@@ -243,6 +273,7 @@ export {
|
|
|
243
273
|
hzToNote,
|
|
244
274
|
lufs,
|
|
245
275
|
lufsInterleaved,
|
|
276
|
+
melDelta,
|
|
246
277
|
melSpectrogram,
|
|
247
278
|
melToAudio,
|
|
248
279
|
melToHz,
|
|
@@ -254,13 +285,16 @@ export {
|
|
|
254
285
|
momentaryLufs,
|
|
255
286
|
nnFilter,
|
|
256
287
|
nnlsChroma,
|
|
288
|
+
noteSegments,
|
|
257
289
|
noteToHz,
|
|
290
|
+
onsetBacktrack,
|
|
258
291
|
onsetEnvelope,
|
|
259
292
|
onsetStrengthMulti,
|
|
260
293
|
padCenter,
|
|
261
294
|
pcen,
|
|
262
295
|
peakPick,
|
|
263
296
|
phaseVocoder,
|
|
297
|
+
piptrack,
|
|
264
298
|
pitchPyin,
|
|
265
299
|
pitchTuning,
|
|
266
300
|
pitchYin,
|
|
@@ -269,15 +303,24 @@ export {
|
|
|
269
303
|
powerToDb,
|
|
270
304
|
preemphasis,
|
|
271
305
|
pseudoCqt,
|
|
306
|
+
reassignedSpectrogram,
|
|
272
307
|
remix,
|
|
273
308
|
resample,
|
|
274
309
|
rmsEnergy,
|
|
275
310
|
samplesToFrames,
|
|
311
|
+
segmentAgglomerative,
|
|
312
|
+
segmentCrossSimilarity,
|
|
313
|
+
segmentLagToRecurrence,
|
|
314
|
+
segmentPathEnhance,
|
|
315
|
+
segmentRecurrenceMatrix,
|
|
316
|
+
segmentRecurrenceToLag,
|
|
317
|
+
segmentSubsegment,
|
|
276
318
|
shortTermLufs,
|
|
277
319
|
spectralBandwidth,
|
|
278
320
|
spectralCentroid,
|
|
279
321
|
spectralContrast,
|
|
280
322
|
spectralFlatness,
|
|
323
|
+
spectralFlux,
|
|
281
324
|
spectralRolloff,
|
|
282
325
|
splitSilence,
|
|
283
326
|
stft,
|
|
@@ -285,6 +328,7 @@ export {
|
|
|
285
328
|
tempogram,
|
|
286
329
|
tempogramRatio,
|
|
287
330
|
timeToFrames,
|
|
331
|
+
tone,
|
|
288
332
|
tonnetz,
|
|
289
333
|
trim,
|
|
290
334
|
trimSilence,
|
|
@@ -312,6 +356,7 @@ export type {
|
|
|
312
356
|
MeteringDynamicRangeOptions,
|
|
313
357
|
MeteringDynamicRangeRequest,
|
|
314
358
|
MeteringSamplesRequest,
|
|
359
|
+
MeteringSilenceRatioRequest,
|
|
315
360
|
MeteringSpectrumFrameRequest,
|
|
316
361
|
MeteringSpectrumRequest,
|
|
317
362
|
MeteringStereoDecimatedRequest,
|
|
@@ -336,6 +381,7 @@ export {
|
|
|
336
381
|
meteringPhaseScope,
|
|
337
382
|
meteringPhaseScopeDecimated,
|
|
338
383
|
meteringRmsDb,
|
|
384
|
+
meteringSilenceRatio,
|
|
339
385
|
meteringSpectrum,
|
|
340
386
|
meteringSpectrumFrame,
|
|
341
387
|
meteringStereoCorrelation,
|
|
@@ -359,6 +405,9 @@ export type {
|
|
|
359
405
|
BuiltinSynthBinding,
|
|
360
406
|
BuiltinSynthConfig,
|
|
361
407
|
BuiltinSynthWaveform,
|
|
408
|
+
ExternalSeparatedStem,
|
|
409
|
+
ExternalSeparatedStemImportRequest,
|
|
410
|
+
ExternalSeparatedStemImportResult,
|
|
362
411
|
MidiCcLearnOptions,
|
|
363
412
|
ProjectAssistSidecar,
|
|
364
413
|
ProjectAutomationCurve,
|
|
@@ -366,6 +415,7 @@ export type {
|
|
|
366
415
|
ProjectAutomationPoint,
|
|
367
416
|
ProjectBounceOptions,
|
|
368
417
|
ProjectChordSymbol,
|
|
418
|
+
ProjectClip,
|
|
369
419
|
ProjectClipCompSegment,
|
|
370
420
|
ProjectClipDesc,
|
|
371
421
|
ProjectClipFade,
|
|
@@ -380,6 +430,8 @@ export type {
|
|
|
380
430
|
ProjectMidiClipResult,
|
|
381
431
|
ProjectMidiEvent,
|
|
382
432
|
ProjectNotePairValidation,
|
|
433
|
+
ProjectSource,
|
|
434
|
+
ProjectTrack,
|
|
383
435
|
ProjectTrackDesc,
|
|
384
436
|
ProjectTrackKind,
|
|
385
437
|
ProjectWarpAnchor,
|
|
@@ -399,6 +451,7 @@ export type {
|
|
|
399
451
|
SynthPatch,
|
|
400
452
|
} from './project';
|
|
401
453
|
export {
|
|
454
|
+
BUILTIN_SYNTH_WAVEFORMS,
|
|
402
455
|
EXPECTED_PROJECT_ABI_VERSION,
|
|
403
456
|
MarkerKind,
|
|
404
457
|
Project,
|
|
@@ -425,6 +478,7 @@ export type {
|
|
|
425
478
|
AnalyzeTimbreOptions,
|
|
426
479
|
AutomationCurve,
|
|
427
480
|
Beat,
|
|
481
|
+
BpmHypothesis,
|
|
428
482
|
Chord,
|
|
429
483
|
ChordAnalysisResult,
|
|
430
484
|
ChordDetectionOptions,
|
|
@@ -448,9 +502,11 @@ export type {
|
|
|
448
502
|
MasteringChainConfig,
|
|
449
503
|
MasteringChainResult,
|
|
450
504
|
MasteringChainStereoResult,
|
|
505
|
+
MasteringLoudnessSummary,
|
|
451
506
|
MasteringOptions,
|
|
452
507
|
MasteringPreset,
|
|
453
508
|
MasteringProcessorParams,
|
|
509
|
+
MasteringReport,
|
|
454
510
|
MasteringResult,
|
|
455
511
|
MasteringStereoChainResult,
|
|
456
512
|
MasteringStereoResult,
|
|
@@ -464,6 +520,7 @@ export type {
|
|
|
464
520
|
MixMeterSnapshot,
|
|
465
521
|
MixOptions,
|
|
466
522
|
MixResult,
|
|
523
|
+
NoteSegment,
|
|
467
524
|
NoteStretchOptions,
|
|
468
525
|
PairAnalysis,
|
|
469
526
|
PairProcessor,
|
|
@@ -481,8 +538,10 @@ export type {
|
|
|
481
538
|
RoomGeometryOptions,
|
|
482
539
|
RoomMorphOptions,
|
|
483
540
|
Section,
|
|
541
|
+
SegmentMatrix,
|
|
484
542
|
SendTiming,
|
|
485
543
|
SoloProcessor,
|
|
544
|
+
SonareCapabilities,
|
|
486
545
|
SpectralEditMode,
|
|
487
546
|
SpectralEditOptions,
|
|
488
547
|
SpectralEditWindow,
|
|
@@ -520,8 +579,10 @@ export type {
|
|
|
520
579
|
DetectAcousticRequest,
|
|
521
580
|
DetectChordsRequest,
|
|
522
581
|
DetectKeyRequest,
|
|
582
|
+
DetectOnsetsRequest,
|
|
523
583
|
DynamicsAnalysisResult,
|
|
524
584
|
EstimateRoomRequest,
|
|
585
|
+
MusicAnalyzeRequest,
|
|
525
586
|
RhythmAnalysisResult,
|
|
526
587
|
RoomMorphRequest,
|
|
527
588
|
SamplesRequest,
|
|
@@ -557,6 +618,7 @@ export type {
|
|
|
557
618
|
EngineBounceResult,
|
|
558
619
|
EngineBus,
|
|
559
620
|
EngineCapabilities,
|
|
621
|
+
EngineCaptureSource,
|
|
560
622
|
EngineCaptureStatus,
|
|
561
623
|
EngineClip,
|
|
562
624
|
EngineFreezeOptions,
|
|
@@ -579,7 +641,12 @@ export type {
|
|
|
579
641
|
ExternalMidiEvent,
|
|
580
642
|
MidiCcBindOptions,
|
|
581
643
|
} from './realtime_engine';
|
|
582
|
-
export {
|
|
644
|
+
export {
|
|
645
|
+
ClipPageProvider,
|
|
646
|
+
EXPECTED_ENGINE_ABI_VERSION,
|
|
647
|
+
engineCapabilities,
|
|
648
|
+
RealtimeEngine,
|
|
649
|
+
} from './realtime_engine';
|
|
583
650
|
export { scaleCorrectionSemitones, scalePitchClassEnabled, scaleQuantizeMidi } from './scale';
|
|
584
651
|
export type { ProgressCallback } from './sonare.js';
|
|
585
652
|
export { StreamAnalyzer, streamAnalyzerConfigDefaults } from './stream_analyzer';
|
|
@@ -620,6 +687,13 @@ export type {
|
|
|
620
687
|
WebMidiInputInfo,
|
|
621
688
|
} from './web_midi';
|
|
622
689
|
export { bindWebMidi, isWebMidiAvailable } from './web_midi';
|
|
690
|
+
export type {
|
|
691
|
+
OfflineWorker,
|
|
692
|
+
OfflineWorkerCallOptions,
|
|
693
|
+
OfflineWorkerClientOptions,
|
|
694
|
+
OfflineWorkerProgress,
|
|
695
|
+
} from './worker_client';
|
|
696
|
+
export { OfflineWorkerClient, OfflineWorkerTask } from './worker_client';
|
|
623
697
|
|
|
624
698
|
/** Row-major 2-D matrix as a flat buffer plus its dimensions. */
|
|
625
699
|
export type Matrix2dResult = WasmMatrix2dResult;
|
|
@@ -693,6 +767,26 @@ export function version(): string {
|
|
|
693
767
|
return module.version();
|
|
694
768
|
}
|
|
695
769
|
|
|
770
|
+
/**
|
|
771
|
+
* Return the capabilities of the loaded WASM build.
|
|
772
|
+
*
|
|
773
|
+
* This is synchronous and only describes the already-initialized module.
|
|
774
|
+
*/
|
|
775
|
+
export function capabilities(): SonareCapabilities {
|
|
776
|
+
if (!module) {
|
|
777
|
+
throw new Error('Module not initialized. Call init() first.');
|
|
778
|
+
}
|
|
779
|
+
return module.capabilities();
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
/** Return the initialized module's processors, parameters, and presets. */
|
|
783
|
+
export function capabilityCatalog(): CapabilityCatalog {
|
|
784
|
+
if (!module) {
|
|
785
|
+
throw new Error('Module not initialized. Call init() first.');
|
|
786
|
+
}
|
|
787
|
+
return JSON.parse(module.capabilityCatalog()) as CapabilityCatalog;
|
|
788
|
+
}
|
|
789
|
+
|
|
696
790
|
/**
|
|
697
791
|
* Aggregate native ABI version: the per-subsystem ABI macros folded into one
|
|
698
792
|
* 32-bit value. It bumps whenever any flat C POD layout changes, so callers can
|
|
@@ -732,6 +826,9 @@ const VOICE_PRESET_ORDINALS: readonly VoicePresetId[] = [
|
|
|
732
826
|
|
|
733
827
|
function resolveVoicePresetOrdinal(preset: VoicePresetId | number): number {
|
|
734
828
|
if (typeof preset === 'number') {
|
|
829
|
+
if (!Number.isSafeInteger(preset) || preset < 0 || preset >= VOICE_PRESET_ORDINALS.length) {
|
|
830
|
+
throw new RangeError(`Unknown voice-character preset ordinal: ${String(preset)}`);
|
|
831
|
+
}
|
|
735
832
|
return preset;
|
|
736
833
|
}
|
|
737
834
|
const ordinal = VOICE_PRESET_ORDINALS.indexOf(preset);
|
|
@@ -743,9 +840,9 @@ function resolveVoicePresetOrdinal(preset: VoicePresetId | number): number {
|
|
|
743
840
|
|
|
744
841
|
/**
|
|
745
842
|
* Map a voice-character preset ordinal (or canonical id) to its canonical id
|
|
746
|
-
* string (e.g. `'bright-idol'`).
|
|
843
|
+
* string (e.g. `'bright-idol'`). Invalid ordinals throw.
|
|
747
844
|
*/
|
|
748
|
-
export function voiceCharacterPresetId(preset: VoicePresetId | number): string
|
|
845
|
+
export function voiceCharacterPresetId(preset: VoicePresetId | number): string {
|
|
749
846
|
if (!module) {
|
|
750
847
|
throw new Error('Module not initialized. Call init() first.');
|
|
751
848
|
}
|
|
@@ -755,11 +852,11 @@ export function voiceCharacterPresetId(preset: VoicePresetId | number): string |
|
|
|
755
852
|
/**
|
|
756
853
|
* Return the canonical (normalized) flat POD config for a built-in voice
|
|
757
854
|
* preset, skipping the JSON round-trip. Accepts a canonical preset id or its
|
|
758
|
-
* integer ordinal.
|
|
855
|
+
* integer ordinal. Invalid ordinals throw.
|
|
759
856
|
*/
|
|
760
857
|
export function realtimeVoiceChangerPresetConfig(
|
|
761
858
|
preset: VoicePresetId | number,
|
|
762
|
-
): RealtimeVoiceChangerPodConfig
|
|
859
|
+
): RealtimeVoiceChangerPodConfig {
|
|
763
860
|
if (!module) {
|
|
764
861
|
throw new Error('Module not initialized. Call init() first.');
|
|
765
862
|
}
|
package/src/mastering_chain.ts
CHANGED
|
@@ -22,6 +22,7 @@ export interface MasteringChainRequest {
|
|
|
22
22
|
sampleRate?: number;
|
|
23
23
|
config?: MasteringChainConfig;
|
|
24
24
|
onProgress?: ProgressCallback;
|
|
25
|
+
cancel?: () => boolean;
|
|
25
26
|
}
|
|
26
27
|
|
|
27
28
|
export interface MasteringChainStereoRequest {
|
|
@@ -30,6 +31,7 @@ export interface MasteringChainStereoRequest {
|
|
|
30
31
|
sampleRate?: number;
|
|
31
32
|
config?: MasteringChainConfig;
|
|
32
33
|
onProgress?: ProgressCallback;
|
|
34
|
+
cancel?: () => boolean;
|
|
33
35
|
}
|
|
34
36
|
|
|
35
37
|
/** Canonical request form for one-shot preset mastering. */
|
|
@@ -39,6 +41,7 @@ export interface MasterAudioRequest {
|
|
|
39
41
|
preset?: MasteringPreset;
|
|
40
42
|
overrides?: MasteringChainConfig;
|
|
41
43
|
onProgress?: ProgressCallback;
|
|
44
|
+
cancel?: () => boolean;
|
|
42
45
|
}
|
|
43
46
|
|
|
44
47
|
/** Canonical request form for one-shot stereo preset mastering. */
|
|
@@ -49,6 +52,7 @@ export interface MasterAudioStereoRequest {
|
|
|
49
52
|
preset?: MasteringPreset;
|
|
50
53
|
overrides?: MasteringChainConfig;
|
|
51
54
|
onProgress?: ProgressCallback;
|
|
55
|
+
cancel?: () => boolean;
|
|
52
56
|
}
|
|
53
57
|
|
|
54
58
|
function masterAudioRequest(
|
|
@@ -114,12 +118,13 @@ export function masteringChain(
|
|
|
114
118
|
): MasteringChainResult {
|
|
115
119
|
const request =
|
|
116
120
|
samples instanceof Float32Array ? { samples, sampleRate, config, onProgress } : samples;
|
|
117
|
-
if (request.onProgress) {
|
|
121
|
+
if (request.onProgress || request.cancel) {
|
|
118
122
|
return requireModule().masteringChainWithProgress(
|
|
119
123
|
request.samples,
|
|
120
124
|
request.sampleRate ?? 22050,
|
|
121
125
|
canonicalChainConfig(request.config ?? {}),
|
|
122
|
-
request.onProgress,
|
|
126
|
+
request.onProgress ?? (() => {}),
|
|
127
|
+
request.cancel ?? (() => false),
|
|
123
128
|
);
|
|
124
129
|
}
|
|
125
130
|
return requireModule().masteringChain(
|
|
@@ -162,13 +167,14 @@ export function masteringChainStereo(
|
|
|
162
167
|
if (request.left.length !== request.right.length) {
|
|
163
168
|
throw new Error('Stereo channel lengths must match.');
|
|
164
169
|
}
|
|
165
|
-
if (request.onProgress) {
|
|
170
|
+
if (request.onProgress || request.cancel) {
|
|
166
171
|
return requireModule().masteringChainStereoWithProgress(
|
|
167
172
|
request.left,
|
|
168
173
|
request.right,
|
|
169
174
|
request.sampleRate ?? 22050,
|
|
170
175
|
canonicalChainConfig(request.config ?? {}),
|
|
171
|
-
request.onProgress,
|
|
176
|
+
request.onProgress ?? (() => {}),
|
|
177
|
+
request.cancel ?? (() => false),
|
|
172
178
|
);
|
|
173
179
|
}
|
|
174
180
|
return requireModule().masteringChainStereo(
|
|
@@ -213,6 +219,7 @@ export function masteringChainWithProgress(
|
|
|
213
219
|
request.sampleRate ?? 22050,
|
|
214
220
|
canonicalChainConfig(request.config ?? {}),
|
|
215
221
|
request.onProgress,
|
|
222
|
+
request.cancel ?? (() => false),
|
|
216
223
|
);
|
|
217
224
|
}
|
|
218
225
|
|
|
@@ -259,6 +266,7 @@ export function masteringChainStereoWithProgress(
|
|
|
259
266
|
request.sampleRate ?? 22050,
|
|
260
267
|
canonicalChainConfig(request.config ?? {}),
|
|
261
268
|
request.onProgress,
|
|
269
|
+
request.cancel ?? (() => false),
|
|
262
270
|
);
|
|
263
271
|
}
|
|
264
272
|
|
|
@@ -298,13 +306,14 @@ export function masterAudio(
|
|
|
298
306
|
): MasteringChainResult {
|
|
299
307
|
const request = masterAudioRequest(samples, sampleRate, presetName, overrides, onProgress);
|
|
300
308
|
const flat = flattenChainConfig(request.overrides ?? {});
|
|
301
|
-
if (request.onProgress) {
|
|
309
|
+
if (request.onProgress || request.cancel) {
|
|
302
310
|
return requireModule().masterAudioWithProgress(
|
|
303
311
|
request.preset ?? 'pop',
|
|
304
312
|
request.samples,
|
|
305
313
|
request.sampleRate ?? 22050,
|
|
306
314
|
flat,
|
|
307
|
-
request.onProgress,
|
|
315
|
+
request.onProgress ?? (() => {}),
|
|
316
|
+
request.cancel ?? (() => false),
|
|
308
317
|
);
|
|
309
318
|
}
|
|
310
319
|
return requireModule().masterAudio(
|
|
@@ -355,14 +364,15 @@ export function masterAudioStereo(
|
|
|
355
364
|
if (request.left.length !== request.right.length) {
|
|
356
365
|
throw new Error('Stereo channel lengths must match.');
|
|
357
366
|
}
|
|
358
|
-
if (request.onProgress) {
|
|
367
|
+
if (request.onProgress || request.cancel) {
|
|
359
368
|
return requireModule().masterAudioStereoWithProgress(
|
|
360
369
|
request.preset ?? 'pop',
|
|
361
370
|
request.left,
|
|
362
371
|
request.right,
|
|
363
372
|
request.sampleRate ?? 22050,
|
|
364
373
|
flat,
|
|
365
|
-
request.onProgress,
|
|
374
|
+
request.onProgress ?? (() => {}),
|
|
375
|
+
request.cancel ?? (() => false),
|
|
366
376
|
);
|
|
367
377
|
}
|
|
368
378
|
return requireModule().masterAudioStereo(
|
|
@@ -405,6 +415,7 @@ export function masterAudioWithProgress(
|
|
|
405
415
|
request.sampleRate ?? 22050,
|
|
406
416
|
flattenChainConfig(request.overrides ?? {}),
|
|
407
417
|
request.onProgress,
|
|
418
|
+
request.cancel ?? (() => false),
|
|
408
419
|
);
|
|
409
420
|
}
|
|
410
421
|
|
|
@@ -451,5 +462,6 @@ export function masterAudioStereoWithProgress(
|
|
|
451
462
|
request.sampleRate ?? 22050,
|
|
452
463
|
flattenChainConfig(request.overrides ?? {}),
|
|
453
464
|
request.onProgress,
|
|
465
|
+
request.cancel ?? (() => false),
|
|
454
466
|
);
|
|
455
467
|
}
|
package/src/mastering_core.ts
CHANGED
|
@@ -152,6 +152,8 @@ export interface MasteringInsertParamInfo {
|
|
|
152
152
|
id: number;
|
|
153
153
|
/** Whether the param can be changed live from the audio thread. */
|
|
154
154
|
rtSafe: boolean;
|
|
155
|
+
/** Physical unit when the parameter is not unitless. */
|
|
156
|
+
unit?: string;
|
|
155
157
|
}
|
|
156
158
|
|
|
157
159
|
/**
|
|
@@ -184,6 +186,9 @@ export type MasteringChannelPolicy =
|
|
|
184
186
|
| 'perChannel'
|
|
185
187
|
| 'passthrough';
|
|
186
188
|
|
|
189
|
+
/** Coarse algorithmic work estimate for a realtime insert; not a benchmark. */
|
|
190
|
+
export type MasteringRealtimeCost = 'low' | 'moderate' | 'high';
|
|
191
|
+
|
|
187
192
|
/** One processor's realtime/offline/pair classification in the catalog. */
|
|
188
193
|
export interface MasteringProcessorCatalogEntry {
|
|
189
194
|
/** Processor id (the name used for scene inserts / named processors). */
|
|
@@ -208,6 +213,8 @@ export interface MasteringProcessorCatalogEntry {
|
|
|
208
213
|
* offline, dry-only, and no-tail processors.
|
|
209
214
|
*/
|
|
210
215
|
tailSamples: number;
|
|
216
|
+
/** Coarse realtime work estimate, or null when the processor is not an insert. */
|
|
217
|
+
realtimeCost: MasteringRealtimeCost | null;
|
|
211
218
|
/**
|
|
212
219
|
* How the mixer wraps the processor on a >2-channel (surround) bus insert:
|
|
213
220
|
* "multichannel" (one full-buffer call) or "stereoPairOnly" (front L/R pair,
|
|
@@ -107,7 +107,13 @@ export function masteringDynamicsCompressor(
|
|
|
107
107
|
typeof request.detector === 'string'
|
|
108
108
|
? COMPRESSOR_DETECTOR_MAP[request.detector]
|
|
109
109
|
: request.detector;
|
|
110
|
-
|
|
110
|
+
// Preserve inherited option values as well as own properties. The embind
|
|
111
|
+
// boundary's hasProperty() intentionally follows the prototype chain, so a
|
|
112
|
+
// spread copy here would otherwise erase values before C++ can read them.
|
|
113
|
+
const opts: Record<string, unknown> = Object.assign(
|
|
114
|
+
Object.create(Object.getPrototypeOf(request)) as Record<string, unknown>,
|
|
115
|
+
request,
|
|
116
|
+
);
|
|
111
117
|
if (detector !== undefined) {
|
|
112
118
|
opts.detector = detector;
|
|
113
119
|
}
|
package/src/metering.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ErrorCode, SonareError } from './errors';
|
|
1
2
|
import { getSonareModule } from './module_state';
|
|
2
3
|
import type { ValidateOptions } from './validation';
|
|
3
4
|
import { assertSamples } from './validation';
|
|
@@ -17,7 +18,11 @@ function assertOversampleFactor(fnName: string, factor: number): void {
|
|
|
17
18
|
normalized > 16 ||
|
|
18
19
|
(normalized & (normalized - 1)) !== 0
|
|
19
20
|
) {
|
|
20
|
-
throw new
|
|
21
|
+
throw new SonareError(
|
|
22
|
+
ErrorCode.InvalidParameter,
|
|
23
|
+
'InvalidParameter',
|
|
24
|
+
`${fnName}: oversampleFactor must be 0 or a power of two from 1 to 16`,
|
|
25
|
+
);
|
|
21
26
|
}
|
|
22
27
|
}
|
|
23
28
|
|
|
@@ -128,6 +133,43 @@ export function meteringRmsDb(
|
|
|
128
133
|
return requireModule().meteringRmsDb(request.samples, request.sampleRate ?? 22050);
|
|
129
134
|
}
|
|
130
135
|
|
|
136
|
+
export interface MeteringSilenceRatioRequest extends MeteringSamplesRequest {
|
|
137
|
+
thresholdDb?: number;
|
|
138
|
+
frameLength?: number;
|
|
139
|
+
hopLength?: number;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
export function meteringSilenceRatio(request: MeteringSilenceRatioRequest): number;
|
|
143
|
+
export function meteringSilenceRatio(
|
|
144
|
+
samples: Float32Array,
|
|
145
|
+
sampleRate?: number,
|
|
146
|
+
thresholdDb?: number,
|
|
147
|
+
frameLength?: number,
|
|
148
|
+
hopLength?: number,
|
|
149
|
+
options?: ValidateOptions,
|
|
150
|
+
): number;
|
|
151
|
+
export function meteringSilenceRatio(
|
|
152
|
+
samples: Float32Array | MeteringSilenceRatioRequest,
|
|
153
|
+
sampleRate = 22050,
|
|
154
|
+
thresholdDb = -45,
|
|
155
|
+
frameLength = 1024,
|
|
156
|
+
hopLength = 256,
|
|
157
|
+
options: ValidateOptions = {},
|
|
158
|
+
): number {
|
|
159
|
+
const request =
|
|
160
|
+
samples instanceof Float32Array
|
|
161
|
+
? { samples, sampleRate, thresholdDb, frameLength, hopLength, ...options }
|
|
162
|
+
: samples;
|
|
163
|
+
assertSamples('meteringSilenceRatio', request.samples, request.validate !== false);
|
|
164
|
+
return requireModule().meteringSilenceRatio(
|
|
165
|
+
request.samples,
|
|
166
|
+
request.sampleRate ?? 22050,
|
|
167
|
+
request.thresholdDb ?? -45,
|
|
168
|
+
request.frameLength ?? 1024,
|
|
169
|
+
request.hopLength ?? 256,
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
|
|
131
173
|
export function meteringCrestFactorDb(request: MeteringSamplesRequest): number;
|
|
132
174
|
export function meteringCrestFactorDb(
|
|
133
175
|
samples: Float32Array,
|
|
@@ -206,16 +248,20 @@ export function meteringDetectClipping(
|
|
|
206
248
|
): ClippingReport {
|
|
207
249
|
const request = samples instanceof Float32Array ? { samples, sampleRate, ...options } : samples;
|
|
208
250
|
assertSamples('meteringDetectClipping', request.samples, request.validate !== false);
|
|
251
|
+
const minRegionSamples = request.minRegionSamples ?? 1;
|
|
252
|
+
if (!Number.isInteger(minRegionSamples) || minRegionSamples < 0) {
|
|
253
|
+
throw new RangeError('meteringDetectClipping: minRegionSamples must be a non-negative integer');
|
|
254
|
+
}
|
|
209
255
|
return requireModule().meteringDetectClipping(
|
|
210
256
|
request.samples,
|
|
211
257
|
request.sampleRate ?? 22050,
|
|
212
258
|
request.threshold ?? 0.999,
|
|
213
|
-
|
|
259
|
+
minRegionSamples,
|
|
214
260
|
);
|
|
215
261
|
}
|
|
216
262
|
|
|
217
263
|
/**
|
|
218
|
-
* Sliding-window dynamic range. Pass 0 for window/hop to use the library
|
|
264
|
+
* Sliding-window dynamic range for mono audio. Pass 0 for window/hop to use the library
|
|
219
265
|
* default (window=3 s, hop=1 s). The percentiles use a NEGATIVE sentinel for
|
|
220
266
|
* "use the library default" (low=0.10, high=0.95) because 0 is a literal 0th
|
|
221
267
|
* percentile; omitted percentiles therefore default to -1.
|
|
@@ -354,7 +400,7 @@ export interface WaveformPeaksReport {
|
|
|
354
400
|
samplesPerBucket: number;
|
|
355
401
|
}
|
|
356
402
|
|
|
357
|
-
/**
|
|
403
|
+
/** Uncentered correlation (cosine similarity) in [-1, 1] between equal-length channels. */
|
|
358
404
|
export function meteringStereoCorrelation(request: MeteringStereoRequest): number;
|
|
359
405
|
export function meteringStereoCorrelation(
|
|
360
406
|
left: Float32Array,
|
|
@@ -561,7 +607,7 @@ export function meteringPhaseScopeDecimated(
|
|
|
561
607
|
}
|
|
562
608
|
|
|
563
609
|
/**
|
|
564
|
-
* Welch-averaged magnitude / power / dB spectrum over the WHOLE signal (split
|
|
610
|
+
* Welch-averaged magnitude / power / dB spectrum over the WHOLE mono signal (split
|
|
565
611
|
* into Hann-windowed, 50%-overlapping `nFft`-length frames whose power spectra
|
|
566
612
|
* are averaged). For a true single-frame snapshot, use
|
|
567
613
|
* {@link meteringSpectrumFrame}.
|
package/src/mixer.ts
CHANGED
|
@@ -74,7 +74,10 @@ export class Mixer {
|
|
|
74
74
|
return new Mixer(module.createMixerFromSceneJson(json, sampleRate, blockSize), blockSize);
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
-
/**
|
|
77
|
+
/**
|
|
78
|
+
* Rebuild and compile the routing graph without resetting its absolute
|
|
79
|
+
* automation sample position or queued strip automation.
|
|
80
|
+
*/
|
|
78
81
|
compile(): void {
|
|
79
82
|
this.mixer.compile();
|
|
80
83
|
}
|
|
@@ -261,6 +264,11 @@ export class Mixer {
|
|
|
261
264
|
this.mixer.setVcaGroupGainDb(id, gainDb);
|
|
262
265
|
}
|
|
263
266
|
|
|
267
|
+
/** Replace an existing VCA group's strip membership. */
|
|
268
|
+
setVcaGroupMembers(id: string, members: string[]): void {
|
|
269
|
+
this.mixer.setVcaGroupMembers(id, members);
|
|
270
|
+
}
|
|
271
|
+
|
|
264
272
|
/** Remove a VCA group by id. */
|
|
265
273
|
removeVcaGroup(id: string): void {
|
|
266
274
|
this.mixer.removeVcaGroup(id);
|
|
@@ -427,6 +435,11 @@ export class Mixer {
|
|
|
427
435
|
return this.mixer.meterTap(stripIndex, meterTapCode(tap));
|
|
428
436
|
}
|
|
429
437
|
|
|
438
|
+
/** Read the post-insert meter for a compiled bus, including master. */
|
|
439
|
+
busMeter(busId: string): MixMeterSnapshot {
|
|
440
|
+
return this.mixer.busMeter(busId);
|
|
441
|
+
}
|
|
442
|
+
|
|
430
443
|
/**
|
|
431
444
|
* Schedule sample-accurate fader automation on a strip.
|
|
432
445
|
*
|