@libraz/libsonare 1.5.2 → 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 (46) hide show
  1. package/README.md +18 -3
  2. package/dist/index.d.ts +1147 -181
  3. package/dist/index.js +4826 -3941
  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 +1067 -973
  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 +357 -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/index.ts +130 -1
  23. package/src/mastering_chain.ts +305 -50
  24. package/src/mastering_core.ts +232 -16
  25. package/src/mastering_dynamics.ts +66 -10
  26. package/src/mastering_repair.ts +119 -7
  27. package/src/metering.ts +366 -81
  28. package/src/mixer.ts +9 -2
  29. package/src/mixing_oneshot.ts +25 -5
  30. package/src/module_state.ts +1 -1
  31. package/src/project_class.ts +17 -6
  32. package/src/project_internal.ts +10 -2
  33. package/src/project_types.ts +25 -2
  34. package/src/public_types_mastering.ts +114 -4
  35. package/src/public_types_spectral.ts +7 -0
  36. package/src/quick_analysis.ts +325 -117
  37. package/src/realtime_engine.ts +8 -0
  38. package/src/sonare.js.d.ts +31 -0
  39. package/src/stream_analyzer.ts +20 -1
  40. package/src/stream_types.ts +12 -1
  41. package/src/validation.ts +17 -2
  42. package/src/worklet/engine-clips.ts +67 -2
  43. package/src/worklet/engine-processor.ts +33 -5
  44. package/src/worklet/engine.ts +7 -3
  45. package/src/worklet/guards.ts +3 -0
  46. package/src/worklet/messages.ts +27 -0
@@ -1,6 +1,5 @@
1
1
  import { getSonareModule } from './module_state';
2
2
  import type { RealtimeVoiceChangerConfigInput } from './public_types';
3
- import { RealtimeVoiceChanger } from './streaming_mixing';
4
3
  import type { ValidateOptions } from './validation';
5
4
  import { assertSamples } from './validation';
6
5
 
@@ -16,6 +15,12 @@ export interface VoiceChangeOptions extends ValidateOptions {
16
15
  formantFactor?: number;
17
16
  }
18
17
 
18
+ /** Canonical request form for one-shot voice changing. */
19
+ export interface VoiceChangeRequest extends VoiceChangeOptions {
20
+ samples: Float32Array;
21
+ sampleRate?: number;
22
+ }
23
+
19
24
  /**
20
25
  * Apply a voice change by shifting pitch and formants independently.
21
26
  *
@@ -24,17 +29,24 @@ export interface VoiceChangeOptions extends ValidateOptions {
24
29
  * @param options - Pitch/formant settings ({@link VoiceChangeOptions})
25
30
  * @returns Voice-changed audio
26
31
  */
32
+ export function voiceChange(request: VoiceChangeRequest): Float32Array;
27
33
  export function voiceChange(
28
34
  samples: Float32Array,
35
+ sampleRate?: number,
36
+ options?: VoiceChangeOptions,
37
+ ): Float32Array;
38
+ export function voiceChange(
39
+ samples: Float32Array | VoiceChangeRequest,
29
40
  sampleRate = 22050,
30
41
  options: VoiceChangeOptions = {},
31
42
  ): Float32Array {
32
- assertSamples('voiceChange', samples, options.validate !== false);
43
+ const request = samples instanceof Float32Array ? { samples, sampleRate, ...options } : samples;
44
+ assertSamples('voiceChange', request.samples, request.validate !== false);
33
45
  return requireModule().voiceChange(
34
- samples,
35
- sampleRate,
36
- options.pitchSemitones ?? 0.0,
37
- options.formantFactor ?? 1.0,
46
+ request.samples,
47
+ request.sampleRate ?? 22050,
48
+ request.pitchSemitones ?? 0.0,
49
+ request.formantFactor ?? 1.0,
38
50
  );
39
51
  }
40
52
 
