@libraz/libsonare 1.5.1 → 1.5.3

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 (48) hide show
  1. package/README.md +18 -3
  2. package/dist/index.d.ts +1165 -178
  3. package/dist/index.js +4830 -3871
  4. package/dist/index.js.map +1 -1
  5. package/dist/sonare.js +1 -1
  6. package/dist/sonare.wasm +0 -0
  7. package/dist/worklet.d.ts +29 -1
  8. package/dist/worklet.js +1068 -974
  9. package/dist/worklet.js.map +1 -1
  10. package/package.json +2 -1
  11. package/src/_chain_config.ts +46 -0
  12. package/src/audio.ts +24 -4
  13. package/src/effects_mastering.ts +25 -1
  14. package/src/effects_transform.ts +283 -43
  15. package/src/effects_voice_change.ts +46 -53
  16. package/src/feature_core.ts +316 -12
  17. package/src/feature_music.ts +462 -0
  18. package/src/feature_pitch.ts +61 -0
  19. package/src/feature_resample.ts +17 -2
  20. package/src/feature_spectral.ts +349 -2
  21. package/src/feature_spectrogram.ts +336 -0
  22. package/src/features.ts +2 -0
  23. package/src/index.ts +133 -1
  24. package/src/mastering_chain.ts +305 -50
  25. package/src/mastering_core.ts +242 -16
  26. package/src/mastering_dynamics.ts +66 -10
  27. package/src/mastering_repair.ts +119 -7
  28. package/src/metering.ts +366 -81
  29. package/src/mixer.ts +10 -3
  30. package/src/mixing_oneshot.ts +25 -5
  31. package/src/module_state.ts +1 -1
  32. package/src/project_class.ts +17 -6
  33. package/src/project_internal.ts +10 -2
  34. package/src/project_types.ts +25 -2
  35. package/src/public_types_mastering.ts +114 -4
  36. package/src/public_types_music.ts +1 -0
  37. package/src/public_types_spectral.ts +7 -0
  38. package/src/quick_analysis.ts +325 -117
  39. package/src/realtime_engine.ts +8 -0
  40. package/src/sonare.js.d.ts +56 -0
  41. package/src/stream_analyzer.ts +25 -2
  42. package/src/stream_types.ts +16 -1
  43. package/src/validation.ts +17 -2
  44. package/src/worklet/engine-clips.ts +67 -2
  45. package/src/worklet/engine-processor.ts +33 -5
  46. package/src/worklet/engine.ts +7 -3
  47. package/src/worklet/guards.ts +3 -0
  48. package/src/worklet/messages.ts +27 -0
@@ -25,6 +25,80 @@ type GuardedOptions = ValidateOptions;
25
25
  type AnalyzeSectionsGuardedOptions = AnalyzeSectionsOptions & ValidateOptions;
26
26
  type MelodyGuardedOptions = MelodyOptions & ValidateOptions;
27
27
 
