@libraz/libsonare 1.6.0 → 1.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/README.md +2 -2
  2. package/dist/analysis.d.ts +139 -11
  3. package/dist/analysis.js +162 -42
  4. package/dist/analysis.js.map +1 -1
  5. package/dist/index.d.ts +211 -39
  6. package/dist/index.js +501 -142
  7. package/dist/index.js.map +1 -1
  8. package/dist/schemas/realtime-voice-changer-preset.schema.json +2 -2
  9. package/dist/sonare-analysis.js +1 -1
  10. package/dist/sonare-analysis.wasm +0 -0
  11. package/dist/sonare.js +1 -1
  12. package/dist/sonare.wasm +0 -0
  13. package/dist/worker.js +56 -29
  14. package/dist/worker.js.map +1 -1
  15. package/dist/worklet.d.ts +67 -18
  16. package/dist/worklet.js +193 -42
  17. package/dist/worklet.js.map +1 -1
  18. package/package.json +3 -3
  19. package/src/_chain_config.ts +6 -1
  20. package/src/analysis_helpers.ts +34 -29
  21. package/src/audio.ts +7 -2
  22. package/src/codes.ts +47 -11
  23. package/src/effects_mastering.ts +5 -0
  24. package/src/effects_transform.ts +202 -22
  25. package/src/feature_music.ts +8 -1
  26. package/src/feature_spectral.ts +64 -2
  27. package/src/feature_spectrogram.ts +44 -3
  28. package/src/index.ts +28 -3
  29. package/src/mastering_core.ts +70 -0
  30. package/src/metering.ts +18 -0
  31. package/src/mixer.ts +3 -3
  32. package/src/project.ts +6 -0
  33. package/src/project_class.ts +143 -16
  34. package/src/project_internal.ts +14 -5
  35. package/src/project_types.ts +50 -9
  36. package/src/public_types_mastering.ts +9 -0
  37. package/src/public_types_mixing.ts +16 -0
  38. package/src/public_types_realtime.ts +23 -5
  39. package/src/public_types_spectral.ts +16 -2
  40. package/src/quick_analysis.ts +21 -3
  41. package/src/realtime_engine.ts +14 -3
  42. package/src/sonare.js.d.ts +87 -0
  43. package/src/stream_analyzer.ts +6 -1
  44. package/src/web_midi.ts +10 -7
  45. package/src/worklet/engine-node.ts +54 -19
  46. package/src/worklet/engine-parameter-facade.ts +30 -1
  47. package/src/worklet/engine-processor.ts +52 -20
  48. package/src/worklet/engine-register.ts +1 -1
  49. package/src/worklet/engine-strips.ts +2 -2
  50. package/src/worklet/engine.ts +10 -0
  51. package/src/worklet/guards.ts +99 -7
  52. package/src/worklet/messages.ts +41 -1
  53. package/src/worklet/protocol.ts +4 -0