@@ -42,50 +54,23 @@ export function voiceChange(
42
54
  export interface VoiceChangeRealtimeOptions extends ValidateOptions {
43
55
  /** Channel count (1 = mono, 2 = interleaved stereo). */
44
56
  channels?: 1 | 2;
45
- /** Block size for the internal render loop (default 512). */
57
+ /** @deprecated The shared C-ABI renderer uses a fixed cross-surface block size. */
46
58
  blockSize?: number;
47
59
  }
48
60
 
49
- function latencyCompensatedVoiceChange(
50
- changer: RealtimeVoiceChanger,
51
- samples: Float32Array,
52
- channels: 1 | 2,
53
- blockFrames: number,
54
- ): Float32Array {
55
- const latencyFrames = Math.max(0, changer.latencySamples());
56
- if (channels === 1) {
57
- const total = samples.length + latencyFrames;
58
- const input = new Float32Array(total);
59
- input.set(samples);
60
- const processed = new Float32Array(total);
61
- for (let offset = 0; offset < total; offset += blockFrames) {
62
- const block = input.subarray(offset, Math.min(offset + blockFrames, total));
63
- processed.set(changer.processMono(block), offset);
64
- }
65
- return processed.slice(latencyFrames, latencyFrames + samples.length);
66
- }
67
-
68
- const frames = samples.length / 2;
69
- const totalFrames = frames + latencyFrames;
70
- const input = new Float32Array(totalFrames * 2);
71
- input.set(samples);
72
- const processed = new Float32Array(totalFrames * 2);
73
- const frameStride = blockFrames * 2;
74
- for (let offset = 0; offset < input.length; offset += frameStride) {
75
- const block = input.subarray(offset, Math.min(offset + frameStride, input.length));
76
- processed.set(changer.processInterleaved(block, 2), offset);
77
- }
78
- const start = latencyFrames * 2;
79
- return processed.slice(start, start + samples.length);
61
+ /** Canonical request form for offline realtime voice changing. */
62
+ export interface VoiceChangeRealtimeRequest extends VoiceChangeRealtimeOptions {
63
+ samples: Float32Array;
64
+ sampleRate?: number;
65
+ preset?: RealtimeVoiceChangerConfigInput;
80
66
  }
81
67
 
82
68
  /**
83
69
  * Applies the realtime voice-changer chain to a whole buffer in one call.
84
70
  *
85
- * Constructs and prepares a {@link RealtimeVoiceChanger}, runs the block loop
86
- * for the caller, then disposes it — matching the Python `voice_change_realtime`
87
- * and Node `voiceChangeRealtime` convenience wrappers. For mono, `samples` is a
88
- * plain mono buffer; for stereo, `samples` is interleaved (L0,R0,L1,R1,...).
71
+ * Uses the shared C-ABI renderer, so Python, Node, and WASM use the same
72
+ * fixed block size and latency compensation. For mono, `samples` is a plain
73
+ * buffer; for stereo, it is interleaved (L0,R0,L1,R1,...).
89
74
  *
90
75
  * @param samples - Audio samples (mono, or interleaved stereo when channels=2)
91
76
  * @param sampleRate - Sample rate in Hz (default 48000, matching Python/Node)
@@ -93,26 +78,34 @@ function latencyCompensatedVoiceChange(
93
78
  * @param options - Channel count and block size ({@link VoiceChangeRealtimeOptions})
94
79
  * @returns The processed buffer (same layout/length as the input).
95
80
  */
81
+ export function voiceChangeRealtime(request: VoiceChangeRealtimeRequest): Float32Array;
96
82
  export function voiceChangeRealtime(
97
83
  samples: Float32Array,
84
+ sampleRate?: number,
85
+ preset?: RealtimeVoiceChangerConfigInput,
86
+ options?: VoiceChangeRealtimeOptions,
87
+ ): Float32Array;
88
+ export function voiceChangeRealtime(
89
+ samples: Float32Array | VoiceChangeRealtimeRequest,
98
90
  sampleRate = 48000,
99
91
  preset: RealtimeVoiceChangerConfigInput = 'neutral-monitor',
100
92
  options: VoiceChangeRealtimeOptions = {},
101
93
  ): Float32Array {
102
- assertSamples('voiceChangeRealtime', samples, options.validate !== false);
103
- const channels = options.channels ?? 1;
94
+ const request =
95
+ samples instanceof Float32Array ? { samples, sampleRate, preset, ...options } : samples;
96
+ assertSamples('voiceChangeRealtime', request.samples, request.validate !== false);
97
+ const channels = request.channels ?? 1;
104
98
  if (channels !== 1 && channels !== 2) {
105
99
  throw new Error('voiceChangeRealtime: channels must be 1 or 2.');
106
100
  }
107
- if (channels === 2 && samples.length % 2 !== 0) {
101
+ if (channels === 2 && request.samples.length % 2 !== 0) {
108
102
  throw new Error('voiceChangeRealtime: stereo input length must be a multiple of 2.');
109
103
  }
110
- const blockSize = Math.max(1, Math.floor(options.blockSize ?? 512));
111
- const changer = new RealtimeVoiceChanger(preset);
112
- try {
113
- changer.prepare(sampleRate, blockSize, channels);
114
- return latencyCompensatedVoiceChange(changer, samples, channels, blockSize);
115
- } finally {
116
- changer.delete();
117
- }
104
+ const presetConfig = request.preset ?? 'neutral-monitor';
105
+ return requireModule().voiceChangeRealtime(
106
+ request.samples,
107
+ request.sampleRate ?? 48000,
108
+ typeof presetConfig === 'string' ? presetConfig : JSON.stringify(presetConfig),
109
+ channels,
110
+ );
118
111
  }
@@ -11,6 +11,102 @@ function requireModule() {
11
11
  return getSonareModule();
12
12
  }
13
13
 
14
+ export interface DbConversionRequest {
15
+ values: Float32Array;
16
+ ref?: number;
17
+ amin?: number;
18
+ topDb?: number;
19
+ }
20
+
21
+ export interface SilenceRequest {
22
+ samples: Float32Array;
23
+ topDb?: number;
24
+ frameLength?: number;
25
+ hopLength?: number;
26
+ }
27
+
28
+ export interface FrameSignalRequest {
29
+ samples: Float32Array;
30
+ frameLength: number;
31
+ hopLength: number;
32
+ }
33
+ /** Canonical request form for pre/de-emphasis filters. */
34
+ export interface EmphasisRequest {
35
+ samples: Float32Array;
36
+ coef?: number;
37
+ zi?: number;
38
+ }
39
+ /** Canonical request form for centering or extending a vector. */
40
+ export interface PadCenterRequest {
41
+ values: Float32Array;
42
+ targetSize: number;
43
+ padValue?: number;
44
+ }
45
+ /** Canonical request form for resizing a vector. */
46
+ export interface FixLengthRequest {
47
+ values: Float32Array;
48
+ targetSize: number;
49
+ padValue?: number;
50
+ }
51
+ /** Canonical request form for bounding a frame-index vector. */
52
+ export interface FixFramesRequest {
53
+ frames: Int32Array;
54
+ xMin?: number;
55
+ xMax?: number;
56
+ pad?: boolean;
57
+ }
58
+ /** Canonical request form for peak selection. */
59
+ export interface PeakPickRequest {
60
+ values: Float32Array;
61
+ preMax: number;
62
+ postMax: number;
63
+ preAvg: number;
64
+ postAvg: number;
65
+ delta: number;
66
+ wait: number;
67
+ }
68
+ /** Canonical request form for vector normalization. */
69
+ export interface VectorNormalizeRequest {
70
+ values: Float32Array;
71
+ normType?: number;
72
+ threshold?: number;
73
+ }
74
+ /** Canonical request form for tonal centroid projection. */
75
+ export interface TonnetzRequest {
76
+ chromagram: Float32Array;
77
+ nChroma: number;
78
+ nFrames: number;
79
+ }
80
+ export interface PcenRequest {
81
+ values: Float32Array;
82
+ nBins: number;
83
+ nFrames: number;
84
+ options?: Record<string, number>;
85
+ }
86
+ export interface TempogramRequest {
87
+ onsetEnvelope: Float32Array;
88
+ sampleRate?: number;
89
+ hopLength?: number;
90
+ winLength?: number;
91
+ mode?: TempogramMode;
92
+ }
93
+ export interface CyclicTempogramRequest {
94
+ onsetEnvelope: Float32Array;
95
+ sampleRate?: number;
96
+ hopLength?: number;
97
+ winLength?: number;
98
+ bpmMin?: number;
99
+ nBins?: number;
100
+ }
101
+ export interface PlpRequest {
102
+ onsetEnvelope: Float32Array;
103
+ sampleRate?: number;
104
+ hopLength?: number;
105
+ tempoMin?: number;
106
+ tempoMax?: number;
107
+ winLength?: number;
108
+ }
109
+
14
110
  // ============================================================================
15
111
  // Core - Unit Conversion
16
112
  // ============================================================================
@@ -107,21 +203,41 @@ export function samplesToFrames(samples: number, hopLength = 512, nFft = 0): num
107
203
  return requireModule().samplesToFrames(samples, hopLength, nFft);
108
204
  }
109
205
 
206
+ export function powerToDb(request: DbConversionRequest): Float32Array;
110
207
  export function powerToDb(
111
208
  values: Float32Array,
209
+ ref?: number,
210
+ amin?: number,
211
+ topDb?: number,
212
+ ): Float32Array;
213
+ export function powerToDb(
214
+ values: Float32Array | DbConversionRequest,
112
215
  ref = 1.0,
113
216
  amin = 1e-10,
114
217
  topDb = 80.0,
115
218
  ): Float32Array {
219
+ if (!(values instanceof Float32Array)) {
220
+ return powerToDb(values.values, values.ref, values.amin, values.topDb);
221
+ }
116
222
  return requireModule().powerToDb(values, ref, amin, topDb);
117
223
  }
118
224
 
225
+ export function amplitudeToDb(request: DbConversionRequest): Float32Array;
119
226
  export function amplitudeToDb(
120
227
  values: Float32Array,
228
+ ref?: number,
229
+ amin?: number,
230
+ topDb?: number,
231
+ ): Float32Array;
232
+ export function amplitudeToDb(
233
+ values: Float32Array | DbConversionRequest,
121
234
  ref = 1.0,
122
235
  amin = 1e-5,
123
236
  topDb = 80.0,
124
237
  ): Float32Array {
238
+ if (!(values instanceof Float32Array)) {
239
+ return amplitudeToDb(values.values, values.ref, values.amin, values.topDb);
240
+ }
125
241
  return requireModule().amplitudeToDb(values, ref, amin, topDb);
126
242
  }
127
243
 
@@ -133,52 +249,141 @@ export function dbToAmplitude(values: Float32Array, ref = 1.0): Float32Array {
133
249
  return requireModule().dbToAmplitude(values, ref);
134
250
  }
135
251
 
136
- export function preemphasis(samples: Float32Array, coef = 0.97, zi?: number): Float32Array {
252
+ export function preemphasis(request: EmphasisRequest): Float32Array;
253
+ export function preemphasis(samples: Float32Array, coef?: number, zi?: number): Float32Array;
254
+ export function preemphasis(
255
+ samples: Float32Array | EmphasisRequest,
256
+ coef = 0.97,
257
+ zi?: number,
258
+ ): Float32Array {
259
+ if (!(samples instanceof Float32Array)) {
260
+ return preemphasis(samples.samples, samples.coef, samples.zi);
261
+ }
137
262
  return requireModule().preemphasis(samples, coef, zi ?? null);
138
263
  }
139
264
 
140
- export function deemphasis(samples: Float32Array, coef = 0.97, zi?: number): Float32Array {
265
+ export function deemphasis(request: EmphasisRequest): Float32Array;
266
+ export function deemphasis(samples: Float32Array, coef?: number, zi?: number): Float32Array;
267
+ export function deemphasis(
268
+ samples: Float32Array | EmphasisRequest,
269
+ coef = 0.97,
270
+ zi?: number,
271
+ ): Float32Array {
272
+ if (!(samples instanceof Float32Array)) {
273
+ return deemphasis(samples.samples, samples.coef, samples.zi);
274
+ }
141
275
  return requireModule().deemphasis(samples, coef, zi ?? null);
142
276
  }
143
277
 
278
+ export function trimSilence(request: SilenceRequest): WasmTrimResult;
144
279
  export function trimSilence(
145
280
  samples: Float32Array,
281
+ topDb?: number,
282
+ frameLength?: number,
283
+ hopLength?: number,
284
+ ): WasmTrimResult;
285
+ export function trimSilence(
286
+ samples: Float32Array | SilenceRequest,
146
287
  topDb = 60.0,
147
288
  frameLength = 2048,
148
289
  hopLength = 512,
149
290
  ): WasmTrimResult {
291
+ if (!(samples instanceof Float32Array)) {
292
+ return trimSilence(samples.samples, samples.topDb, samples.frameLength, samples.hopLength);
293
+ }
150
294
  return requireModule().trimSilence(samples, topDb, frameLength, hopLength);
151
295
  }
152
296
 
297
+ export function splitSilence(request: SilenceRequest): Int32Array;
153
298
  export function splitSilence(
154
299
  samples: Float32Array,
300
+ topDb?: number,
301
+ frameLength?: number,
302
+ hopLength?: number,
303
+ ): Int32Array;
304
+ export function splitSilence(
305
+ samples: Float32Array | SilenceRequest,
155
306
  topDb = 60.0,
156
307
  frameLength = 2048,
157
308
  hopLength = 512,
158
309
  ): Int32Array {
310
+ if (!(samples instanceof Float32Array)) {
311
+ return splitSilence(samples.samples, samples.topDb, samples.frameLength, samples.hopLength);
312
+ }
159
313
  return requireModule().splitSilence(samples, topDb, frameLength, hopLength);
160
314
  }
161
315
 
316
+ export function frameSignal(request: FrameSignalRequest): WasmFrameResult;
162
317
  export function frameSignal(
163
318
  samples: Float32Array,
164
319
  frameLength: number,
165
320
  hopLength: number,
321
+ ): WasmFrameResult;
322
+ export function frameSignal(
323
+ samples: Float32Array | FrameSignalRequest,
324
+ frameLength?: number,
325
+ hopLength?: number,
166
326
  ): WasmFrameResult {
167
- return requireModule().frameSignal(samples, frameLength, hopLength);
327
+ if (!(samples instanceof Float32Array)) {
328
+ return frameSignal(samples.samples, samples.frameLength, samples.hopLength);
329
+ }
330
+ return requireModule().frameSignal(samples, frameLength as number, hopLength as number);
168
331
  }
169
332
 
170
- export function padCenter(values: Float32Array, targetSize: number, padValue = 0.0): Float32Array {
171
- return requireModule().padCenter(values, targetSize, padValue);
333
+ export function padCenter(request: PadCenterRequest): Float32Array;
334
+ export function padCenter(
335
+ values: Float32Array,
336
+ targetSize: number,
337
+ padValue?: number,
338
+ ): Float32Array;
339
+ export function padCenter(
340
+ values: Float32Array | PadCenterRequest,
341
+ targetSize?: number,
342
+ padValue = 0.0,
343
+ ): Float32Array {
344
+ if (!(values instanceof Float32Array)) {
345
+ return padCenter(values.values, values.targetSize, values.padValue);
346
+ }
347
+ return requireModule().padCenter(values, targetSize as number, padValue);
172
348
  }
173
349
 
174
- export function fixLength(values: Float32Array, targetSize: number, padValue = 0.0): Float32Array {
175
- return requireModule().fixLength(values, targetSize, padValue);
350
+ export function fixLength(request: FixLengthRequest): Float32Array;
351
+ export function fixLength(
352
+ values: Float32Array,
353
+ targetSize: number,
354
+ padValue?: number,
355
+ ): Float32Array;
356
+ export function fixLength(
357
+ values: Float32Array | FixLengthRequest,
358
+ targetSize?: number,
359
+ padValue = 0.0,
360
+ ): Float32Array {
361
+ if (!(values instanceof Float32Array)) {
362
+ return fixLength(values.values, values.targetSize, values.padValue);
363
+ }
364
+ return requireModule().fixLength(values, targetSize as number, padValue);
176
365
  }
177
366
 
178
- export function fixFrames(frames: Int32Array, xMin = 0, xMax = -1, pad = true): Int32Array {
367
+ export function fixFrames(request: FixFramesRequest): Int32Array;
368
+ export function fixFrames(
369
+ frames: Int32Array,
370
+ xMin?: number,
371
+ xMax?: number,
372
+ pad?: boolean,
373
+ ): Int32Array;
374
+ export function fixFrames(
375
+ frames: Int32Array | FixFramesRequest,
376
+ xMin = 0,
377
+ xMax = -1,
378
+ pad = true,
379
+ ): Int32Array {
380
+ if (!(frames instanceof Int32Array)) {
381
+ return fixFrames(frames.frames, frames.xMin, frames.xMax, frames.pad);
382
+ }
179
383
  return requireModule().fixFrames(frames, xMin, xMax, pad);
180
384
  }
181
385
 
386
+ export function peakPick(request: PeakPickRequest): Int32Array;
182
387
  export function peakPick(
183
388
  values: Float32Array,
184
389
  preMax: number,
@@ -187,45 +392,131 @@ export function peakPick(
187
392
  postAvg: number,
188
393
  delta: number,
189
394
  wait: number,
395
+ ): Int32Array;
396
+ export function peakPick(
397
+ values: Float32Array | PeakPickRequest,
398
+ preMax?: number,
399
+ postMax?: number,
400
+ preAvg?: number,
401
+ postAvg?: number,
402
+ delta?: number,
403
+ wait?: number,
190
404
  ): Int32Array {
191
- return requireModule().peakPick(values, preMax, postMax, preAvg, postAvg, delta, wait);
405
+ if (!(values instanceof Float32Array)) {
406
+ const r = values;
407
+ return peakPick(r.values, r.preMax, r.postMax, r.preAvg, r.postAvg, r.delta, r.wait);
408
+ }
409
+ return requireModule().peakPick(
410
+ values,
411
+ preMax as number,
412
+ postMax as number,
413
+ preAvg as number,
414
+ postAvg as number,
415
+ delta as number,
416
+ wait as number,
417
+ );
192
418
  }
193
419
 
194
- export function vectorNormalize(values: Float32Array, normType = 0, threshold = 0.0): Float32Array {
420
+ export function vectorNormalize(request: VectorNormalizeRequest): Float32Array;
421
+ export function vectorNormalize(
422
+ values: Float32Array,
423
+ normType?: number,
424
+ threshold?: number,
425
+ ): Float32Array;
426
+ export function vectorNormalize(
427
+ values: Float32Array | VectorNormalizeRequest,
428
+ normType = 0,
429
+ threshold = 0.0,
430
+ ): Float32Array {
431
+ if (!(values instanceof Float32Array)) {
432
+ return vectorNormalize(values.values, values.normType, values.threshold);
433
+ }
195
434
  return requireModule().vectorNormalize(values, normType, threshold);
196
435
  }
197
436
 
437
+ export function pcen(request: PcenRequest): Float32Array;
198
438
  export function pcen(
199
439
  values: Float32Array,
200
440
  nBins: number,
201
441
  nFrames: number,
442
+ options?: Record<string, number>,
443
+ ): Float32Array;
444
+ export function pcen(
445
+ values: Float32Array | PcenRequest,
446
+ nBins = 0,
447
+ nFrames = 0,
202
448
  options: Record<string, number> = {},
203
449
  ): Float32Array {
450
+ if (!(values instanceof Float32Array)) {
451
+ const r = values;
452
+ return pcen(r.values, r.nBins, r.nFrames, r.options);
453
+ }
204
454
  return requireModule().pcen(values, nBins, nFrames, options);
205
455
  }
206
456
 
207
- export function tonnetz(chromagram: Float32Array, nChroma: number, nFrames: number): Float32Array {
208
- return requireModule().tonnetz(chromagram, nChroma, nFrames);
457
+ export function tonnetz(request: TonnetzRequest): Float32Array;
458
+ export function tonnetz(chromagram: Float32Array, nChroma: number, nFrames: number): Float32Array;
459
+ export function tonnetz(
460
+ chromagram: Float32Array | TonnetzRequest,
461
+ nChroma?: number,
462
+ nFrames?: number,
463
+ ): Float32Array {
464
+ if (!(chromagram instanceof Float32Array)) {
465
+ return tonnetz(chromagram.chromagram, chromagram.nChroma, chromagram.nFrames);
466
+ }
467
+ return requireModule().tonnetz(chromagram, nChroma as number, nFrames as number);
209
468
  }
210
469
 
470
+ export function tempogram(request: TempogramRequest): WasmTempogramResult;
211
471
  export function tempogram(
212
472
  onsetEnvelope: Float32Array,
473
+ sampleRate?: number,
474
+ hopLength?: number,
475
+ winLength?: number,
476
+ mode?: TempogramMode,
477
+ ): WasmTempogramResult;
478
+ export function tempogram(
479
+ onsetEnvelope: Float32Array | TempogramRequest,
213
480
  sampleRate = 22050,
214
481
  hopLength = 512,
215
482
  winLength = 384,
216
483
  mode: TempogramMode = 'autocorrelation',
217
484
  ): WasmTempogramResult {
485
+ if (!(onsetEnvelope instanceof Float32Array)) {
486
+ const r = onsetEnvelope;
487
+ return tempogram(r.onsetEnvelope, r.sampleRate, r.hopLength, r.winLength, r.mode);
488
+ }
218
489
  return requireModule().tempogram(onsetEnvelope, sampleRate, hopLength, winLength, mode);
219
490
  }
220
491
 
492
+ export function cyclicTempogram(request: CyclicTempogramRequest): WasmCyclicTempogramResult;
221
493
  export function cyclicTempogram(
222
494
  onsetEnvelope: Float32Array,
495
+ sampleRate?: number,
496
+ hopLength?: number,
497
+ winLength?: number,
498
+ bpmMin?: number,
499
+ nBins?: number,
500
+ ): WasmCyclicTempogramResult;
501
+ export function cyclicTempogram(
502
+ onsetEnvelope: Float32Array | CyclicTempogramRequest,
223
503
  sampleRate = 22050,
224
504
  hopLength = 512,
225
505
  winLength = 384,
226
506
  bpmMin = 60.0,
227
507
  nBins = 60,
228
508
  ): WasmCyclicTempogramResult {
509
+ if (!(onsetEnvelope instanceof Float32Array)) {
510
+ const r = onsetEnvelope;
511
+ return cyclicTempogram(
512
+ r.onsetEnvelope,
513
+ r.sampleRate,
514
+ r.hopLength,
515
+ r.winLength,
516
+ r.bpmMin,
517
+ r.nBins,
518
+ );
519
+ }
229
520
  return requireModule().cyclicTempogram(
230
521
  onsetEnvelope,
231
522
  sampleRate,
@@ -236,13 +527,26 @@ export function cyclicTempogram(
236
527
  );
237
528
  }
238
529
 
530
+ export function plp(request: PlpRequest): Float32Array;
239
531
  export function plp(
240
532
  onsetEnvelope: Float32Array,
533
+ sampleRate?: number,
534
+ hopLength?: number,
535
+ tempoMin?: number,
536
+ tempoMax?: number,
537
+ winLength?: number,
538
+ ): Float32Array;
539
+ export function plp(
540
+ onsetEnvelope: Float32Array | PlpRequest,
241
541
  sampleRate = 22050,
242
542
  hopLength = 512,
243
543
  tempoMin = 30.0,
244
544
  tempoMax = 300.0,
245
545
  winLength = 384,
246
546
  ): Float32Array {
547
+ if (!(onsetEnvelope instanceof Float32Array)) {
548
+ const r = onsetEnvelope;
549
+ return plp(r.onsetEnvelope, r.sampleRate, r.hopLength, r.tempoMin, r.tempoMax, r.winLength);
550
+ }
247
551
  return requireModule().plp(onsetEnvelope, sampleRate, hopLength, tempoMin, tempoMax, winLength);
248
552
  }