28
+ /** Canonical request form shared by the Constant-Q transform variants. */
29
+ export interface CqtRequest extends GuardedOptions {
30
+ samples: Float32Array;
31
+ sampleRate?: number;
32
+ hopLength?: number;
33
+ fmin?: number;
34
+ nBins?: number;
35
+ binsPerOctave?: number;
36
+ }
37
+
38
+ /** Canonical request form for {@link vqt}. */
39
+ export interface VqtRequest extends CqtRequest {
40
+ gamma?: number;
41
+ }
42
+
43
+ export interface OnsetEnvelopeRequest extends GuardedOptions {
44
+ samples: Float32Array;
45
+ sampleRate?: number;
46
+ nFft?: number;
47
+ hopLength?: number;
48
+ nMels?: number;
49
+ }
50
+
51
+ export interface OnsetStrengthMultiRequest extends OnsetEnvelopeRequest {
52
+ nBands?: number;
53
+ }
54
+
55
+ export interface FourierTempogramRequest extends GuardedOptions {
56
+ onsetEnvelope: Float32Array;
57
+ sampleRate?: number;
58
+ hopLength?: number;
59
+ winLength?: number;
60
+ }
61
+
62
+ export interface TempogramRatioRequest extends GuardedOptions {
63
+ tempogramData: Float32Array;
64
+ winLength?: number;
65
+ sampleRate?: number;
66
+ hopLength?: number;
67
+ factors?: Float32Array | number[];
68
+ }
69
+
70
+ export interface CqtToAudioRequest extends GuardedOptions {
71
+ magnitude: Float32Array;
72
+ nBins: number;
73
+ nFrames: number;
74
+ sampleRate?: number;
75
+ hopLength?: number;
76
+ fmin?: number;
77
+ binsPerOctave?: number;
78
+ nIter?: number;
79
+ }
80
+
81
+ export interface VqtToAudioRequest extends CqtToAudioRequest {
82
+ gamma?: number;
83
+ }
84
+
85
+ export interface AnalyzeSectionsRequest extends AnalyzeSectionsGuardedOptions {
86
+ samples: Float32Array;
87
+ sampleRate?: number;
88
+ }
89
+ export interface AnalyzeMelodyRequest extends MelodyGuardedOptions {
90
+ samples: Float32Array;
91
+ sampleRate?: number;
92
+ }
93
+ export interface LufsRequest extends ValidateOptions {
94
+ samples: Float32Array;
95
+ sampleRate?: number;
96
+ }
97
+ export interface NnlsChromaRequest extends GuardedOptions {
98
+ samples: Float32Array;
99
+ sampleRate?: number;
100
+ }
101
+
28
102
  function validateMusicSamples(
29
103
  fnName: string,
30
104
  samples: Float32Array,
@@ -61,11 +135,20 @@ function validateFrequencyBounds(fnName: string, fmin: number, fmax?: number): v
61
135
  * @param sampleRate - Sample rate in Hz (default: 22050)
62
136
  * @returns NNLS chroma result
63
137
  */
138
+ export function nnlsChroma(request: NnlsChromaRequest): WasmNnlsChromaResult;
64
139
  export function nnlsChroma(
65
140
  samples: Float32Array,
141
+ sampleRate?: number,
142
+ options?: GuardedOptions,
143
+ ): WasmNnlsChromaResult;
144
+ export function nnlsChroma(
145
+ samples: Float32Array | NnlsChromaRequest,
66
146
  sampleRate = 22050,
67
147
  options: GuardedOptions = {},
68
148
  ): WasmNnlsChromaResult {
149
+ if (!(samples instanceof Float32Array)) {
150
+ return nnlsChroma(samples.samples, samples.sampleRate, samples);
151
+ }
69
152
  validateMusicSamples('nnlsChroma', samples, sampleRate, options);
70
153
  return requireModule().nnlsChroma(samples, sampleRate);
71
154
  }
@@ -81,8 +164,18 @@ export function nnlsChroma(
81
164
  * @param binsPerOctave - Bins per octave (default: 12)
82
165
  * @returns CQT magnitude result
83
166
  */
167
+ export function cqt(request: CqtRequest): CqtResult;
84
168
  export function cqt(
85
169
  samples: Float32Array,
170
+ sampleRate?: number,
171
+ hopLength?: number,
172
+ fmin?: number,
173
+ nBins?: number,
174
+ binsPerOctave?: number,
175
+ options?: GuardedOptions,
176
+ ): CqtResult;
177
+ export function cqt(
178
+ samples: Float32Array | CqtRequest,
86
179
  sampleRate = 22050,
87
180
  hopLength = 512,
88
181
  fmin = 32.70319566257483,
@@ -90,6 +183,18 @@ export function cqt(
90
183
  binsPerOctave = 12,
91
184
  options: GuardedOptions = {},
92
185
  ): CqtResult {
186
+ if (!(samples instanceof Float32Array)) {
187
+ const request = samples;
188
+ return cqt(
189
+ request.samples,
190
+ request.sampleRate,
191
+ request.hopLength,
192
+ request.fmin,
193
+ request.nBins,
194
+ request.binsPerOctave,
195
+ request,
196
+ );
197
+ }
93
198
  validateMusicSamples('cqt', samples, sampleRate, options);
94
199
  validatePositiveIntegers('cqt', { hopLength, nBins, binsPerOctave });
95
200
  validateFrequencyBounds('cqt', fmin);
@@ -107,8 +212,18 @@ export function cqt(
107
212
  * @param binsPerOctave - Bins per octave (default: 12)
108
213
  * @returns CQT magnitude result
109
214
  */
215
+ export function pseudoCqt(request: CqtRequest): CqtResult;
110
216
  export function pseudoCqt(
111
217
  samples: Float32Array,
218
+ sampleRate?: number,
219
+ hopLength?: number,
220
+ fmin?: number,
221
+ nBins?: number,
222
+ binsPerOctave?: number,
223
+ options?: GuardedOptions,
224
+ ): CqtResult;
225
+ export function pseudoCqt(
226
+ samples: Float32Array | CqtRequest,
112
227
  sampleRate = 22050,
113
228
  hopLength = 512,
114
229
  fmin = 32.70319566257483,
@@ -116,6 +231,18 @@ export function pseudoCqt(
116
231
  binsPerOctave = 12,
117
232
  options: GuardedOptions = {},
118
233
  ): CqtResult {
234
+ if (!(samples instanceof Float32Array)) {
235
+ const request = samples;
236
+ return pseudoCqt(
237
+ request.samples,
238
+ request.sampleRate,
239
+ request.hopLength,
240
+ request.fmin,
241
+ request.nBins,
242
+ request.binsPerOctave,
243
+ request,
244
+ );
245
+ }
119
246
  validateMusicSamples('pseudoCqt', samples, sampleRate, options);
120
247
  validatePositiveIntegers('pseudoCqt', { hopLength, nBins, binsPerOctave });
121
248
  validateFrequencyBounds('pseudoCqt', fmin);
@@ -133,8 +260,18 @@ export function pseudoCqt(
133
260
  * @param binsPerOctave - Bins per octave (default: 12)
134
261
  * @returns CQT magnitude result
135
262
  */
263
+ export function hybridCqt(request: CqtRequest): CqtResult;
136
264
  export function hybridCqt(
137
265
  samples: Float32Array,
266
+ sampleRate?: number,
267
+ hopLength?: number,
268
+ fmin?: number,
269
+ nBins?: number,
270
+ binsPerOctave?: number,
271
+ options?: GuardedOptions,
272
+ ): CqtResult;
273
+ export function hybridCqt(
274
+ samples: Float32Array | CqtRequest,
138
275
  sampleRate = 22050,
139
276
  hopLength = 512,
140
277
  fmin = 32.70319566257483,
@@ -142,6 +279,18 @@ export function hybridCqt(
142
279
  binsPerOctave = 12,
143
280
  options: GuardedOptions = {},
144
281
  ): CqtResult {
282
+ if (!(samples instanceof Float32Array)) {
283
+ const request = samples;
284
+ return hybridCqt(
285
+ request.samples,
286
+ request.sampleRate,
287
+ request.hopLength,
288
+ request.fmin,
289
+ request.nBins,
290
+ request.binsPerOctave,
291
+ request,
292
+ );
293
+ }
145
294
  validateMusicSamples('hybridCqt', samples, sampleRate, options);
146
295
  validatePositiveIntegers('hybridCqt', { hopLength, nBins, binsPerOctave });
147
296
  validateFrequencyBounds('hybridCqt', fmin);
@@ -160,8 +309,19 @@ export function hybridCqt(
160
309
  * @param gamma - Bandwidth offset; 0 is equivalent to CQT (default: 0)
161
310
  * @returns VQT magnitude result (same shape as CQT)
162
311
  */
312
+ export function vqt(request: VqtRequest): CqtResult;
163
313
  export function vqt(
164
314
  samples: Float32Array,
315
+ sampleRate?: number,
316
+ hopLength?: number,
317
+ fmin?: number,
318
+ nBins?: number,
319
+ binsPerOctave?: number,
320
+ gamma?: number,
321
+ options?: GuardedOptions,
322
+ ): CqtResult;
323
+ export function vqt(
324
+ samples: Float32Array | VqtRequest,
165
325
  sampleRate = 22050,
166
326
  hopLength = 512,
167
327
  fmin = 32.70319566257483,
@@ -170,6 +330,19 @@ export function vqt(
170
330
  gamma = 0,
171
331
  options: GuardedOptions = {},
172
332
  ): CqtResult {
333
+ if (!(samples instanceof Float32Array)) {
334
+ const request = samples;
335
+ return vqt(
336
+ request.samples,
337
+ request.sampleRate,
338
+ request.hopLength,
339
+ request.fmin,
340
+ request.nBins,
341
+ request.binsPerOctave,
342
+ request.gamma,
343
+ request,
344
+ );
345
+ }
173
346
  validateMusicSamples('vqt', samples, sampleRate, options);
174
347
  validatePositiveIntegers('vqt', { hopLength, nBins, binsPerOctave });
175
348
  validateFrequencyBounds('vqt', fmin);
@@ -180,6 +353,165 @@ export function vqt(
180
353
  return requireModule().vqt(samples, sampleRate, hopLength, fmin, nBins, binsPerOctave, gamma);
181
354
  }
182
355
 
356
+ function validateCqtInverse(
357
+ fnName: string,
358
+ magnitude: Float32Array,
359
+ nBins: number,
360
+ nFrames: number,
361
+ sampleRate: number,
362
+ hopLength: number,
363
+ fmin: number,
364
+ binsPerOctave: number,
365
+ nIter: number,
366
+ options: GuardedOptions,
367
+ ): void {
368
+ assertSampleRate(fnName, sampleRate);
369
+ validatePositiveIntegers(fnName, { nBins, nFrames, hopLength, binsPerOctave, nIter });
370
+ if (nIter > 256) {
371
+ throw new RangeError(`${fnName}: nIter must be at most 256`);
372
+ }
373
+ validateFrequencyBounds(fnName, fmin);
374
+ if (fmin === 0) {
375
+ throw new RangeError(`${fnName}: fmin must be positive`);
376
+ }
377
+ if (magnitude.length !== nBins * nFrames) {
378
+ throw new RangeError(`${fnName}: magnitude length must equal nBins * nFrames`);
379
+ }
380
+ assertSamples(fnName, magnitude, options.validate !== false);
381
+ }
382
+
383
+ /** Reconstruct mono audio from row-major CQT magnitude via Griffin-Lim. */
384
+ export function cqtToAudio(request: CqtToAudioRequest): Float32Array;
385
+ export function cqtToAudio(
386
+ magnitude: Float32Array,
387
+ nBins: number,
388
+ nFrames: number,
389
+ sampleRate?: number,
390
+ hopLength?: number,
391
+ fmin?: number,
392
+ binsPerOctave?: number,
393
+ nIter?: number,
394
+ options?: GuardedOptions,
395
+ ): Float32Array;
396
+ export function cqtToAudio(
397
+ magnitude: Float32Array | CqtToAudioRequest,
398
+ nBins = 0,
399
+ nFrames = 0,
400
+ sampleRate = 22050,
401
+ hopLength = 512,
402
+ fmin = 32.70319566257483,
403
+ binsPerOctave = 12,
404
+ nIter = 32,
405
+ options: GuardedOptions = {},
406
+ ): Float32Array {
407
+ if (!(magnitude instanceof Float32Array)) {
408
+ const request = magnitude;
409
+ return cqtToAudio(
410
+ request.magnitude,
411
+ request.nBins,
412
+ request.nFrames,
413
+ request.sampleRate,
414
+ request.hopLength,
415
+ request.fmin,
416
+ request.binsPerOctave,
417
+ request.nIter,
418
+ request,
419
+ );
420
+ }
421
+ validateCqtInverse(
422
+ 'cqtToAudio',
423
+ magnitude,
424
+ nBins,
425
+ nFrames,
426
+ sampleRate,
427
+ hopLength,
428
+ fmin,
429
+ binsPerOctave,
430
+ nIter,
431
+ options,
432
+ );
433
+ return requireModule().cqtToAudio(
434
+ magnitude,
435
+ nBins,
436
+ nFrames,
437
+ sampleRate,
438
+ hopLength,
439
+ fmin,
440
+ binsPerOctave,
441
+ nIter,
442
+ );
443
+ }
444
+
445
+ /** Reconstruct mono audio from row-major VQT magnitude via Griffin-Lim. */
446
+ export function vqtToAudio(request: VqtToAudioRequest): Float32Array;
447
+ export function vqtToAudio(
448
+ magnitude: Float32Array,
449
+ nBins: number,
450
+ nFrames: number,
451
+ sampleRate?: number,
452
+ hopLength?: number,
453
+ fmin?: number,
454
+ binsPerOctave?: number,
455
+ gamma?: number,
456
+ nIter?: number,
457
+ options?: GuardedOptions,
458
+ ): Float32Array;
459
+ export function vqtToAudio(
460
+ magnitude: Float32Array | VqtToAudioRequest,
461
+ nBins = 0,
462
+ nFrames = 0,
463
+ sampleRate = 22050,
464
+ hopLength = 512,
465
+ fmin = 32.70319566257483,
466
+ binsPerOctave = 12,
467
+ gamma = 0,
468
+ nIter = 32,
469
+ options: GuardedOptions = {},
470
+ ): Float32Array {
471
+ if (!(magnitude instanceof Float32Array)) {
472
+ const request = magnitude;
473
+ return vqtToAudio(
474
+ request.magnitude,
475
+ request.nBins,
476
+ request.nFrames,
477
+ request.sampleRate,
478
+ request.hopLength,
479
+ request.fmin,
480
+ request.binsPerOctave,
481
+ request.gamma,
482
+ request.nIter,
483
+ request,
484
+ );
485
+ }
486
+ validateCqtInverse(
487
+ 'vqtToAudio',
488
+ magnitude,
489
+ nBins,
490
+ nFrames,
491
+ sampleRate,
492
+ hopLength,
493
+ fmin,
494
+ binsPerOctave,
495
+ nIter,
496
+ options,
497
+ );
498
+ assertFiniteScalar('vqtToAudio', gamma, 'gamma');
499
+ if (gamma < 0) {
500
+ throw new RangeError('vqtToAudio: gamma must be non-negative');
501
+ }
502
+ return requireModule().vqtToAudio(
503
+ magnitude,
504
+ nBins,
505
+ nFrames,
506
+ sampleRate,
507
+ hopLength,
508
+ fmin,
509
+ binsPerOctave,
510
+ gamma,
511
+ nIter,
512
+ );
513
+ }
514
+
183
515
  /**
184
516
  * Detect song-structure sections (intro/verse/chorus/...).
185
517
  *
@@ -190,11 +522,21 @@ export function vqt(
190
522
  * @param minSectionSec - Minimum section duration in seconds (default: 4.0)
191
523
  * @returns Array of detected sections
192
524
  */
525
+ export function analyzeSections(request: AnalyzeSectionsRequest): Section[];
193
526
  export function analyzeSections(
194
527
  samples: Float32Array,
528
+ sampleRate?: number,
529
+ options?: AnalyzeSectionsGuardedOptions,
530
+ ): Section[];
531
+ export function analyzeSections(
532
+ samples: Float32Array | AnalyzeSectionsRequest,
195
533
  sampleRate = 22050,
196
534
  options: AnalyzeSectionsGuardedOptions = {},
197
535
  ): Section[] {
536
+ if (!(samples instanceof Float32Array)) {
537
+ const r = samples;
538
+ return analyzeSections(r.samples, r.sampleRate, r);
539
+ }
198
540
  validateMusicSamples('analyzeSections', samples, sampleRate, options);
199
541
  validatePositiveIntegers('analyzeSections', {
200
542
  nFft: options.nFft ?? 2048,
@@ -252,11 +594,21 @@ export interface MelodyOptions {
252
594
  * @param options - Tracker + tuning options ({@link MelodyOptions})
253
595
  * @returns Melody contour with per-frame pitch points and summary stats
254
596
  */
597
+ export function analyzeMelody(request: AnalyzeMelodyRequest): MelodyResult;
255
598
  export function analyzeMelody(
256
599
  samples: Float32Array,
600
+ sampleRate?: number,
601
+ options?: MelodyGuardedOptions,
602
+ ): MelodyResult;
603
+ export function analyzeMelody(
604
+ samples: Float32Array | AnalyzeMelodyRequest,
257
605
  sampleRate = 22050,
258
606
  options: MelodyGuardedOptions = {},
259
607
  ): MelodyResult {
608
+ if (!(samples instanceof Float32Array)) {
609
+ const r = samples;
610
+ return analyzeMelody(r.samples, r.sampleRate, r);
611
+ }
260
612
  validateMusicSamples('analyzeMelody', samples, sampleRate, options);
261
613
  const fmin = options.fmin ?? 65.0;
262
614
  const fmax = options.fmax ?? 2093.0;
@@ -299,14 +651,34 @@ export function analyzeMelody(
299
651
  * @param nMels - Number of Mel bands (default: 128)
300
652
  * @returns Onset envelope for each frame
301
653
  */
654
+ export function onsetEnvelope(request: OnsetEnvelopeRequest): Float32Array;
302
655
  export function onsetEnvelope(
303
656
  samples: Float32Array,
657
+ sampleRate?: number,
658
+ nFft?: number,
659
+ hopLength?: number,
660
+ nMels?: number,
661
+ options?: GuardedOptions,
662
+ ): Float32Array;
663
+ export function onsetEnvelope(
664
+ samples: Float32Array | OnsetEnvelopeRequest,
304
665
  sampleRate = 22050,
305
666
  nFft = 2048,
306
667
  hopLength = 512,
307
668
  nMels = 128,
308
669
  options: GuardedOptions = {},
309
670
  ): Float32Array {
671
+ if (!(samples instanceof Float32Array)) {
672
+ const request = samples;
673
+ return onsetEnvelope(
674
+ request.samples,
675
+ request.sampleRate,
676
+ request.nFft,
677
+ request.hopLength,
678
+ request.nMels,
679
+ request,
680
+ );
681
+ }
310
682
  validateMusicSamples('onsetEnvelope', samples, sampleRate, options);
311
683
  validatePositiveIntegers('onsetEnvelope', { nFft, hopLength, nMels });
312
684
  return requireModule().onsetEnvelope(samples, sampleRate, nFft, hopLength, nMels);
@@ -323,8 +695,18 @@ export function onsetEnvelope(
323
695
  * @param nBands - Number of onset bands (default: 3)
324
696
  * @returns Multi-band onset matrix
325
697
  */
698
+ export function onsetStrengthMulti(request: OnsetStrengthMultiRequest): OnsetStrengthMultiResult;
326
699
  export function onsetStrengthMulti(
327
700
  samples: Float32Array,
701
+ sampleRate?: number,
702
+ nFft?: number,
703
+ hopLength?: number,
704
+ nMels?: number,
705
+ nBands?: number,
706
+ options?: GuardedOptions,
707
+ ): OnsetStrengthMultiResult;
708
+ export function onsetStrengthMulti(
709
+ samples: Float32Array | OnsetStrengthMultiRequest,
328
710
  sampleRate = 22050,
329
711
  nFft = 2048,
330
712
  hopLength = 512,
@@ -332,6 +714,18 @@ export function onsetStrengthMulti(
332
714
  nBands = 3,
333
715
  options: GuardedOptions = {},
334
716
  ): OnsetStrengthMultiResult {
717
+ if (!(samples instanceof Float32Array)) {
718
+ const request = samples;
719
+ return onsetStrengthMulti(
720
+ request.samples,
721
+ request.sampleRate,
722
+ request.nFft,
723
+ request.hopLength,
724
+ request.nMels,
725
+ request.nBands,
726
+ request,
727
+ );
728
+ }
335
729
  validateMusicSamples('onsetStrengthMulti', samples, sampleRate, options);
336
730
  validatePositiveIntegers('onsetStrengthMulti', { nFft, hopLength, nMels, nBands });
337
731
  return requireModule().onsetStrengthMulti(samples, sampleRate, nFft, hopLength, nMels, nBands);
@@ -346,13 +740,31 @@ export function onsetStrengthMulti(
346
740
  * @param winLength - Window length in frames (default: 384)
347
741
  * @returns Fourier tempogram result
348
742
  */
743
+ export function fourierTempogram(request: FourierTempogramRequest): WasmFourierTempogramResult;
349
744
  export function fourierTempogram(
350
745
  onsetEnvelope: Float32Array,
746
+ sampleRate?: number,
747
+ hopLength?: number,
748
+ winLength?: number,
749
+ options?: GuardedOptions,
750
+ ): WasmFourierTempogramResult;
751
+ export function fourierTempogram(
752
+ onsetEnvelope: Float32Array | FourierTempogramRequest,
351
753
  sampleRate = 22050,
352
754
  hopLength = 512,
353
755
  winLength = 384,
354
756
  options: GuardedOptions = {},
355
757
  ): WasmFourierTempogramResult {
758
+ if (!(onsetEnvelope instanceof Float32Array)) {
759
+ const request = onsetEnvelope;
760
+ return fourierTempogram(
761
+ request.onsetEnvelope,
762
+ request.sampleRate,
763
+ request.hopLength,
764
+ request.winLength,
765
+ request,
766
+ );
767
+ }
356
768
  assertSampleRate('fourierTempogram', sampleRate);
357
769
  assertSamples('fourierTempogram', onsetEnvelope, options.validate !== false, 'onsetEnvelope');
358
770
  validatePositiveIntegers('fourierTempogram', { hopLength, winLength });
@@ -370,14 +782,34 @@ export function fourierTempogram(
370
782
  * default {0.5, 1, 2, 3, 4} is used.
371
783
  * @returns Tempogram ratio features (one value per factor)
372
784
  */
785
+ export function tempogramRatio(request: TempogramRatioRequest): Float32Array;
373
786
  export function tempogramRatio(
374
787
  tempogramData: Float32Array,
788
+ winLength?: number,
789
+ sampleRate?: number,
790
+ hopLength?: number,
791
+ factors?: Float32Array | number[],
792
+ options?: GuardedOptions,
793
+ ): Float32Array;
794
+ export function tempogramRatio(
795
+ tempogramData: Float32Array | TempogramRatioRequest,
375
796
  winLength = 384,
376
797
  sampleRate = 22050,
377
798
  hopLength = 512,
378
799
  factors?: Float32Array | number[],
379
800
  options: GuardedOptions = {},
380
801
  ): Float32Array {
802
+ if (!(tempogramData instanceof Float32Array)) {
803
+ const request = tempogramData;
804
+ return tempogramRatio(
805
+ request.tempogramData,
806
+ request.winLength,
807
+ request.sampleRate,
808
+ request.hopLength,
809
+ request.factors,
810
+ request,
811
+ );
812
+ }
381
813
  assertSampleRate('tempogramRatio', sampleRate);
382
814
  assertSamples('tempogramRatio', tempogramData, options.validate !== false, 'tempogramData');
383
815
  validatePositiveIntegers('tempogramRatio', { winLength, hopLength });
@@ -393,11 +825,21 @@ export function tempogramRatio(
393
825
  * dependent and a wrong rate yields wrong loudness.
394
826
  * @returns Loudness measurement result
395
827
  */
828
+ export function lufs(request: LufsRequest): LufsResult;
396
829
  export function lufs(
397
830
  samples: Float32Array,
831
+ sampleRate?: number,
832
+ options?: ValidateOptions,
833
+ ): LufsResult;
834
+ export function lufs(
835
+ samples: Float32Array | LufsRequest,
398
836
  sampleRate = 22050,
399
837
  options: ValidateOptions = {},
400
838
  ): LufsResult {
839
+ if (!(samples instanceof Float32Array)) {
840
+ const r = samples;
841
+ return lufs(r.samples, r.sampleRate, r);
842
+ }
401
843
  assertSampleRate('lufs', sampleRate);
402
844
  assertSamples('lufs', samples, options.validate !== false);
403
845
  return requireModule().lufs(samples, sampleRate);
@@ -411,11 +853,21 @@ export function lufs(
411
853
  * K-weighting is sample-rate dependent; pass the buffer's actual rate.
412
854
  * @returns Momentary LUFS values over time
413
855
  */
856
+ export function momentaryLufs(request: LufsRequest): Float32Array;
414
857
  export function momentaryLufs(
415
858
  samples: Float32Array,
859
+ sampleRate?: number,
860
+ options?: ValidateOptions,
861
+ ): Float32Array;
862
+ export function momentaryLufs(
863
+ samples: Float32Array | LufsRequest,
416
864
  sampleRate = 22050,
417
865
  options: ValidateOptions = {},
418
866
  ): Float32Array {
867
+ if (!(samples instanceof Float32Array)) {
868
+ const r = samples;
869
+ return momentaryLufs(r.samples, r.sampleRate, r);
870
+ }
419
871
  assertSampleRate('momentaryLufs', sampleRate);
420
872
  assertSamples('momentaryLufs', samples, options.validate !== false);
421
873
  return requireModule().momentaryLufs(samples, sampleRate);
@@ -429,11 +881,21 @@ export function momentaryLufs(
429
881
  * K-weighting is sample-rate dependent; pass the buffer's actual rate.
430
882
  * @returns Short-term LUFS values over time
431
883
  */
884
+ export function shortTermLufs(request: LufsRequest): Float32Array;
432
885
  export function shortTermLufs(
433
886
  samples: Float32Array,
887
+ sampleRate?: number,
888
+ options?: ValidateOptions,
889
+ ): Float32Array;
890
+ export function shortTermLufs(
891
+ samples: Float32Array | LufsRequest,
434
892
  sampleRate = 22050,
435
893
  options: ValidateOptions = {},
436
894
  ): Float32Array {
895
+ if (!(samples instanceof Float32Array)) {
896
+ const r = samples;
897
+ return shortTermLufs(r.samples, r.sampleRate, r);
898
+ }
437
899
  assertSampleRate('shortTermLufs', sampleRate);
438
900
  assertSamples('shortTermLufs', samples, options.validate !== false);
439
901
  return requireModule().shortTermLufs(samples, sampleRate);