@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
@@ -12,6 +12,95 @@ function requireModule() {
12
12
  return getSonareModule();
13
13
  }
14
14
 
15
+ /** Canonical request form for frame-based spectral feature extraction. */
16
+ export interface SpectralFrameRequest {
17
+ samples: Float32Array;
18
+ sampleRate?: number;
19
+ nFft?: number;
20
+ hopLength?: number;
21
+ }
22
+
23
+ export interface SpectralRolloffRequest extends SpectralFrameRequest {
24
+ rollPercent?: number;
25
+ }
26
+
27
+ export interface ZeroCrossingRateRequest {
28
+ samples: Float32Array;
29
+ sampleRate?: number;
30
+ frameLength?: number;
31
+ hopLength?: number;
32
+ }
33
+
34
+ export interface DecomposeRequest {
35
+ s: Float32Array;
36
+ nFeatures: number;
37
+ nFrames: number;
38
+ nComponents: number;
39
+ nIter?: number;
40
+ beta?: number;
41
+ }
42
+
43
+ export interface DecomposeWithInitRequest extends DecomposeRequest {
44
+ init?: 'random' | 'nndsvd';
45
+ }
46
+
47
+ export interface SpectralContrastRequest extends SpectralFrameRequest {
48
+ nBands?: number;
49
+ fmin?: number;
50
+ quantile?: number;
51
+ }
52
+ export interface PolyFeaturesRequest extends SpectralFrameRequest {
53
+ order?: number;
54
+ }
55
+ export interface ZeroCrossingsRequest {
56
+ samples: Float32Array;
57
+ threshold?: number;
58
+ refMagnitude?: boolean;
59
+ pad?: boolean;
60
+ zeroPos?: boolean;
61
+ }
62
+ export interface PitchTuningRequest {
63
+ frequencies: Float32Array;
64
+ resolution?: number;
65
+ binsPerOctave?: number;
66
+ }
67
+ export interface EstimateTuningRequest extends SpectralFrameRequest {
68
+ resolution?: number;
69
+ binsPerOctave?: number;
70
+ }
71
+ export interface NnFilterRequest {
72
+ s: Float32Array;
73
+ nFeatures: number;
74
+ nFrames: number;
75
+ aggregate?: string;
76
+ k?: number;
77
+ width?: number;
78
+ }
79
+ export interface RemixRequest {
80
+ samples: Float32Array;
81
+ intervals: Int32Array | ArrayLike<number>;
82
+ sampleRate?: number;
83
+ alignZeros?: boolean;
84
+ }
85
+ export interface PhaseVocoderRequest extends SpectralFrameRequest {
86
+ rate: number;
87
+ }
88
+ export interface HpssWithResidualRequest {
89
+ samples: Float32Array;
90
+ sampleRate?: number;
91
+ kernelHarmonic?: number;
92
+ kernelPercussive?: number;
93
+ }
94
+ export interface LufsInterleavedRequest extends ValidateOptions {
95
+ samples: Float32Array;
96
+ channels: number;
97
+ sampleRate?: number;
98
+ }
99
+ export interface Ebur128LoudnessRangeRequest extends ValidateOptions {
100
+ samples: Float32Array;
101
+ sampleRate?: number;
102
+ }
103
+
15
104
  // ============================================================================
16
105
  // Features - Spectral
17
106
  // ============================================================================