package/dist/index.js CHANGED
@@ -227,13 +227,66 @@ function assertInterleavedSamples(fnName, samples, channels, validate) {
227
227
  function requireModule() {
228
228
  return getSonareModule();
229
229
  }
230
- function hpss(samples, sampleRate = 22050, kernelHarmonic = 31, kernelPercussive = 31) {
231
- const request = samples instanceof Float32Array ? { samples, sampleRate, kernelHarmonic, kernelPercussive } : samples;
232
- return requireModule().hpss(
230
+ function toVoicedFloat32(voiced) {
231
+ const out = new Float32Array(voiced.length);
232
+ for (let index = 0; index < voiced.length; index += 1) {
233
+ out[index] = voiced[index] ? 1 : 0;
234
+ }
235
+ return out;
236
+ }
237
+ function resolveEffectFftOptions(fnName, nFft, hopLength) {
238
+ const resolvedNFft = nFft === void 0 ? 2048 : nFft;
239
+ const resolvedHopLength = hopLength === void 0 ? 512 : hopLength;
240
+ if (typeof resolvedNFft !== "number" || !Number.isInteger(resolvedNFft)) {
241
+ throw new TypeError(`${fnName}: nFft must be an integer`);
242
+ }
243
+ if (resolvedNFft < 2 || resolvedNFft > 2 ** 30) {
244
+ throw new RangeError(`${fnName}: nFft must be an even power of two >= 2`);
245
+ }
246
+ if ((resolvedNFft & resolvedNFft - 1) !== 0) {
247
+ throw new RangeError(`${fnName}: nFft must be an even power of two >= 2`);
248
+ }
249
+ if (typeof resolvedHopLength !== "number" || !Number.isInteger(resolvedHopLength)) {
250
+ throw new TypeError(`${fnName}: hopLength must be an integer`);
251
+ }
252
+ if (resolvedHopLength <= 0 || resolvedHopLength > 2 ** 31 - 1) {
253
+ throw new RangeError(`${fnName}: hopLength must be a positive integer`);
254
+ }
255
+ return { nFft: resolvedNFft, hopLength: resolvedHopLength };
256
+ }
257
+ function resolveNormalizeMode(value) {
258
+ if (value === void 0) {
259
+ return "peak";
260
+ }
261
+ if (typeof value !== "string") {
262
+ throw new TypeError("normalize: mode must be the string 'peak' or 'rms'");
263
+ }
264
+ if (value !== "peak" && value !== "rms") {
265
+ throw new RangeError("normalize: mode must be the string 'peak' or 'rms'");
266
+ }
267
+ return value;
268
+ }
269
+ function resolveHardMask(value, fnName) {
270
+ if (value === void 0) {
271
+ return false;
272
+ }
273
+ if (typeof value !== "boolean") {
274
+ throw new TypeError(`${fnName}: hardMask must be a boolean`);
275
+ }
276
+ return value;
277
+ }
278
+ function hpss(samples, sampleRate = 22050, kernelHarmonic = 31, kernelPercussive = 31, nFft, hopLength, hardMask) {
279
+ const request = samples instanceof Float32Array ? { samples, sampleRate, kernelHarmonic, kernelPercussive, nFft, hopLength, hardMask } : samples;
280
+ const fftOptions = resolveEffectFftOptions("hpss", request.nFft, request.hopLength);
281
+ const resolvedHardMask = resolveHardMask(request.hardMask, "hpss");
282
+ return requireModule().hpssEx(
233
283
  request.samples,
234
284
  request.sampleRate ?? 22050,
235
285
  request.kernelHarmonic ?? 31,
236
- request.kernelPercussive ?? 31
286
+ request.kernelPercussive ?? 31,
287
+ fftOptions.nFft,
288
+ fftOptions.hopLength,
289
+ resolvedHardMask
237
290
  );
238
291
  }
239
292
  function harmonic(samples, sampleRate = 22050, options = {}) {
@@ -246,18 +299,58 @@ function percussive(samples, sampleRate = 22050, options = {}) {
246
299
  assertSamples("percussive", request.samples, request.validate !== false);
247
300
  return requireModule().percussive(request.samples, request.sampleRate ?? 22050);
248
301
  }
249
- function timeStretch(samples, sampleRate, rate, options = {}) {
250
- const request = samples instanceof Float32Array ? { samples, sampleRate, rate, ...options } : samples;
302
+ function timeStretch(samples, sampleRate, rate, nFftOrOptions, hopLength, options = {}) {
303
+ if (nFftOrOptions !== void 0 && nFftOrOptions !== null && typeof nFftOrOptions !== "number" && typeof nFftOrOptions !== "object") {
304
+ throw new TypeError("timeStretch: nFft must be an integer or options object");
305
+ }
306
+ if (nFftOrOptions === null) {
307
+ throw new TypeError("timeStretch: nFft must be an integer or options object");
308
+ }
309
+ const positionalOptions = typeof nFftOrOptions === "object" && nFftOrOptions !== null ? nFftOrOptions : options;
310
+ const positionalNFft = typeof nFftOrOptions === "number" ? nFftOrOptions : void 0;
311
+ const request = samples instanceof Float32Array ? {
312
+ samples,
313
+ sampleRate,
314
+ rate,
315
+ nFft: positionalNFft,
316
+ hopLength,
317
+ ...positionalOptions
318
+ } : samples;
251
319
  assertSamples("timeStretch", request.samples, request.validate !== false);
252
- return requireModule().timeStretch(request.samples, request.sampleRate ?? 22050, request.rate);
320
+ const fftOptions = resolveEffectFftOptions("timeStretch", request.nFft, request.hopLength);
321
+ return requireModule().timeStretchEx(
322
+ request.samples,
323
+ request.sampleRate ?? 22050,
324
+ request.rate,
325
+ fftOptions.nFft,
326
+ fftOptions.hopLength
327
+ );
253
328
  }
254
- function pitchShift(samples, sampleRate, semitones, options = {}) {
255
- const request = samples instanceof Float32Array ? { samples, sampleRate, semitones, ...options } : samples;
329
+ function pitchShift(samples, sampleRate, semitones, nFftOrOptions, hopLength, options = {}) {
330
+ if (nFftOrOptions !== void 0 && nFftOrOptions !== null && typeof nFftOrOptions !== "number" && typeof nFftOrOptions !== "object") {
331
+ throw new TypeError("pitchShift: nFft must be an integer or options object");
332
+ }
333
+ if (nFftOrOptions === null) {
334
+ throw new TypeError("pitchShift: nFft must be an integer or options object");
335
+ }
336
+ const positionalOptions = typeof nFftOrOptions === "object" && nFftOrOptions !== null ? nFftOrOptions : options;
337
+ const positionalNFft = typeof nFftOrOptions === "number" ? nFftOrOptions : void 0;
338
+ const request = samples instanceof Float32Array ? {
339
+ samples,
340
+ sampleRate,
341
+ semitones,
342
+ nFft: positionalNFft,
343
+ hopLength,
344
+ ...positionalOptions
345
+ } : samples;
256
346
  assertSamples("pitchShift", request.samples, request.validate !== false);
257
- return requireModule().pitchShift(
347
+ const fftOptions = resolveEffectFftOptions("pitchShift", request.nFft, request.hopLength);
348
+ return requireModule().pitchShiftEx(
258
349
  request.samples,
259
350
  request.sampleRate ?? 22050,
260
- request.semitones
351
+ request.semitones,
352
+ fftOptions.nFft,
353
+ fftOptions.hopLength
261
354
  );
262
355
  }
263
356
  function pitchCorrectToMidi(samples, sampleRate = 22050, currentMidi = 69, targetMidi = 69, options = {}) {
@@ -288,7 +381,7 @@ function pitchCorrectToMidiTimevarying(samples, f0Hz, targetMidi, sampleRate = 2
288
381
  if (request.voicedProb && request.voicedProb.length !== request.f0Hz.length) {
289
382
  throw new RangeError("pitchCorrectToMidiTimevarying: voicedProb length must match f0Hz length");
290
383
  }
291
- const voicedF32 = request.voiced ? Float32Array.from(request.voiced) : void 0;
384
+ const voicedF32 = request.voiced ? toVoicedFloat32(request.voiced) : void 0;
292
385
  return requireModule().pitchCorrectToMidiTimevarying(
293
386
  request.samples,
294
387
  request.sampleRate ?? 22050,
@@ -310,7 +403,7 @@ function pitchCorrectTimevarying(samples, f0Hz, sampleRate = 22050, hopLength =
310
403
  }
311
404
  const nativeOptions = {
312
405
  ...request,
313
- voiced: request.voiced ? Float32Array.from(request.voiced) : void 0
406
+ voiced: request.voiced ? toVoicedFloat32(request.voiced) : void 0
314
407
  };
315
408
  return requireModule().pitchCorrectTimevarying(
316
409
  request.samples,
@@ -342,13 +435,23 @@ function noteMove(samples, sampleRate = 22050, options = {}) {
342
435
  request.targetOnsetSample ?? 0
343
436
  );
344
437
  }
345
- function normalize(samples, sampleRate, targetDb = 0, options = {}) {
346
- const request = samples instanceof Float32Array ? { samples, sampleRate, targetDb, ...options } : samples;
438
+ function normalize(samples, sampleRate, targetDb = 0, modeOrOptions = "peak", options = {}) {
439
+ if (modeOrOptions !== void 0 && modeOrOptions !== null && typeof modeOrOptions !== "string" && typeof modeOrOptions !== "object") {
440
+ throw new TypeError("normalize: mode must be the string 'peak' or 'rms'");
441
+ }
442
+ if (modeOrOptions === null) {
443
+ throw new TypeError("normalize: mode must be the string 'peak' or 'rms'");
444
+ }
445
+ const positionalOptions = typeof modeOrOptions === "object" && modeOrOptions !== null ? modeOrOptions : options;
446
+ const positionalMode = typeof modeOrOptions === "string" ? modeOrOptions : void 0;
447
+ const request = samples instanceof Float32Array ? { samples, sampleRate, targetDb, mode: positionalMode, ...positionalOptions } : samples;
347
448
  assertSamples("normalize", request.samples, request.validate !== false);
348
- return requireModule().normalize(
449
+ const mode = resolveNormalizeMode(request.mode);
450
+ return requireModule().normalizeEx(
349
451
  request.samples,
350
452
  request.sampleRate ?? 22050,
351
- request.targetDb ?? 0
453
+ request.targetDb ?? 0,
454
+ mode
352
455
  );
353
456
  }
354
457
  function spectralEdit(samples, sampleRate, ops = [], options = {}) {
@@ -760,6 +863,30 @@ function masteringStreamingPreview(samples, sampleRate = 22050, platforms = [])
760
863
  request.platforms ?? []
761
864
  );
762
865
  }
866
+ function masteringAssistantSuggestStereo(request) {
867
+ return requireModule4().masteringAssistantSuggestStereo(
868
+ request.left,
869
+ request.right,
870
+ request.sampleRate ?? 22050,
871
+ request.params ?? {}
872
+ );
873
+ }
874
+ function masteringAudioProfileStereo(request) {
875
+ return requireModule4().masteringAudioProfileStereo(
876
+ request.left,
877
+ request.right,
878
+ request.sampleRate ?? 22050,
879
+ request.params ?? {}
880
+ );
881
+ }
882
+ function masteringStreamingPreviewStereo(request) {
883
+ return requireModule4().masteringStreamingPreviewStereo(
884
+ request.left,
885
+ request.right,
886
+ request.sampleRate ?? 22050,
887
+ request.platforms ?? []
888
+ );
889
+ }
763
890
 
764
891
  // src/mastering_dynamics.ts
765
892
  function requireModule5() {
@@ -1124,12 +1251,18 @@ function nnlsChroma(samples, sampleRate = 22050, options = {}) {
1124
1251
  return nnlsChroma(samples.samples, samples.sampleRate, samples);
1125
1252
  }
1126
1253
  validateMusicSamples("nnlsChroma", samples, sampleRate, options);
1127
- return requireModule9().nnlsChroma(
1254
+ const hopLength = options.hopLength === void 0 ? 512 : options.hopLength;
1255
+ assertPositiveInteger("nnlsChroma", hopLength, "hopLength");
1256
+ if (hopLength > 2 ** 31 - 1) {
1257
+ throw new RangeError("nnlsChroma: hopLength must fit in a signed 32-bit integer");
1258
+ }
1259
+ return requireModule9().nnlsChromaEx(
1128
1260
  samples,
1129
1261
  sampleRate,
1130
1262
  options.enableStftBlend ?? true,
1131
1263
  options.stftBlendWeight ?? 0.55,
1132
- options.stftBlendNFft ?? 4096
1264
+ options.stftBlendNFft ?? 4096,
1265
+ hopLength
1133
1266
  );
1134
1267
  }
1135
1268
  function cqt(samples, sampleRate = 22050, hopLength = 512, fmin = 32.70319566257483, nBins = 84, binsPerOctave = 12, options = {}) {
@@ -1559,6 +1692,35 @@ function resample(samples, srcSr, targetSr) {
1559
1692
  function requireModule12() {
1560
1693
  return getSonareModule();
1561
1694
  }
1695
+ function resolveEffectFftOptions2(fnName, nFft, hopLength) {
1696
+ const resolvedNFft = nFft === void 0 ? 2048 : nFft;
1697
+ const resolvedHopLength = hopLength === void 0 ? 512 : hopLength;
1698
+ if (typeof resolvedNFft !== "number" || !Number.isInteger(resolvedNFft)) {
1699
+ throw new TypeError(`${fnName}: nFft must be an integer`);
1700
+ }
1701
+ if (resolvedNFft < 2 || resolvedNFft > 2 ** 30) {
1702
+ throw new RangeError(`${fnName}: nFft must be an even power of two >= 2`);
1703
+ }
1704
+ if ((resolvedNFft & resolvedNFft - 1) !== 0) {
1705
+ throw new RangeError(`${fnName}: nFft must be an even power of two >= 2`);
1706
+ }
1707
+ if (typeof resolvedHopLength !== "number" || !Number.isInteger(resolvedHopLength)) {
1708
+ throw new TypeError(`${fnName}: hopLength must be an integer`);
1709
+ }
1710
+ if (resolvedHopLength <= 0 || resolvedHopLength > 2 ** 31 - 1) {
1711
+ throw new RangeError(`${fnName}: hopLength must be a positive integer`);
1712
+ }
1713
+ return { nFft: resolvedNFft, hopLength: resolvedHopLength };
1714
+ }
1715
+ function resolveHardMask2(fnName, value) {
1716
+ if (value === void 0) {
1717
+ return false;
1718
+ }
1719
+ if (typeof value !== "boolean") {
1720
+ throw new TypeError(`${fnName}: hardMask must be a boolean`);
1721
+ }
1722
+ return value;
1723
+ }
1562
1724
  function validateSegmentMatrix(fnName, data, rows, cols, dataName) {
1563
1725
  assertPositiveInteger(fnName, rows, "rows");
1564
1726
  assertPositiveInteger(fnName, cols, "cols");
@@ -1690,12 +1852,30 @@ function phaseVocoder(samples, sampleRate = 22050, rate = 1, nFft = 2048, hopLen
1690
1852
  }
1691
1853
  return requireModule12().phaseVocoder(samples, sampleRate, rate, nFft, hopLength);
1692
1854
  }
1693
- function hpssWithResidual(samples, sampleRate = 22050, kernelHarmonic = 31, kernelPercussive = 31) {
1855
+ function hpssWithResidual(samples, sampleRate = 22050, kernelHarmonic = 31, kernelPercussive = 31, nFft, hopLength, hardMask) {
1694
1856
  if (!(samples instanceof Float32Array)) {
1695
1857
  const r = samples;
1696
- return hpssWithResidual(r.samples, r.sampleRate, r.kernelHarmonic, r.kernelPercussive);
1858
+ return hpssWithResidual(
1859
+ r.samples,
1860
+ r.sampleRate,
1861
+ r.kernelHarmonic,
1862
+ r.kernelPercussive,
1863
+ r.nFft,
1864
+ r.hopLength,
1865
+ r.hardMask
1866
+ );
1697
1867
  }
1698
- return requireModule12().hpssWithResidual(samples, sampleRate, kernelHarmonic, kernelPercussive);
1868
+ const fftOptions = resolveEffectFftOptions2("hpssWithResidual", nFft, hopLength);
1869
+ const resolvedHardMask = resolveHardMask2("hpssWithResidual", hardMask);
1870
+ return requireModule12().hpssWithResidualEx(
1871
+ samples,
1872
+ sampleRate,
1873
+ kernelHarmonic,
1874
+ kernelPercussive,
1875
+ fftOptions.nFft,
1876
+ fftOptions.hopLength,
1877
+ resolvedHardMask
1878
+ );
1699
1879
  }
1700
1880
  function lufsInterleaved(samples, channels = 0, sampleRate = 22050, options = {}) {
1701
1881
  if (!(samples instanceof Float32Array)) {
@@ -1908,14 +2088,35 @@ function validateMatrix(fnName, data, rows, frames, dataName, rowName, options =
1908
2088
  throw new RangeError(`${fnName}: ${dataName} length must equal ${rowName} * nFrames`);
1909
2089
  }
1910
2090
  }
1911
- function trim(samples, sampleRate = 22050, thresholdDb = -60, options = {}) {
2091
+ function trim(samples, sampleRate = 22050, thresholdDb = -60, frameLengthOrOptions, hopLength, options = {}) {
1912
2092
  if (!(samples instanceof Float32Array)) {
1913
2093
  const r = samples;
1914
- return trim(r.samples, r.sampleRate, r.thresholdDb, r);
2094
+ return trim(r.samples, r.sampleRate, r.thresholdDb, r.frameLength, r.hopLength, r);
2095
+ }
2096
+ if (frameLengthOrOptions === null) {
2097
+ throw new TypeError("trim: frameLength must be an integer or options object");
1915
2098
  }
1916
- validateSpectrogramSamples("trim", samples, sampleRate, options);
2099
+ if (frameLengthOrOptions !== void 0 && typeof frameLengthOrOptions !== "number" && typeof frameLengthOrOptions !== "object") {
2100
+ throw new TypeError("trim: frameLength must be an integer or options object");
2101
+ }
2102
+ const positionalOptions = typeof frameLengthOrOptions === "object" && frameLengthOrOptions !== null ? frameLengthOrOptions : options;
2103
+ const positionalFrameLength = typeof frameLengthOrOptions === "number" ? frameLengthOrOptions : void 0;
2104
+ const resolvedFrameLength = positionalFrameLength ?? 2048;
2105
+ const resolvedHopLength = hopLength === void 0 ? 512 : hopLength;
2106
+ validateSpectrogramSamples("trim", samples, sampleRate, positionalOptions);
1917
2107
  assertFiniteScalar("trim", thresholdDb, "thresholdDb");
1918
- return requireModule13().trim(samples, sampleRate, thresholdDb);
2108
+ assertPositiveInteger("trim", resolvedFrameLength, "frameLength");
2109
+ assertPositiveInteger("trim", resolvedHopLength, "hopLength");
2110
+ if (resolvedFrameLength > 2 ** 31 - 1 || resolvedHopLength > 2 ** 31 - 1) {
2111
+ throw new RangeError("trim: frameLength and hopLength must fit in a signed 32-bit integer");
2112
+ }
2113
+ return requireModule13().trimEx(
2114
+ samples,
2115
+ sampleRate,
2116
+ thresholdDb,
2117
+ resolvedFrameLength,
2118
+ resolvedHopLength
2119
+ );
1919
2120
  }
1920
2121
  function stft(samples, sampleRate = 22050, nFft = 2048, hopLength = 512, options = {}) {
1921
2122
  if (!(samples instanceof Float32Array)) {
@@ -2261,6 +2462,88 @@ function chroma(samples, sampleRate = 22050, nFft = 2048, hopLength = 512, optio
2261
2462
  return requireModule13().chroma(samples, sampleRate, nFft, hopLength);
2262
2463
  }
2263
2464
 
2465
+ // src/codes.ts
2466
+ function resolveOrdinalInRange(value, min, max, enumName) {
2467
+ if (typeof value !== "number" || !Number.isSafeInteger(value) || value < min || value > max) {
2468
+ throw new RangeError(`Invalid ${enumName}: ${String(value)}`);
2469
+ }
2470
+ return value;
2471
+ }
2472
+ function resolveEnumOrdinal(value, values, enumName) {
2473
+ if (typeof value === "number") {
2474
+ const ordinals = Object.values(values);
2475
+ const ordinal = resolveOrdinalInRange(
2476
+ value,
2477
+ Math.min(...ordinals),
2478
+ Math.max(...ordinals),
2479
+ enumName
2480
+ );
2481
+ if (!ordinals.includes(ordinal)) {
2482
+ throw new RangeError(`Invalid ${enumName}: ${String(value)}`);
2483
+ }
2484
+ return ordinal;
2485
+ }
2486
+ if (typeof value === "string") {
2487
+ const ordinal = values[value];
2488
+ if (ordinal !== void 0) {
2489
+ return ordinal;
2490
+ }
2491
+ }
2492
+ throw new RangeError(`Invalid ${enumName}: ${String(value)}`);
2493
+ }
2494
+ var AUTOMATION_CURVE_VALUES = {
2495
+ linear: 0,
2496
+ exponential: 1,
2497
+ hold: 2,
2498
+ "s-curve": 3
2499
+ };
2500
+ var PAN_LAW_VALUES = {
2501
+ const3db: 0,
2502
+ "const-3db": 0,
2503
+ "-3db": 0,
2504
+ "const4.5db": 1,
2505
+ "const-4.5db": 1,
2506
+ "-4.5db": 1,
2507
+ const6db: 2,
2508
+ "const-6db": 2,
2509
+ "-6db": 2,
2510
+ linear0db: 3,
2511
+ "linear-0db": 3,
2512
+ linear: 3,
2513
+ "0db": 3
2514
+ };
2515
+ var PAN_MODE_VALUES = {
2516
+ balance: 0,
2517
+ pan: 1,
2518
+ stereopan: 1,
2519
+ "stereo-pan": 1,
2520
+ dualpan: 2,
2521
+ "dual-pan": 2
2522
+ };
2523
+ var METER_TAP_VALUES = { preFader: 0, postFader: 1 };
2524
+ var SEND_TIMING_VALUES = { postFader: 0, preFader: 1 };
2525
+ var TRACK_MONITOR_MODE_VALUES = { off: 0, pfl: 1, afl: 2 };
2526
+ function automationCurveCode(curve) {
2527
+ return resolveEnumOrdinal(curve, AUTOMATION_CURVE_VALUES, "automation curve");
2528
+ }
2529
+ function panLawCode(panLaw) {
2530
+ const normalized = typeof panLaw === "string" ? panLaw.toLowerCase().replace(/_/g, "-") : panLaw;
2531
+ return resolveEnumOrdinal(normalized, PAN_LAW_VALUES, "pan law");
2532
+ }
2533
+ function panModeCode(panMode) {
2534
+ const normalized = typeof panMode === "string" ? panMode.replace(/_/g, "-").toLowerCase() : panMode;
2535
+ return resolveEnumOrdinal(normalized, PAN_MODE_VALUES, "pan mode");
2536
+ }
2537
+ function meterTapCode(tap) {
2538
+ return resolveEnumOrdinal(tap, METER_TAP_VALUES, "meter tap");
2539
+ }
2540
+ function sendTimingCode(timing) {
2541
+ return resolveEnumOrdinal(timing, SEND_TIMING_VALUES, "send timing");
2542
+ }
2543
+ function trackMonitorModeCode(mode) {
2544
+ return resolveEnumOrdinal(mode, TRACK_MONITOR_MODE_VALUES, "track monitor mode");
2545
+ }
2546
+
2264
2547
  // src/public_types_music.ts
2265
2548
  var PitchClass = {
2266
2549
  C: 0,
@@ -2354,6 +2637,30 @@ function convertKeyCandidate(wasm) {
2354
2637
  correlation: wasm.correlation
2355
2638
  };
2356
2639
  }
2640
+ var KEY_MODE_VALUES = {
2641
+ major: Mode.Major,
2642
+ minor: Mode.Minor,
2643
+ dorian: Mode.Dorian,
2644
+ phrygian: Mode.Phrygian,
2645
+ lydian: Mode.Lydian,
2646
+ mixolydian: Mode.Mixolydian,
2647
+ locrian: Mode.Locrian
2648
+ };
2649
+ var KEY_PROFILE_VALUES = {
2650
+ ks: KeyProfile.KrumhanslSchmuckler,
2651
+ krumhansl: KeyProfile.KrumhanslSchmuckler,
2652
+ temperley: KeyProfile.Temperley,
2653
+ shaath: KeyProfile.Shaath,
2654
+ keyfinder: KeyProfile.Shaath,
2655
+ "faraldo-edmt": KeyProfile.FaraldoEDMT,
2656
+ edmt: KeyProfile.FaraldoEDMT,
2657
+ "faraldo-edma": KeyProfile.FaraldoEDMA,
2658
+ edma: KeyProfile.FaraldoEDMA,
2659
+ "faraldo-edmm": KeyProfile.FaraldoEDMM,
2660
+ edmm: KeyProfile.FaraldoEDMM,
2661
+ "bellman-budge": KeyProfile.BellmanBudge,
2662
+ bellman: KeyProfile.BellmanBudge
2663
+ };
2357
2664
  function keyModeValues(modes) {
2358
2665
  if (!modes) {
2359
2666
  return [];
@@ -2372,40 +2679,13 @@ function keyModeValues(modes) {
2372
2679
  Mode.Locrian
2373
2680
  ];
2374
2681
  }
2375
- const names = {
2376
- major: Mode.Major,
2377
- minor: Mode.Minor,
2378
- dorian: Mode.Dorian,
2379
- phrygian: Mode.Phrygian,
2380
- lydian: Mode.Lydian,
2381
- mixolydian: Mode.Mixolydian,
2382
- locrian: Mode.Locrian
2383
- };
2384
- return modes.map((mode) => typeof mode === "number" ? mode : names[mode]);
2682
+ return modes.map((mode) => resolveEnumOrdinal(mode, KEY_MODE_VALUES, "key mode"));
2385
2683
  }
2386
2684
  function keyProfileValue(profile) {
2387
2685
  if (profile === void 0) {
2388
2686
  return -1;
2389
2687
  }
2390
- if (typeof profile === "number") {
2391
- return profile;
2392
- }
2393
- const names = {
2394
- ks: KeyProfile.KrumhanslSchmuckler,
2395
- krumhansl: KeyProfile.KrumhanslSchmuckler,
2396
- temperley: KeyProfile.Temperley,
2397
- shaath: KeyProfile.Shaath,
2398
- keyfinder: KeyProfile.Shaath,
2399
- "faraldo-edmt": KeyProfile.FaraldoEDMT,
2400
- edmt: KeyProfile.FaraldoEDMT,
2401
- "faraldo-edma": KeyProfile.FaraldoEDMA,
2402
- edma: KeyProfile.FaraldoEDMA,
2403
- "faraldo-edmm": KeyProfile.FaraldoEDMM,
2404
- edmm: KeyProfile.FaraldoEDMM,
2405
- "bellman-budge": KeyProfile.BellmanBudge,
2406
- bellman: KeyProfile.BellmanBudge
2407
- };
2408
- return names[profile];
2688
+ return resolveEnumOrdinal(profile, KEY_PROFILE_VALUES, "key profile");
2409
2689
  }
2410
2690
  function convertChordAnalysisResult(wasm) {
2411
2691
  return {
@@ -2611,18 +2891,27 @@ function analyze(samples, sampleRate = 22050, options = {}) {
2611
2891
  const result = requireModule14().analyze(request.samples, request.sampleRate ?? 22050, request);
2612
2892
  return convertAnalysisResult(result);
2613
2893
  }
2614
- function analyzeImpulseResponse(samples, sampleRate = 48e3, nOctaveBands = 6) {
2615
- const request = samples instanceof Float32Array ? { samples, sampleRate, nOctaveBands } : samples;
2894
+ function analyzeImpulseResponse(samples, sampleRate = 48e3, nOctaveBands = 6, minDecayDb) {
2895
+ const request = samples instanceof Float32Array ? { samples, sampleRate, nOctaveBands, minDecayDb } : samples;
2896
+ if (request.minDecayDb === null) {
2897
+ throw new TypeError("analyzeImpulseResponse: minDecayDb must be a finite number");
2898
+ }
2899
+ const resolvedMinDecayDb = request.minDecayDb === void 0 ? 30 : request.minDecayDb;
2900
+ assertFiniteScalar("analyzeImpulseResponse", resolvedMinDecayDb, "minDecayDb");
2901
+ if (resolvedMinDecayDb <= 0) {
2902
+ throw new RangeError("analyzeImpulseResponse: minDecayDb must be greater than zero");
2903
+ }
2616
2904
  validateAnalysisInput(
2617
2905
  "analyzeImpulseResponse",
2618
2906
  request.samples,
2619
2907
  request.sampleRate ?? 48e3,
2620
2908
  request
2621
2909
  );
2622
- const result = requireModule14().analyzeImpulseResponse(
2910
+ const result = requireModule14().analyzeImpulseResponseEx(
2623
2911
  request.samples,
2624
2912
  request.sampleRate ?? 48e3,
2625
- request.nOctaveBands ?? 6
2913
+ request.nOctaveBands ?? 6,
2914
+ resolvedMinDecayDb
2626
2915
  );
2627
2916
  return result;
2628
2917
  }
@@ -2831,9 +3120,14 @@ var Audio = class _Audio {
2831
3120
  }
2832
3121
  }
2833
3122
  }
2834
- /** The raw audio samples. */
3123
+ /**
3124
+ * A copy of the raw audio samples. Mirrors Node's `getData()` contract: the
3125
+ * returned array is independent of the Audio's internal buffer, so mutating
3126
+ * it (or transferring it to a Worker) does not affect subsequent facade
3127
+ * calls, which all read the internal snapshot directly.
3128
+ */
2835
3129
  get data() {
2836
- return this._samples;
3130
+ return this._samples.slice();
2837
3131
  }
2838
3132
  /** Number of samples. */
2839
3133
  get length() {
@@ -3477,6 +3771,15 @@ function meteringCrestFactorDb(samples, sampleRate = 22050, options = {}) {
3477
3771
  assertSamples("meteringCrestFactorDb", request.samples, request.validate !== false);
3478
3772
  return requireModule15().meteringCrestFactorDb(request.samples, request.sampleRate ?? 22050);
3479
3773
  }
3774
+ function meteringCrestFactorDbStereo(request) {
3775
+ assertSamples("meteringCrestFactorDbStereo", request.left, request.validate !== false);
3776
+ assertSamples("meteringCrestFactorDbStereo", request.right, request.validate !== false);
3777
+ return requireModule15().meteringCrestFactorDbStereo(
3778
+ request.left,
3779
+ request.right,
3780
+ request.sampleRate ?? 22050
3781
+ );
3782
+ }
3480
3783
  function meteringDcOffset(samples, sampleRate = 22050, options = {}) {
3481
3784
  const request = samples instanceof Float32Array ? { samples, sampleRate, ...options } : samples;
3482
3785
  assertSamples("meteringDcOffset", request.samples, request.validate !== false);
@@ -3625,61 +3928,6 @@ function waveformPeakPyramid(samples, channels, options = {}) {
3625
3928
  return requireModule15().waveformPeakPyramid(request.samples, request.channels, levels);
3626
3929
  }
3627
3930
 
3628
- // src/codes.ts
3629
- function resolveEnumOrdinal(value, values, enumName) {
3630
- if (typeof value === "number") {
3631
- if (!Number.isSafeInteger(value) || !Object.values(values).includes(value)) {
3632
- throw new RangeError(`Invalid ${enumName}: ${String(value)}`);
3633
- }
3634
- return value;
3635
- }
3636
- if (typeof value === "string") {
3637
- const ordinal = values[value];
3638
- if (ordinal !== void 0) {
3639
- return ordinal;
3640
- }
3641
- }
3642
- throw new RangeError(`Invalid ${enumName}: ${String(value)}`);
3643
- }
3644
- var AUTOMATION_CURVE_VALUES = {
3645
- linear: 0,
3646
- exponential: 1,
3647
- hold: 2,
3648
- "s-curve": 3
3649
- };
3650
- var PAN_LAW_VALUES = {
3651
- const3dB: 0,
3652
- "const4.5dB": 1,
3653
- const6dB: 2,
3654
- linear0dB: 3
3655
- };
3656
- var PAN_MODE_VALUES = {
3657
- balance: 0,
3658
- pan: 0,
3659
- stereopan: 1,
3660
- "stereo-pan": 1,
3661
- dualpan: 2,
3662
- "dual-pan": 2
3663
- };
3664
- var METER_TAP_VALUES = { preFader: 0, postFader: 1 };
3665
- var SEND_TIMING_VALUES = { postFader: 0, preFader: 1 };
3666
- function automationCurveCode(curve) {
3667
- return resolveEnumOrdinal(curve, AUTOMATION_CURVE_VALUES, "automation curve");
3668
- }
3669
- function panLawCode(panLaw) {
3670
- return resolveEnumOrdinal(panLaw, PAN_LAW_VALUES, "pan law");
3671
- }
3672
- function panModeCode(panMode) {
3673
- const normalized = typeof panMode === "string" ? panMode.replace(/_/g, "-").toLowerCase() : panMode;
3674
- return resolveEnumOrdinal(normalized, PAN_MODE_VALUES, "pan mode");
3675
- }
3676
- function meterTapCode(tap) {
3677
- return resolveEnumOrdinal(tap, METER_TAP_VALUES, "meter tap");
3678
- }
3679
- function sendTimingCode(timing) {
3680
- return resolveEnumOrdinal(timing, SEND_TIMING_VALUES, "send timing");
3681
- }
3682
-
3683
3931
  // src/project_internal.ts
3684
3932
  function projectModule() {
3685
3933
  const candidate = getSonareModule();
@@ -3748,6 +3996,13 @@ function assertProjectMidiEvents(fnName, events) {
3748
3996
  function projectTrackKindValue(kind) {
3749
3997
  return resolveEnumOrdinal(kind ?? "audio", { audio: 0, midi: 1, aux: 2 }, "project track kind");
3750
3998
  }
3999
+ function projectAutomationTargetKindValue(kind) {
4000
+ return resolveEnumOrdinal(
4001
+ kind,
4002
+ { opaque: 0, "track-fader-db": 1, "track-pan": 2 },
4003
+ "project automation target kind"
4004
+ );
4005
+ }
3751
4006
  function projectWarpModeValue(mode) {
3752
4007
  return resolveEnumOrdinal(
3753
4008
  mode ?? "off",
@@ -3760,10 +4015,40 @@ function projectLoopModeValue(mode) {
3760
4015
  }
3761
4016
 
3762
4017
  // src/project_class.ts
4018
+ function validateAssistSidecarUint32(value, field) {
4019
+ if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 0 || value > 4294967295) {
4020
+ throw new RangeError(`Project.setAssistSidecar: ${field} must be a uint32`);
4021
+ }
4022
+ return value;
4023
+ }
4024
+ function validateAssistSidecarPpq(value, field) {
4025
+ if (typeof value !== "number" || !Number.isFinite(value) || value < 0) {
4026
+ throw new RangeError(
4027
+ `Project.setAssistSidecar: ${field} must be a finite, non-negative number`
4028
+ );
4029
+ }
4030
+ return value;
4031
+ }
4032
+ function validateAssistSidecarPayload(value) {
4033
+ if (!(value instanceof Uint8Array)) {
4034
+ throw new TypeError("Project.setAssistSidecar: payload must be a Uint8Array");
4035
+ }
4036
+ return value;
4037
+ }
4038
+ function validateAssistSidecarModuleId(value) {
4039
+ if (typeof value !== "string" || value.length === 0) {
4040
+ throw new TypeError("Project.setAssistSidecar: moduleId must be a non-empty string");
4041
+ }
4042
+ return value;
4043
+ }
3763
4044
  var Project = class _Project {
3764
4045
  constructor() {
3765
4046
  this.native = new (projectModule()).Project();
3766
4047
  }
4048
+ /** Create a new empty project. */
4049
+ static create() {
4050
+ return new _Project();
4051
+ }
3767
4052
  /** Pack a MIDI 1.0 note-on event accepted by {@link setMidiEvents}. */
3768
4053
  static midiNoteOn(ppq, group, channel, note, velocity) {
3769
4054
  return projectMidi1Event("Project.midiNoteOn", ppq, group, 9, channel, note, velocity);
@@ -4027,6 +4312,18 @@ var Project = class _Project {
4027
4312
  }
4028
4313
  this.native.setMaxUndoDepth(depth);
4029
4314
  }
4315
+ /** Set the combined undo/redo history byte cap. Zero disables retention. */
4316
+ setMaxHistoryBytes(bytes) {
4317
+ if (typeof bytes !== "number") {
4318
+ throw new TypeError("Project.setMaxHistoryBytes: bytes must be a number");
4319
+ }
4320
+ if (!Number.isFinite(bytes) || !Number.isInteger(bytes) || bytes < 0 || bytes > 4294967295) {
4321
+ throw new RangeError(
4322
+ "Project.setMaxHistoryBytes: bytes must be a finite integer in the uint32 range"
4323
+ );
4324
+ }
4325
+ this.native.setMaxHistoryBytes(bytes);
4326
+ }
4030
4327
  /** Replace a MIDI clip's entire event list. */
4031
4328
  setMidiEvents(clipId, events) {
4032
4329
  assertProjectMidiEvents("Project.setMidiEvents", events);
@@ -4157,8 +4454,11 @@ var Project = class _Project {
4157
4454
  * Karplus-Strong / modal / additive / percussion / extended-waveguide-piano
4158
4455
  * engines plus the realism layer). Pass a {@link SynthPatch}, a preset-name
4159
4456
  * string (`'saw-lead'` / `'va:saw-lead'`; see {@link synthPresetNames}), or
4160
- * an array of either; each object entry may carry a `destinationId` binding
4161
- * convenience (default 0), which is not part of the NativeSynth patch itself.
4457
+ * an array of either; each object entry may carry `destinationId` (default
4458
+ * 0) and `useGmPrograms` (default `false`) binding conveniences, neither of
4459
+ * which is part of the NativeSynth patch itself. When enabled, MIDI program
4460
+ * changes select the corresponding General MIDI voice while the patch remains
4461
+ * the fallback.
4162
4462
  * Because the parameter defaults to `{}`, omission and explicit `undefined`
4163
4463
  * both create one default binding. Use an explicitly empty array `[]` (or
4164
4464
  * runtime `null`) for zero bindings. Unknown preset names throw.
@@ -4232,6 +4532,10 @@ var Project = class _Project {
4232
4532
  setSourceAudio(sourceId, audio, channels, sampleRate) {
4233
4533
  this.native.setSourceAudio(sourceId, audio, channels, sampleRate);
4234
4534
  }
4535
+ /** Replace an audio source's metadata strings as one undoable edit. */
4536
+ setAudioSourceMetadata(sourceId, contentHash, externalStemRole) {
4537
+ this.native.setAudioSourceMetadata(sourceId, contentHash, externalStemRole);
4538
+ }
4235
4539
  /** Replace a clip's take list and active take id (undoable). */
4236
4540
  setClipTakes(clipId, takes, activeTakeId = 0) {
4237
4541
  this.native.setClipTakes(clipId, takes, activeTakeId);
@@ -4275,17 +4579,29 @@ var Project = class _Project {
4275
4579
  }
4276
4580
  /** Append an automation lane; returns its stable target parameter id (undoable). */
4277
4581
  addAutomationLane(trackId, desc) {
4278
- return this.native.addAutomationLane(trackId, {
4279
- targetParamId: desc.targetParamId,
4280
- points: desc.points
4281
- });
4582
+ if (desc.targetParamId === 0) {
4583
+ throw new RangeError("project automation lane targetParamId must be non-zero");
4584
+ }
4585
+ const nativeDesc = { ...desc };
4586
+ if (Object.keys(desc).includes("targetKind")) {
4587
+ nativeDesc.targetKind = projectAutomationTargetKindValue(
4588
+ desc.targetKind
4589
+ );
4590
+ }
4591
+ return this.native.addAutomationLane(trackId, nativeDesc);
4282
4592
  }
4283
4593
  /** Replace the lane identified by its stable target parameter id (undoable). */
4284
4594
  editAutomationLane(trackId, targetParamId, desc) {
4285
- this.native.editAutomationLane(trackId, targetParamId, {
4286
- targetParamId: desc.targetParamId,
4287
- points: desc.points
4288
- });
4595
+ if (desc.targetParamId === 0) {
4596
+ throw new RangeError("project automation lane targetParamId must be non-zero");
4597
+ }
4598
+ const nativeDesc = { ...desc };
4599
+ if (Object.keys(desc).includes("targetKind")) {
4600
+ nativeDesc.targetKind = projectAutomationTargetKindValue(
4601
+ desc.targetKind
4602
+ );
4603
+ }
4604
+ this.native.editAutomationLane(trackId, targetParamId, nativeDesc);
4289
4605
  }
4290
4606
  /** Remove the lane identified by its stable target parameter id (undoable). */
4291
4607
  removeAutomationLane(trackId, targetParamId) {
@@ -4299,15 +4615,33 @@ var Project = class _Project {
4299
4615
  annotateChords(chords) {
4300
4616
  this.native.annotateChords(chords);
4301
4617
  }
4302
- /** Add or update an opaque assist sidecar by module id + target scope (undoable). */
4303
- setAssistSidecar(moduleId, schemaVersion, targetTrackId, regionStartPpq, regionEndPpq, payload) {
4618
+ setAssistSidecar(sidecarOrModuleId, schemaVersion, targetTrackId, regionStartPpq, regionEndPpq, payload) {
4619
+ if (typeof sidecarOrModuleId === "string") {
4620
+ if (schemaVersion === void 0 || targetTrackId === void 0 || regionStartPpq === void 0 || regionEndPpq === void 0 || payload === void 0) {
4621
+ throw new TypeError("Project.setAssistSidecar: positional form requires six arguments");
4622
+ }
4623
+ this.native.setAssistSidecar(
4624
+ validateAssistSidecarModuleId(sidecarOrModuleId),
4625
+ validateAssistSidecarUint32(schemaVersion, "schemaVersion"),
4626
+ validateAssistSidecarUint32(targetTrackId, "targetTrackId"),
4627
+ validateAssistSidecarPpq(regionStartPpq, "regionStartPpq"),
4628
+ validateAssistSidecarPpq(regionEndPpq, "regionEndPpq"),
4629
+ validateAssistSidecarPayload(payload)
4630
+ );
4631
+ return;
4632
+ }
4633
+ if (sidecarOrModuleId === null || typeof sidecarOrModuleId !== "object" || Array.isArray(sidecarOrModuleId)) {
4634
+ throw new TypeError("Project.setAssistSidecar: expected a sidecar descriptor object");
4635
+ }
4636
+ const sidecar = sidecarOrModuleId;
4637
+ const moduleId = validateAssistSidecarModuleId(sidecar.moduleId);
4304
4638
  this.native.setAssistSidecar(
4305
4639
  moduleId,
4306
- schemaVersion,
4307
- targetTrackId,
4308
- regionStartPpq,
4309
- regionEndPpq,
4310
- payload
4640
+ validateAssistSidecarUint32(sidecar.schemaVersion ?? 0, "schemaVersion"),
4641
+ validateAssistSidecarUint32(sidecar.targetTrackId ?? 0, "targetTrackId"),
4642
+ validateAssistSidecarPpq(sidecar.regionStartPpq ?? 0, "regionStartPpq"),
4643
+ validateAssistSidecarPpq(sidecar.regionEndPpq ?? 0, "regionEndPpq"),
4644
+ validateAssistSidecarPayload(sidecar.payload ?? new Uint8Array())
4311
4645
  );
4312
4646
  }
4313
4647
  /** Number of assist sidecars currently stored on the project. */
@@ -4318,6 +4652,11 @@ var Project = class _Project {
4318
4652
  getAssistSidecar(index) {
4319
4653
  return this.native.getAssistSidecar(index);
4320
4654
  }
4655
+ /** Read every stored assist sidecar in the same order as the index getter. */
4656
+ assistSidecars() {
4657
+ const count = this.assistSidecarCount();
4658
+ return Array.from({ length: count }, (_, index) => this.getAssistSidecar(index));
4659
+ }
4321
4660
  /** Set the project's clip-overlap policy (SonareProjectOverlapPolicy ordinal). */
4322
4661
  setOverlapPolicy(policy) {
4323
4662
  this.native.setOverlapPolicy(policy);
@@ -4500,6 +4839,14 @@ var SYNTH_MOD_DESTINATIONS = [
4500
4839
  "amp-gain",
4501
4840
  "pan-units"
4502
4841
  ];
4842
+ var AutomationTargetKind = {
4843
+ opaque: 0,
4844
+ trackFaderDb: 1,
4845
+ trackPan: 2
4846
+ };
4847
+ var PROJECT_AUTOMATION_TARGET_OPAQUE = AutomationTargetKind.opaque;
4848
+ var PROJECT_AUTOMATION_TARGET_TRACK_FADER_DB = AutomationTargetKind.trackFaderDb;
4849
+ var PROJECT_AUTOMATION_TARGET_TRACK_PAN = AutomationTargetKind.trackPan;
4503
4850
 
4504
4851
  // src/realtime_engine.ts
4505
4852
  var EXPECTED_ENGINE_ABI_VERSION = 3;
@@ -4563,6 +4910,10 @@ var RealtimeEngine = class {
4563
4910
  setSoloMute(laneIndex, solo, mute, renderFrame = -1) {
4564
4911
  this.native.setSoloMute(laneIndex, solo, mute, renderFrame);
4565
4912
  }
4913
+ /** Queue a per-track PFL/AFL monitor tap mode change. */
4914
+ setTrackMonitorMode(laneIndex, mode, renderFrame = -1) {
4915
+ this.native.setTrackMonitorMode(laneIndex, trackMonitorModeCode(mode), renderFrame);
4916
+ }
4566
4917
  setMidiClips(clips) {
4567
4918
  this.native.setMidiClips(clips);
4568
4919
  }
@@ -5276,6 +5627,7 @@ var StreamAnalyzer = class {
5276
5627
  if (config.outputFormat !== void 0 && (typeof config.outputFormat !== "number" || !Number.isFinite(config.outputFormat) || !Number.isInteger(config.outputFormat) || config.outputFormat !== 0)) {
5277
5628
  throw new TypeError("outputFormat must be the integer 0 (Float32)");
5278
5629
  }
5630
+ const window = config.window === void 0 ? void 0 : resolveOrdinalInRange(config.window, 0, 3, "stream analyzer window");
5279
5631
  const module2 = getSonareModule();
5280
5632
  const defaults = streamAnalyzerConfigDefaults();
5281
5633
  this.analyzer = new module2.StreamAnalyzer(
@@ -5297,7 +5649,7 @@ var StreamAnalyzer = class {
5297
5649
  config.maxProgressionEntries ?? defaults.maxProgressionEntries,
5298
5650
  config.keyUpdateIntervalSec ?? defaults.keyUpdateIntervalSec,
5299
5651
  config.bpmUpdateIntervalSec ?? defaults.bpmUpdateIntervalSec,
5300
- config.window ?? defaults.window,
5652
+ window ?? defaults.window,
5301
5653
  config.outputFormat ?? defaults.outputFormat
5302
5654
  );
5303
5655
  }
@@ -5725,7 +6077,7 @@ var Mixer = class _Mixer {
5725
6077
  setPolarityInvert(stripIndex, invertLeft, invertRight) {
5726
6078
  this.mixer.setPolarityInvert(stripIndex, invertLeft, invertRight);
5727
6079
  }
5728
- /** Set the strip's pan law. */
6080
+ /** Set the strip's pan law (a {@link PanLawName} alias or raw C ABI ordinal). */
5729
6081
  setPanLaw(stripIndex, panLaw) {
5730
6082
  this.mixer.setPanLaw(stripIndex, panLawCode(panLaw));
5731
6083
  }
@@ -6430,7 +6782,6 @@ async function bindWebMidi(engine, options = {}) {
6430
6782
  for (const [, input] of iterInputs(access)) {
6431
6783
  bindInput(input);
6432
6784
  }
6433
- notify();
6434
6785
  };
6435
6786
  const stateListener = (event) => {
6436
6787
  if (closed) {
@@ -6449,6 +6800,7 @@ async function bindWebMidi(engine, options = {}) {
6449
6800
  notify();
6450
6801
  };
6451
6802
  refreshInputs();
6803
+ notify();
6452
6804
  if (access.addEventListener) {
6453
6805
  access.addEventListener("statechange", stateListener);
6454
6806
  } else {
@@ -6550,12 +6902,8 @@ function dispatchUmpMessage(engine, words, portTimeSamples) {
6550
6902
  if (status === 8) {
6551
6903
  engine.pushMidiInputNoteOff(group, channel, data1, word1 >>> 25 & 127, portTimeSamples);
6552
6904
  } else if (status === 9) {
6553
- const velocity = word1 >>> 25 & 127;
6554
- if (velocity === 0) {
6555
- engine.pushMidiInputNoteOff(group, channel, data1, 0, portTimeSamples);
6556
- } else {
6557
- engine.pushMidiInputNoteOn(group, channel, data1, velocity, portTimeSamples);
6558
- }
6905
+ const velocity = Math.max(1, word1 >>> 25 & 127);
6906
+ engine.pushMidiInputNoteOn(group, channel, data1, velocity, portTimeSamples);
6559
6907
  } else if (status === 11) {
6560
6908
  engine.pushMidiInputCc(group, channel, data1, word1 >>> 25 & 127, portTimeSamples);
6561
6909
  }
@@ -6874,6 +7222,9 @@ function voiceCharacterPresetId(preset) {
6874
7222
  if (!module) {
6875
7223
  throw new Error("Module not initialized. Call init() first.");
6876
7224
  }
7225
+ if (typeof preset === "number" && (!Number.isSafeInteger(preset) || preset < 0 || preset >= VOICE_PRESET_ORDINALS.length)) {
7226
+ return null;
7227
+ }
6877
7228
  return module.voiceCharacterPresetId(resolveVoicePresetOrdinal(preset));
6878
7229
  }
6879
7230
  function realtimeVoiceChangerPresetConfig(preset) {
@@ -6884,6 +7235,7 @@ function realtimeVoiceChangerPresetConfig(preset) {
6884
7235
  }
6885
7236
  export {
6886
7237
  Audio,
7238
+ AutomationTargetKind,
6887
7239
  BUILTIN_SYNTH_WAVEFORMS,
6888
7240
  ChordQuality,
6889
7241
  ClipPageProvider,
@@ -6897,6 +7249,9 @@ export {
6897
7249
  Mode,
6898
7250
  OfflineWorkerClient,
6899
7251
  OfflineWorkerTask,
7252
+ PROJECT_AUTOMATION_TARGET_OPAQUE,
7253
+ PROJECT_AUTOMATION_TARGET_TRACK_FADER_DB,
7254
+ PROJECT_AUTOMATION_TARGET_TRACK_PAN,
6900
7255
  PitchClass as Pitch,
6901
7256
  PitchClass,
6902
7257
  Project,
@@ -6988,7 +7343,9 @@ export {
6988
7343
  masterAudioWithProgress,
6989
7344
  mastering,
6990
7345
  masteringAssistantSuggest,
7346
+ masteringAssistantSuggestStereo,
6991
7347
  masteringAudioProfile,
7348
+ masteringAudioProfileStereo,
6992
7349
  masteringChain,
6993
7350
  masteringChainStereo,
6994
7351
  masteringChainStereoWithProgress,
@@ -7018,12 +7375,14 @@ export {
7018
7375
  masteringStereoAnalysisNames,
7019
7376
  masteringStereoAnalyze,
7020
7377
  masteringStreamingPreview,
7378
+ masteringStreamingPreviewStereo,
7021
7379
  melDelta,
7022
7380
  melSpectrogram,
7023
7381
  melToAudio,
7024
7382
  melToHz,
7025
7383
  melToStft,
7026
7384
  meteringCrestFactorDb,
7385
+ meteringCrestFactorDbStereo,
7027
7386
  meteringDcOffset,
7028
7387
  meteringDetectClipping,
7029
7388
  meteringDynamicRange,