@@ -25,12 +114,22 @@ function requireModule() {
25
114
  * @param hopLength - Hop length (default: 512)
26
115
  * @returns Spectral centroid in Hz for each frame
27
116
  */
117
+ export function spectralCentroid(request: SpectralFrameRequest): Float32Array;
28
118
  export function spectralCentroid(
29
119
  samples: Float32Array,
120
+ sampleRate?: number,
121
+ nFft?: number,
122
+ hopLength?: number,
123
+ ): Float32Array;
124
+ export function spectralCentroid(
125
+ samples: Float32Array | SpectralFrameRequest,
30
126
  sampleRate = 22050,
31
127
  nFft = 2048,
32
128
  hopLength = 512,
33
129
  ): Float32Array {
130
+ if (!(samples instanceof Float32Array)) {
131
+ return spectralCentroid(samples.samples, samples.sampleRate, samples.nFft, samples.hopLength);
132
+ }
34
133
  return requireModule().spectralCentroid(samples, sampleRate, nFft, hopLength);
35
134
  }
36
135
 
@@ -39,8 +138,18 @@ export function spectralCentroid(
39
138
  *
40
139
  * @returns Matrix2d of shape (nBands + 1) x nFrames.
41
140
  */
141
+ export function spectralContrast(request: SpectralContrastRequest): WasmMatrix2dResult;
42
142
  export function spectralContrast(
43
143
  samples: Float32Array,
144
+ sampleRate?: number,
145
+ nFft?: number,
146
+ hopLength?: number,
147
+ nBands?: number,
148
+ fmin?: number,
149
+ quantile?: number,
150
+ ): WasmMatrix2dResult;
151
+ export function spectralContrast(
152
+ samples: Float32Array | SpectralContrastRequest,
44
153
  sampleRate = 22050,
45
154
  nFft = 2048,
46
155
  hopLength = 512,
@@ -48,6 +157,18 @@ export function spectralContrast(
48
157
  fmin = 200.0,
49
158
  quantile = 0.02,
50
159
  ): WasmMatrix2dResult {
160
+ if (!(samples instanceof Float32Array)) {
161
+ const r = samples;
162
+ return spectralContrast(
163
+ r.samples,
164
+ r.sampleRate,
165
+ r.nFft,
166
+ r.hopLength,
167
+ r.nBands,
168
+ r.fmin,
169
+ r.quantile,
170
+ );
171
+ }
51
172
  return requireModule().spectralContrast(
52
173
  samples,
53
174
  sampleRate,
@@ -64,26 +185,50 @@ export function spectralContrast(
64
185
  *
65
186
  * @returns Matrix2d of shape (order + 1) x nFrames.
66
187
  */
188
+ export function polyFeatures(request: PolyFeaturesRequest): WasmMatrix2dResult;
67
189
  export function polyFeatures(
68
190
  samples: Float32Array,
191
+ sampleRate?: number,
192
+ nFft?: number,
193
+ hopLength?: number,
194
+ order?: number,
195
+ ): WasmMatrix2dResult;
196
+ export function polyFeatures(
197
+ samples: Float32Array | PolyFeaturesRequest,
69
198
  sampleRate = 22050,
70
199
  nFft = 2048,
71
200
  hopLength = 512,
72
201
  order = 1,
73
202
  ): WasmMatrix2dResult {
203
+ if (!(samples instanceof Float32Array)) {
204
+ const r = samples;
205
+ return polyFeatures(r.samples, r.sampleRate, r.nFft, r.hopLength, r.order);
206
+ }
74
207
  return requireModule().polyFeatures(samples, sampleRate, nFft, hopLength, order);
75
208
  }
76
209
 
77
210
  /**
78
211
  * Locate zero-crossing indices of a signal (librosa.zero_crossings).
79
212
  */
213
+ export function zeroCrossings(request: ZeroCrossingsRequest): Int32Array;
80
214
  export function zeroCrossings(
81
215
  samples: Float32Array,
216
+ threshold?: number,
217
+ refMagnitude?: boolean,
218
+ pad?: boolean,
219
+ zeroPos?: boolean,
220
+ ): Int32Array;
221
+ export function zeroCrossings(
222
+ samples: Float32Array | ZeroCrossingsRequest,
82
223
  threshold = 1e-10,
83
224
  refMagnitude = false,
84
225
  pad = true,
85
226
  zeroPos = true,
86
227
  ): Int32Array {
228
+ if (!(samples instanceof Float32Array)) {
229
+ const r = samples;
230
+ return zeroCrossings(r.samples, r.threshold, r.refMagnitude, r.pad, r.zeroPos);
231
+ }
87
232
  return requireModule().zeroCrossings(samples, threshold, refMagnitude, pad, zeroPos);
88
233
  }
89
234
 
@@ -91,25 +236,55 @@ export function zeroCrossings(
91
236
  * Estimate the global tuning offset from a set of frequencies
92
237
  * (librosa.pitch_tuning). Returns a deviation in fractions of a bin.
93
238
  */
239
+ export function pitchTuning(request: PitchTuningRequest): number;
94
240
  export function pitchTuning(
95
241
  frequencies: Float32Array,
242
+ resolution?: number,
243
+ binsPerOctave?: number,
244
+ ): number;
245
+ export function pitchTuning(
246
+ frequencies: Float32Array | PitchTuningRequest,
96
247
  resolution = 0.01,
97
248
  binsPerOctave = 12,
98
249
  ): number {
250
+ if (!(frequencies instanceof Float32Array)) {
251
+ const r = frequencies;
252
+ return pitchTuning(r.frequencies, r.resolution, r.binsPerOctave);
253
+ }
99
254
  return requireModule().pitchTuning(frequencies, resolution, binsPerOctave);
100
255
  }
101
256
 
102
257
  /**
103
258
  * Estimate the tuning offset of an audio signal (librosa.estimate_tuning).
104
259
  */
260
+ export function estimateTuning(request: EstimateTuningRequest): number;
105
261
  export function estimateTuning(
106
262
  samples: Float32Array,
263
+ sampleRate?: number,
264
+ nFft?: number,
265
+ hopLength?: number,
266
+ resolution?: number,
267
+ binsPerOctave?: number,
268
+ ): number;
269
+ export function estimateTuning(
270
+ samples: Float32Array | EstimateTuningRequest,
107
271
  sampleRate = 22050,
108
272
  nFft = 2048,
109
273
  hopLength = 512,
110
274
  resolution = 0.01,
111
275
  binsPerOctave = 12,
112
276
  ): number {
277
+ if (!(samples instanceof Float32Array)) {
278
+ const r = samples;
279
+ return estimateTuning(
280
+ r.samples,
281
+ r.sampleRate,
282
+ r.nFft,
283
+ r.hopLength,
284
+ r.resolution,
285
+ r.binsPerOctave,
286
+ );
287
+ }
113
288
  return requireModule().estimateTuning(
114
289
  samples,
115
290
  sampleRate,
@@ -124,14 +299,34 @@ export function estimateTuning(
124
299
  * Non-negative matrix factorisation of a flattened [nFeatures x nFrames]
125
300
  * spectrogram (librosa.decompose.decompose). Returns the W and H factors.
126
301
  */
302
+ export function decompose(request: DecomposeRequest): WasmDecomposeResult;
127
303
  export function decompose(
128
304
  s: Float32Array,
129
305
  nFeatures: number,
130
306
  nFrames: number,
131
307
  nComponents: number,
308
+ nIter?: number,
309
+ beta?: number,
310
+ ): WasmDecomposeResult;
311
+ export function decompose(
312
+ s: Float32Array | DecomposeRequest,
313
+ nFeatures = 0,
314
+ nFrames = 0,
315
+ nComponents = 0,
132
316
  nIter = 50,
133
317
  beta = 2.0,
134
318
  ): WasmDecomposeResult {
319
+ if (!(s instanceof Float32Array)) {
320
+ const request = s;
321
+ return decompose(
322
+ request.s,
323
+ request.nFeatures,
324
+ request.nFrames,
325
+ request.nComponents,
326
+ request.nIter,
327
+ request.beta,
328
+ );
329
+ }
135
330
  return requireModule().decompose(s, nFeatures, nFrames, nComponents, nIter, beta);
136
331
  }
137
332
 
@@ -142,15 +337,37 @@ export function decompose(
142
337
  * or `'nndsvd'` (SVD-based warm start, which tends to converge in fewer
143
338
  * iterations). Returns the W and H factors.
144
339
  */
340
+ export function decomposeWithInit(request: DecomposeWithInitRequest): WasmDecomposeResult;
145
341
  export function decomposeWithInit(
146
342
  s: Float32Array,
147
343
  nFeatures: number,
148
344
  nFrames: number,
149
345
  nComponents: number,
346
+ nIter?: number,
347
+ beta?: number,
348
+ init?: 'random' | 'nndsvd',
349
+ ): WasmDecomposeResult;
350
+ export function decomposeWithInit(
351
+ s: Float32Array | DecomposeWithInitRequest,
352
+ nFeatures = 0,
353
+ nFrames = 0,
354
+ nComponents = 0,
150
355
  nIter = 50,
151
356
  beta = 2.0,
152
357
  init: 'random' | 'nndsvd' = 'random',
153
358
  ): WasmDecomposeResult {
359
+ if (!(s instanceof Float32Array)) {
360
+ const request = s;
361
+ return decomposeWithInit(
362
+ request.s,
363
+ request.nFeatures,
364
+ request.nFrames,
365
+ request.nComponents,
366
+ request.nIter,
367
+ request.beta,
368
+ request.init,
369
+ );
370
+ }
154
371
  return requireModule().decomposeWithInit(s, nFeatures, nFrames, nComponents, nIter, beta, init);
155
372
  }
156
373
 
@@ -158,14 +375,27 @@ export function decomposeWithInit(
158
375
  * Nearest-neighbour filtering of a flattened [nFeatures x nFrames] spectrogram
159
376
  * (librosa.decompose.nn_filter).
160
377
  */
378
+ export function nnFilter(request: NnFilterRequest): WasmMatrix2dResult;
161
379
  export function nnFilter(
162
380
  s: Float32Array,
163
381
  nFeatures: number,
164
382
  nFrames: number,
383
+ aggregate?: string,
384
+ k?: number,
385
+ width?: number,
386
+ ): WasmMatrix2dResult;
387
+ export function nnFilter(
388
+ s: Float32Array | NnFilterRequest,
389
+ nFeatures = 0,
390
+ nFrames = 0,
165
391
  aggregate = 'mean',
166
392
  k = 7,
167
393
  width = 1,
168
394
  ): WasmMatrix2dResult {
395
+ if (!(s instanceof Float32Array)) {
396
+ const r = s;
397
+ return nnFilter(r.s, r.nFeatures, r.nFrames, r.aggregate, r.k, r.width);
398
+ }
169
399
  return requireModule().nnFilter(s, nFeatures, nFrames, aggregate, k, width);
170
400
  }
171
401
 
@@ -174,43 +404,79 @@ export function nnFilter(
174
404
  *
175
405
  * @param intervals - Flat (start, end) sample pairs (even length).
176
406
  */
407
+ export function remix(request: RemixRequest): Float32Array;
177
408
  export function remix(
178
409
  samples: Float32Array,
179
410
  intervals: Int32Array | ArrayLike<number>,
411
+ sampleRate?: number,
412
+ alignZeros?: boolean,
413
+ ): Float32Array;
414
+ export function remix(
415
+ samples: Float32Array | RemixRequest,
416
+ intervals?: Int32Array | ArrayLike<number>,
180
417
  sampleRate = 22050,
181
418
  alignZeros = false,
182
419
  ): Float32Array {
420
+ if (!(samples instanceof Float32Array)) {
421
+ const r = samples;
422
+ return remix(r.samples, r.intervals, r.sampleRate, r.alignZeros);
423
+ }
183
424
  // Sample indices must reach the native side as exact 32-bit integers. Passing
184
425
  // a Float32Array (or a number[] holding fractional/large values) would round
185
426
  // boundaries above 2^24 and misalign the slice. Coerce to an Int32Array,
186
427
  // truncating toward zero, so callers can hand us any numeric array safely.
187
428
  const intervalsI32 =
188
- intervals instanceof Int32Array ? intervals : Int32Array.from(intervals, (v) => Math.trunc(v));
429
+ intervals instanceof Int32Array
430
+ ? intervals
431
+ : Int32Array.from(intervals as ArrayLike<number>, (v) => Math.trunc(v));
189
432
  return requireModule().remix(samples, intervalsI32, sampleRate, alignZeros);
190
433
  }
191
434
 
192
435
  /**
193
436
  * Phase-vocoder time-scale modification (rate > 1 faster, < 1 slower).
194
437
  */
438
+ export function phaseVocoder(request: PhaseVocoderRequest): Float32Array;
195
439
  export function phaseVocoder(
196
440
  samples: Float32Array,
197
441
  rate: number,
442
+ sampleRate?: number,
443
+ nFft?: number,
444
+ hopLength?: number,
445
+ ): Float32Array;
446
+ export function phaseVocoder(
447
+ samples: Float32Array | PhaseVocoderRequest,
448
+ rate = 1,
198
449
  sampleRate = 22050,
199
450
  nFft = 2048,
200
451
  hopLength = 512,
201
452
  ): Float32Array {
453
+ if (!(samples instanceof Float32Array)) {
454
+ const r = samples;
455
+ return phaseVocoder(r.samples, r.rate, r.sampleRate, r.nFft, r.hopLength);
456
+ }
202
457
  return requireModule().phaseVocoder(samples, sampleRate, rate, nFft, hopLength);
203
458
  }
204
459
 
205
460
  /**
206
461
  * HPSS into harmonic / percussive / residual signals.
207
462
  */
463
+ export function hpssWithResidual(request: HpssWithResidualRequest): WasmHpssWithResidualResult;
208
464
  export function hpssWithResidual(
209
465
  samples: Float32Array,
466
+ sampleRate?: number,
467
+ kernelHarmonic?: number,
468
+ kernelPercussive?: number,
469
+ ): WasmHpssWithResidualResult;
470
+ export function hpssWithResidual(
471
+ samples: Float32Array | HpssWithResidualRequest,
210
472
  sampleRate = 22050,
211
473
  kernelHarmonic = 31,
212
474
  kernelPercussive = 31,
213
475
  ): WasmHpssWithResidualResult {
476
+ if (!(samples instanceof Float32Array)) {
477
+ const r = samples;
478
+ return hpssWithResidual(r.samples, r.sampleRate, r.kernelHarmonic, r.kernelPercussive);
479
+ }
214
480
  return requireModule().hpssWithResidual(samples, sampleRate, kernelHarmonic, kernelPercussive);
215
481
  }
216
482
 
@@ -223,12 +489,23 @@ export function hpssWithResidual(
223
489
  * audio, and K-weighting is sample-rate dependent, so a wrong rate yields wrong
224
490
  * loudness.
225
491
  */
492
+ export function lufsInterleaved(request: LufsInterleavedRequest): WasmLufsResult;
226
493
  export function lufsInterleaved(
227
494
  samples: Float32Array,
228
495
  channels: number,
496
+ sampleRate?: number,
497
+ options?: ValidateOptions,
498
+ ): WasmLufsResult;
499
+ export function lufsInterleaved(
500
+ samples: Float32Array | LufsInterleavedRequest,
501
+ channels = 0,
229
502
  sampleRate = 22050,
230
503
  options: ValidateOptions = {},
231
504
  ): WasmLufsResult {
505
+ if (!(samples instanceof Float32Array)) {
506
+ const r = samples;
507
+ return lufsInterleaved(r.samples, r.channels, r.sampleRate, r);
508
+ }
232
509
  assertSampleRate('lufsInterleaved', sampleRate);
233
510
  assertInterleavedSamples('lufsInterleaved', samples, channels, options.validate !== false);
234
511
  return requireModule().lufsInterleaved(samples, channels, sampleRate);
@@ -239,7 +516,15 @@ export function lufsInterleaved(
239
516
  * actual `sampleRate`: the default (22050) is non-standard and K-weighting is
240
517
  * sample-rate dependent.
241
518
  */
242
- export function ebur128LoudnessRange(samples: Float32Array, sampleRate = 22050): number {
519
+ export function ebur128LoudnessRange(request: Ebur128LoudnessRangeRequest): number;
520
+ export function ebur128LoudnessRange(samples: Float32Array, sampleRate?: number): number;
521
+ export function ebur128LoudnessRange(
522
+ samples: Float32Array | Ebur128LoudnessRangeRequest,
523
+ sampleRate = 22050,
524
+ ): number {
525
+ if (!(samples instanceof Float32Array)) {
526
+ return ebur128LoudnessRange(samples.samples, samples.sampleRate);
527
+ }
243
528
  return requireModule().ebur128LoudnessRange(samples, sampleRate);
244
529
  }
245
530
 
@@ -252,12 +537,22 @@ export function ebur128LoudnessRange(samples: Float32Array, sampleRate = 22050):
252
537
  * @param hopLength - Hop length (default: 512)
253
538
  * @returns Spectral bandwidth in Hz for each frame
254
539
  */
540
+ export function spectralBandwidth(request: SpectralFrameRequest): Float32Array;
255
541
  export function spectralBandwidth(
256
542
  samples: Float32Array,
543
+ sampleRate?: number,
544
+ nFft?: number,
545
+ hopLength?: number,
546
+ ): Float32Array;
547
+ export function spectralBandwidth(
548
+ samples: Float32Array | SpectralFrameRequest,
257
549
  sampleRate = 22050,
258
550
  nFft = 2048,
259
551
  hopLength = 512,
260
552
  ): Float32Array {
553
+ if (!(samples instanceof Float32Array)) {
554
+ return spectralBandwidth(samples.samples, samples.sampleRate, samples.nFft, samples.hopLength);
555
+ }
261
556
  return requireModule().spectralBandwidth(samples, sampleRate, nFft, hopLength);
262
557
  }
263
558
 
@@ -271,13 +566,30 @@ export function spectralBandwidth(
271
566
  * @param rollPercent - Percentage threshold (default: 0.85)
272
567
  * @returns Rolloff frequency in Hz for each frame
273
568
  */
569
+ export function spectralRolloff(request: SpectralRolloffRequest): Float32Array;
274
570
  export function spectralRolloff(
275
571
  samples: Float32Array,
572
+ sampleRate?: number,
573
+ nFft?: number,
574
+ hopLength?: number,
575
+ rollPercent?: number,
576
+ ): Float32Array;
577
+ export function spectralRolloff(
578
+ samples: Float32Array | SpectralRolloffRequest,
276
579
  sampleRate = 22050,
277
580
  nFft = 2048,
278
581
  hopLength = 512,
279
582
  rollPercent = 0.85,
280
583
  ): Float32Array {
584
+ if (!(samples instanceof Float32Array)) {
585
+ return spectralRolloff(
586
+ samples.samples,
587
+ samples.sampleRate,
588
+ samples.nFft,
589
+ samples.hopLength,
590
+ samples.rollPercent,
591
+ );
592
+ }
281
593
  return requireModule().spectralRolloff(samples, sampleRate, nFft, hopLength, rollPercent);
282
594
  }
283
595
 
@@ -290,12 +602,22 @@ export function spectralRolloff(
290
602
  * @param hopLength - Hop length (default: 512)
291
603
  * @returns Spectral flatness for each frame (0 = tonal, 1 = noise-like)
292
604
  */
605
+ export function spectralFlatness(request: SpectralFrameRequest): Float32Array;
293
606
  export function spectralFlatness(
294
607
  samples: Float32Array,
608
+ sampleRate?: number,
609
+ nFft?: number,
610
+ hopLength?: number,
611
+ ): Float32Array;
612
+ export function spectralFlatness(
613
+ samples: Float32Array | SpectralFrameRequest,
295
614
  sampleRate = 22050,
296
615
  nFft = 2048,
297
616
  hopLength = 512,
298
617
  ): Float32Array {
618
+ if (!(samples instanceof Float32Array)) {
619
+ return spectralFlatness(samples.samples, samples.sampleRate, samples.nFft, samples.hopLength);
620
+ }
299
621
  return requireModule().spectralFlatness(samples, sampleRate, nFft, hopLength);
300
622
  }
301
623
 
@@ -308,12 +630,27 @@ export function spectralFlatness(
308
630
  * @param hopLength - Hop length (default: 512)
309
631
  * @returns Zero crossing rate for each frame
310
632
  */
633
+ export function zeroCrossingRate(request: ZeroCrossingRateRequest): Float32Array;
311
634
  export function zeroCrossingRate(
312
635
  samples: Float32Array,
636
+ sampleRate?: number,
637
+ frameLength?: number,
638
+ hopLength?: number,
639
+ ): Float32Array;
640
+ export function zeroCrossingRate(
641
+ samples: Float32Array | ZeroCrossingRateRequest,
313
642
  sampleRate = 22050,
314
643
  frameLength = 2048,
315
644
  hopLength = 512,
316
645
  ): Float32Array {
646
+ if (!(samples instanceof Float32Array)) {
647
+ return zeroCrossingRate(
648
+ samples.samples,
649
+ samples.sampleRate,
650
+ samples.frameLength,
651
+ samples.hopLength,
652
+ );
653
+ }
317
654
  return requireModule().zeroCrossingRate(samples, sampleRate, frameLength, hopLength);
318
655
  }
319
656
 
@@ -326,11 +663,21 @@ export function zeroCrossingRate(
326
663
  * @param hopLength - Hop length (default: 512)
327
664
  * @returns RMS energy for each frame
328
665
  */
666
+ export function rmsEnergy(request: ZeroCrossingRateRequest): Float32Array;
329
667
  export function rmsEnergy(
330
668
  samples: Float32Array,
669
+ sampleRate?: number,
670
+ frameLength?: number,
671
+ hopLength?: number,
672
+ ): Float32Array;
673
+ export function rmsEnergy(
674
+ samples: Float32Array | ZeroCrossingRateRequest,
331
675
  sampleRate = 22050,
332
676
  frameLength = 2048,
333
677
  hopLength = 512,
334
678
  ): Float32Array {
679
+ if (!(samples instanceof Float32Array)) {
680
+ return rmsEnergy(samples.samples, samples.sampleRate, samples.frameLength, samples.hopLength);
681
+ }
335
682
  return requireModule().rmsEnergy(samples, sampleRate, frameLength, hopLength);
336
683
  }