@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.
- package/README.md +18 -3
- package/dist/index.d.ts +1165 -178
- package/dist/index.js +4830 -3871
- package/dist/index.js.map +1 -1
- package/dist/sonare.js +1 -1
- package/dist/sonare.wasm +0 -0
- package/dist/worklet.d.ts +29 -1
- package/dist/worklet.js +1068 -974
- package/dist/worklet.js.map +1 -1
- package/package.json +2 -1
- package/src/_chain_config.ts +46 -0
- package/src/audio.ts +24 -4
- package/src/effects_mastering.ts +25 -1
- package/src/effects_transform.ts +283 -43
- package/src/effects_voice_change.ts +46 -53
- package/src/feature_core.ts +316 -12
- package/src/feature_music.ts +462 -0
- package/src/feature_pitch.ts +61 -0
- package/src/feature_resample.ts +17 -2
- package/src/feature_spectral.ts +349 -2
- package/src/feature_spectrogram.ts +336 -0
- package/src/features.ts +2 -0
- package/src/index.ts +133 -1
- package/src/mastering_chain.ts +305 -50
- package/src/mastering_core.ts +242 -16
- package/src/mastering_dynamics.ts +66 -10
- package/src/mastering_repair.ts +119 -7
- package/src/metering.ts +366 -81
- package/src/mixer.ts +10 -3
- package/src/mixing_oneshot.ts +25 -5
- package/src/module_state.ts +1 -1
- package/src/project_class.ts +17 -6
- package/src/project_internal.ts +10 -2
- package/src/project_types.ts +25 -2
- package/src/public_types_mastering.ts +114 -4
- package/src/public_types_music.ts +1 -0
- package/src/public_types_spectral.ts +7 -0
- package/src/quick_analysis.ts +325 -117
- package/src/realtime_engine.ts +8 -0
- package/src/sonare.js.d.ts +56 -0
- package/src/stream_analyzer.ts +25 -2
- package/src/stream_types.ts +16 -1
- package/src/validation.ts +17 -2
- package/src/worklet/engine-clips.ts +67 -2
- package/src/worklet/engine-processor.ts +33 -5
- package/src/worklet/engine.ts +7 -3
- package/src/worklet/guards.ts +3 -0
- package/src/worklet/messages.ts +27 -0
package/src/metering.ts
CHANGED
|
@@ -2,6 +2,25 @@ import { getSonareModule } from './module_state';
|
|
|
2
2
|
import type { ValidateOptions } from './validation';
|
|
3
3
|
import { assertSamples } from './validation';
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* Validates a true-peak oversample factor: `0` (meaning "use the default 4") or
|
|
7
|
+
* a power of two in `[1, 16]`. The native layer applies the same `0 -> 4`
|
|
8
|
+
* normalization (see `metering::true_peak_db`), so the raw factor can be passed
|
|
9
|
+
* through unchanged after this check. Kept module-local (not exported) so it does
|
|
10
|
+
* not surface as a WASM-only symbol with no C-API counterpart.
|
|
11
|
+
*/
|
|
12
|
+
function assertOversampleFactor(fnName: string, factor: number): void {
|
|
13
|
+
const normalized = factor === 0 ? 4 : factor;
|
|
14
|
+
if (
|
|
15
|
+
!Number.isInteger(normalized) ||
|
|
16
|
+
normalized < 1 ||
|
|
17
|
+
normalized > 16 ||
|
|
18
|
+
(normalized & (normalized - 1)) !== 0
|
|
19
|
+
) {
|
|
20
|
+
throw new RangeError(`${fnName}: oversampleFactor must be 0 or a power of two from 1 to 16`);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
5
24
|
// ============================================================================
|
|
6
25
|
// Metering — basic / true-peak / clipping / dynamic range
|
|
7
26
|
// ============================================================================
|
|
@@ -50,64 +69,122 @@ export interface MeteringDynamicRangeOptions extends ValidateOptions {
|
|
|
50
69
|
highPercentile?: number;
|
|
51
70
|
}
|
|
52
71
|
|
|
72
|
+
/** Canonical request form for single-channel meter readings. */
|
|
73
|
+
export interface MeteringSamplesRequest extends ValidateOptions {
|
|
74
|
+
samples: Float32Array;
|
|
75
|
+
sampleRate?: number;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/** Canonical request form for true-peak analysis. */
|
|
79
|
+
export interface MeteringTruePeakRequest extends MeteringSamplesRequest {
|
|
80
|
+
oversampleFactor?: number;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/** Canonical request form for clipping analysis. */
|
|
84
|
+
export interface MeteringDetectClippingRequest extends MeteringDetectClippingOptions {
|
|
85
|
+
samples: Float32Array;
|
|
86
|
+
sampleRate?: number;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/** Canonical request form for dynamic-range analysis. */
|
|
90
|
+
export interface MeteringDynamicRangeRequest extends MeteringDynamicRangeOptions {
|
|
91
|
+
samples: Float32Array;
|
|
92
|
+
sampleRate?: number;
|
|
93
|
+
}
|
|
94
|
+
|
|
53
95
|
function requireModule() {
|
|
54
96
|
return getSonareModule();
|
|
55
97
|
}
|
|
56
98
|
|
|
99
|
+
export function meteringPeakDb(request: MeteringSamplesRequest): number;
|
|
57
100
|
export function meteringPeakDb(
|
|
58
101
|
samples: Float32Array,
|
|
102
|
+
sampleRate?: number,
|
|
103
|
+
options?: ValidateOptions,
|
|
104
|
+
): number;
|
|
105
|
+
export function meteringPeakDb(
|
|
106
|
+
samples: Float32Array | MeteringSamplesRequest,
|
|
59
107
|
sampleRate = 22050,
|
|
60
108
|
options: ValidateOptions = {},
|
|
61
109
|
): number {
|
|
62
|
-
|
|
63
|
-
|
|
110
|
+
const request = samples instanceof Float32Array ? { samples, sampleRate, ...options } : samples;
|
|
111
|
+
assertSamples('meteringPeakDb', request.samples, request.validate !== false);
|
|
112
|
+
return requireModule().meteringPeakDb(request.samples, request.sampleRate ?? 22050);
|
|
64
113
|
}
|
|
65
114
|
|
|
115
|
+
export function meteringRmsDb(request: MeteringSamplesRequest): number;
|
|
66
116
|
export function meteringRmsDb(
|
|
67
117
|
samples: Float32Array,
|
|
118
|
+
sampleRate?: number,
|
|
119
|
+
options?: ValidateOptions,
|
|
120
|
+
): number;
|
|
121
|
+
export function meteringRmsDb(
|
|
122
|
+
samples: Float32Array | MeteringSamplesRequest,
|
|
68
123
|
sampleRate = 22050,
|
|
69
124
|
options: ValidateOptions = {},
|
|
70
125
|
): number {
|
|
71
|
-
|
|
72
|
-
|
|
126
|
+
const request = samples instanceof Float32Array ? { samples, sampleRate, ...options } : samples;
|
|
127
|
+
assertSamples('meteringRmsDb', request.samples, request.validate !== false);
|
|
128
|
+
return requireModule().meteringRmsDb(request.samples, request.sampleRate ?? 22050);
|
|
73
129
|
}
|
|
74
130
|
|
|
131
|
+
export function meteringCrestFactorDb(request: MeteringSamplesRequest): number;
|
|
75
132
|
export function meteringCrestFactorDb(
|
|
76
133
|
samples: Float32Array,
|
|
134
|
+
sampleRate?: number,
|
|
135
|
+
options?: ValidateOptions,
|
|
136
|
+
): number;
|
|
137
|
+
export function meteringCrestFactorDb(
|
|
138
|
+
samples: Float32Array | MeteringSamplesRequest,
|
|
77
139
|
sampleRate = 22050,
|
|
78
140
|
options: ValidateOptions = {},
|
|
79
141
|
): number {
|
|
80
|
-
|
|
81
|
-
|
|
142
|
+
const request = samples instanceof Float32Array ? { samples, sampleRate, ...options } : samples;
|
|
143
|
+
assertSamples('meteringCrestFactorDb', request.samples, request.validate !== false);
|
|
144
|
+
return requireModule().meteringCrestFactorDb(request.samples, request.sampleRate ?? 22050);
|
|
82
145
|
}
|
|
83
146
|
|
|
147
|
+
export function meteringDcOffset(request: MeteringSamplesRequest): number;
|
|
84
148
|
export function meteringDcOffset(
|
|
85
149
|
samples: Float32Array,
|
|
150
|
+
sampleRate?: number,
|
|
151
|
+
options?: ValidateOptions,
|
|
152
|
+
): number;
|
|
153
|
+
export function meteringDcOffset(
|
|
154
|
+
samples: Float32Array | MeteringSamplesRequest,
|
|
86
155
|
sampleRate = 22050,
|
|
87
156
|
options: ValidateOptions = {},
|
|
88
157
|
): number {
|
|
89
|
-
|
|
90
|
-
|
|
158
|
+
const request = samples instanceof Float32Array ? { samples, sampleRate, ...options } : samples;
|
|
159
|
+
assertSamples('meteringDcOffset', request.samples, request.validate !== false);
|
|
160
|
+
return requireModule().meteringDcOffset(request.samples, request.sampleRate ?? 22050);
|
|
91
161
|
}
|
|
92
162
|
|
|
93
163
|
/**
|
|
94
164
|
* Inter-sample (true) peak in dBFS. `oversampleFactor` must be a power of two
|
|
95
165
|
* in [1, 16]; pass 0 to use the library default (4).
|
|
96
166
|
*/
|
|
167
|
+
export function meteringTruePeakDb(request: MeteringTruePeakRequest): number;
|
|
97
168
|
export function meteringTruePeakDb(
|
|
98
169
|
samples: Float32Array,
|
|
170
|
+
sampleRate?: number,
|
|
171
|
+
oversampleFactor?: number,
|
|
172
|
+
options?: ValidateOptions,
|
|
173
|
+
): number;
|
|
174
|
+
export function meteringTruePeakDb(
|
|
175
|
+
samples: Float32Array | MeteringTruePeakRequest,
|
|
99
176
|
sampleRate = 22050,
|
|
100
177
|
oversampleFactor = 4,
|
|
101
178
|
options: ValidateOptions = {},
|
|
102
179
|
): number {
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
return requireModule().meteringTruePeakDb(samples, sampleRate,
|
|
180
|
+
const request =
|
|
181
|
+
samples instanceof Float32Array
|
|
182
|
+
? { samples, sampleRate, oversampleFactor, ...options }
|
|
183
|
+
: samples;
|
|
184
|
+
assertSamples('meteringTruePeakDb', request.samples, request.validate !== false);
|
|
185
|
+
const factor = request.oversampleFactor ?? 4;
|
|
186
|
+
assertOversampleFactor('meteringTruePeakDb', factor);
|
|
187
|
+
return requireModule().meteringTruePeakDb(request.samples, request.sampleRate ?? 22050, factor);
|
|
111
188
|
}
|
|
112
189
|
|
|
113
190
|
/**
|
|
@@ -116,17 +193,24 @@ export function meteringTruePeakDb(
|
|
|
116
193
|
* @param threshold Linear absolute threshold (default 0.999).
|
|
117
194
|
* @param minRegionSamples Minimum run length to report (default 1).
|
|
118
195
|
*/
|
|
196
|
+
export function meteringDetectClipping(request: MeteringDetectClippingRequest): ClippingReport;
|
|
119
197
|
export function meteringDetectClipping(
|
|
120
198
|
samples: Float32Array,
|
|
199
|
+
sampleRate?: number,
|
|
200
|
+
options?: MeteringDetectClippingOptions,
|
|
201
|
+
): ClippingReport;
|
|
202
|
+
export function meteringDetectClipping(
|
|
203
|
+
samples: Float32Array | MeteringDetectClippingRequest,
|
|
121
204
|
sampleRate = 22050,
|
|
122
205
|
options: MeteringDetectClippingOptions = {},
|
|
123
206
|
): ClippingReport {
|
|
124
|
-
|
|
207
|
+
const request = samples instanceof Float32Array ? { samples, sampleRate, ...options } : samples;
|
|
208
|
+
assertSamples('meteringDetectClipping', request.samples, request.validate !== false);
|
|
125
209
|
return requireModule().meteringDetectClipping(
|
|
126
|
-
samples,
|
|
127
|
-
sampleRate,
|
|
128
|
-
|
|
129
|
-
|
|
210
|
+
request.samples,
|
|
211
|
+
request.sampleRate ?? 22050,
|
|
212
|
+
request.threshold ?? 0.999,
|
|
213
|
+
request.minRegionSamples ?? 1,
|
|
130
214
|
);
|
|
131
215
|
}
|
|
132
216
|
|
|
@@ -136,19 +220,26 @@ export function meteringDetectClipping(
|
|
|
136
220
|
* "use the library default" (low=0.10, high=0.95) because 0 is a literal 0th
|
|
137
221
|
* percentile; omitted percentiles therefore default to -1.
|
|
138
222
|
*/
|
|
223
|
+
export function meteringDynamicRange(request: MeteringDynamicRangeRequest): DynamicRangeReport;
|
|
139
224
|
export function meteringDynamicRange(
|
|
140
225
|
samples: Float32Array,
|
|
226
|
+
sampleRate?: number,
|
|
227
|
+
options?: MeteringDynamicRangeOptions,
|
|
228
|
+
): DynamicRangeReport;
|
|
229
|
+
export function meteringDynamicRange(
|
|
230
|
+
samples: Float32Array | MeteringDynamicRangeRequest,
|
|
141
231
|
sampleRate = 22050,
|
|
142
232
|
options: MeteringDynamicRangeOptions = {},
|
|
143
233
|
): DynamicRangeReport {
|
|
144
|
-
|
|
234
|
+
const request = samples instanceof Float32Array ? { samples, sampleRate, ...options } : samples;
|
|
235
|
+
assertSamples('meteringDynamicRange', request.samples, request.validate !== false);
|
|
145
236
|
return requireModule().meteringDynamicRange(
|
|
146
|
-
samples,
|
|
147
|
-
sampleRate,
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
237
|
+
request.samples,
|
|
238
|
+
request.sampleRate ?? 22050,
|
|
239
|
+
request.windowSec ?? 0,
|
|
240
|
+
request.hopSec ?? 0,
|
|
241
|
+
request.lowPercentile ?? -1,
|
|
242
|
+
request.highPercentile ?? -1,
|
|
152
243
|
);
|
|
153
244
|
}
|
|
154
245
|
|
|
@@ -209,6 +300,51 @@ export interface WaveformPeakPyramidOptions extends ValidateOptions {
|
|
|
209
300
|
samplesPerBucketLevels?: number[];
|
|
210
301
|
}
|
|
211
302
|
|
|
303
|
+
/** Canonical request form for stereo meter readings. */
|
|
304
|
+
export interface MeteringStereoRequest extends ValidateOptions {
|
|
305
|
+
left: Float32Array;
|
|
306
|
+
right: Float32Array;
|
|
307
|
+
sampleRate?: number;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/** Canonical request form for display-decimated stereo scopes. */
|
|
311
|
+
export interface MeteringStereoDecimatedRequest extends MeteringStereoRequest {
|
|
312
|
+
maxPoints?: number;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
/** Options for the scope functions (mirrors the Node `ScopeOptions`). */
|
|
316
|
+
export interface ScopeOptions extends ValidateOptions {
|
|
317
|
+
/**
|
|
318
|
+
* Upper bound on the returned point count. Omit / `0` (or a value `>= length`)
|
|
319
|
+
* yields one point per input sample; otherwise the point cloud is
|
|
320
|
+
* deterministically decimated to at most `maxPoints` points for display.
|
|
321
|
+
*/
|
|
322
|
+
maxPoints?: number;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
/** Canonical request form for whole-signal spectrum analysis. */
|
|
326
|
+
export interface MeteringSpectrumRequest extends SpectrumOptions, ValidateOptions {
|
|
327
|
+
samples: Float32Array;
|
|
328
|
+
sampleRate?: number;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
/** Canonical request form for a single spectrum frame. */
|
|
332
|
+
export interface MeteringSpectrumFrameRequest extends MeteringSpectrumRequest {
|
|
333
|
+
frameOffset?: number;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
/** Canonical request form for waveform bucket generation. */
|
|
337
|
+
export interface WaveformPeaksRequest extends WaveformPeaksOptions {
|
|
338
|
+
samples: Float32Array;
|
|
339
|
+
channels: number;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
/** Canonical request form for multi-resolution waveform bucket generation. */
|
|
343
|
+
export interface WaveformPeakPyramidRequest extends WaveformPeakPyramidOptions {
|
|
344
|
+
samples: Float32Array;
|
|
345
|
+
channels: number;
|
|
346
|
+
}
|
|
347
|
+
|
|
212
348
|
/** Per-channel min/max waveform buckets. Arrays are channel-major. */
|
|
213
349
|
export interface WaveformPeaksReport {
|
|
214
350
|
min: Float32Array;
|
|
@@ -219,97 +355,207 @@ export interface WaveformPeaksReport {
|
|
|
219
355
|
}
|
|
220
356
|
|
|
221
357
|
/** Pearson correlation in [-1, 1] between two equal-length channels. */
|
|
358
|
+
export function meteringStereoCorrelation(request: MeteringStereoRequest): number;
|
|
222
359
|
export function meteringStereoCorrelation(
|
|
223
360
|
left: Float32Array,
|
|
224
361
|
right: Float32Array,
|
|
362
|
+
sampleRate?: number,
|
|
363
|
+
options?: ValidateOptions,
|
|
364
|
+
): number;
|
|
365
|
+
export function meteringStereoCorrelation(
|
|
366
|
+
left: Float32Array | MeteringStereoRequest,
|
|
367
|
+
right?: Float32Array,
|
|
225
368
|
sampleRate = 22050,
|
|
226
369
|
options: ValidateOptions = {},
|
|
227
370
|
): number {
|
|
228
|
-
const
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
371
|
+
const request =
|
|
372
|
+
left instanceof Float32Array
|
|
373
|
+
? { left, right: right as Float32Array, sampleRate, ...options }
|
|
374
|
+
: left;
|
|
375
|
+
const validate = request.validate !== false;
|
|
376
|
+
assertSamples('meteringStereoCorrelation', request.left, validate, 'left');
|
|
377
|
+
assertSamples('meteringStereoCorrelation', request.right, validate, 'right');
|
|
378
|
+
return requireModule().meteringStereoCorrelation(
|
|
379
|
+
request.left,
|
|
380
|
+
request.right,
|
|
381
|
+
request.sampleRate ?? 22050,
|
|
382
|
+
);
|
|
232
383
|
}
|
|
233
384
|
|
|
234
385
|
/**
|
|
235
386
|
* Side / mid energy ratio, clamped to `[0, 2]`: 0 = pure mono, ~1 = wide
|
|
236
387
|
* stereo, 2 = fully decorrelated / out-of-phase.
|
|
237
388
|
*/
|
|
389
|
+
export function meteringStereoWidth(request: MeteringStereoRequest): number;
|
|
238
390
|
export function meteringStereoWidth(
|
|
239
391
|
left: Float32Array,
|
|
240
392
|
right: Float32Array,
|
|
393
|
+
sampleRate?: number,
|
|
394
|
+
options?: ValidateOptions,
|
|
395
|
+
): number;
|
|
396
|
+
export function meteringStereoWidth(
|
|
397
|
+
left: Float32Array | MeteringStereoRequest,
|
|
398
|
+
right?: Float32Array,
|
|
241
399
|
sampleRate = 22050,
|
|
242
400
|
options: ValidateOptions = {},
|
|
243
401
|
): number {
|
|
244
|
-
const
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
402
|
+
const request =
|
|
403
|
+
left instanceof Float32Array
|
|
404
|
+
? { left, right: right as Float32Array, sampleRate, ...options }
|
|
405
|
+
: left;
|
|
406
|
+
const validate = request.validate !== false;
|
|
407
|
+
assertSamples('meteringStereoWidth', request.left, validate, 'left');
|
|
408
|
+
assertSamples('meteringStereoWidth', request.right, validate, 'right');
|
|
409
|
+
return requireModule().meteringStereoWidth(
|
|
410
|
+
request.left,
|
|
411
|
+
request.right,
|
|
412
|
+
request.sampleRate ?? 22050,
|
|
413
|
+
);
|
|
248
414
|
}
|
|
249
415
|
|
|
250
|
-
/**
|
|
416
|
+
/**
|
|
417
|
+
* Mid/side vectorscope point series. By default emits one point per input
|
|
418
|
+
* sample; pass `maxPoints` to get a display-sized decimated point set (matching
|
|
419
|
+
* the Node `meteringVectorscope` shape).
|
|
420
|
+
*/
|
|
421
|
+
export function meteringVectorscope(request: MeteringStereoDecimatedRequest): VectorscopeReport;
|
|
251
422
|
export function meteringVectorscope(
|
|
252
423
|
left: Float32Array,
|
|
253
424
|
right: Float32Array,
|
|
425
|
+
sampleRate?: number,
|
|
426
|
+
options?: ScopeOptions,
|
|
427
|
+
): VectorscopeReport;
|
|
428
|
+
export function meteringVectorscope(
|
|
429
|
+
left: Float32Array | MeteringStereoDecimatedRequest,
|
|
430
|
+
right?: Float32Array,
|
|
254
431
|
sampleRate = 22050,
|
|
255
|
-
options:
|
|
432
|
+
options: ScopeOptions = {},
|
|
256
433
|
): VectorscopeReport {
|
|
257
|
-
const
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
434
|
+
const request =
|
|
435
|
+
left instanceof Float32Array
|
|
436
|
+
? { left, right: right as Float32Array, sampleRate, ...options }
|
|
437
|
+
: left;
|
|
438
|
+
const validate = request.validate !== false;
|
|
439
|
+
assertSamples('meteringVectorscope', request.left, validate, 'left');
|
|
440
|
+
assertSamples('meteringVectorscope', request.right, validate, 'right');
|
|
441
|
+
return requireModule().meteringVectorscopeDecimated(
|
|
442
|
+
request.left,
|
|
443
|
+
request.right,
|
|
444
|
+
request.sampleRate ?? 22050,
|
|
445
|
+
request.maxPoints ?? 0,
|
|
446
|
+
);
|
|
261
447
|
}
|
|
262
448
|
|
|
263
449
|
/**
|
|
264
|
-
* Display-sized mid/side vectorscope.
|
|
265
|
-
*
|
|
266
|
-
*
|
|
267
|
-
* Node
|
|
450
|
+
* Display-sized mid/side vectorscope.
|
|
451
|
+
*
|
|
452
|
+
* @deprecated Pass `maxPoints` to {@link meteringVectorscope} instead; it now
|
|
453
|
+
* folds `maxPoints` into the request, matching the Node surface. This alias is
|
|
454
|
+
* kept for backward compatibility and simply delegates.
|
|
268
455
|
*/
|
|
456
|
+
export function meteringVectorscopeDecimated(
|
|
457
|
+
request: MeteringStereoDecimatedRequest,
|
|
458
|
+
): VectorscopeReport;
|
|
269
459
|
export function meteringVectorscopeDecimated(
|
|
270
460
|
left: Float32Array,
|
|
271
461
|
right: Float32Array,
|
|
462
|
+
sampleRate?: number,
|
|
463
|
+
maxPoints?: number,
|
|
464
|
+
options?: ValidateOptions,
|
|
465
|
+
): VectorscopeReport;
|
|
466
|
+
export function meteringVectorscopeDecimated(
|
|
467
|
+
left: Float32Array | MeteringStereoDecimatedRequest,
|
|
468
|
+
right?: Float32Array,
|
|
272
469
|
sampleRate = 22050,
|
|
273
470
|
maxPoints = 0,
|
|
274
471
|
options: ValidateOptions = {},
|
|
275
472
|
): VectorscopeReport {
|
|
276
|
-
const
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
473
|
+
const request =
|
|
474
|
+
left instanceof Float32Array
|
|
475
|
+
? { left, right: right as Float32Array, sampleRate, maxPoints, ...options }
|
|
476
|
+
: left;
|
|
477
|
+
const validate = request.validate !== false;
|
|
478
|
+
assertSamples('meteringVectorscopeDecimated', request.left, validate, 'left');
|
|
479
|
+
assertSamples('meteringVectorscopeDecimated', request.right, validate, 'right');
|
|
480
|
+
return requireModule().meteringVectorscopeDecimated(
|
|
481
|
+
request.left,
|
|
482
|
+
request.right,
|
|
483
|
+
request.sampleRate ?? 22050,
|
|
484
|
+
request.maxPoints ?? 0,
|
|
485
|
+
);
|
|
280
486
|
}
|
|
281
487
|
|
|
282
|
-
/**
|
|
488
|
+
/**
|
|
489
|
+
* Phase-scope point series plus summary stats. By default emits one point per
|
|
490
|
+
* input sample; pass `maxPoints` to decimate the point cloud for display
|
|
491
|
+
* (matching the Node `meteringPhaseScope` shape). The summary stats are always
|
|
492
|
+
* computed over the full-resolution signal.
|
|
493
|
+
*/
|
|
494
|
+
export function meteringPhaseScope(request: MeteringStereoDecimatedRequest): PhaseScopeReport;
|
|
283
495
|
export function meteringPhaseScope(
|
|
284
496
|
left: Float32Array,
|
|
285
497
|
right: Float32Array,
|
|
498
|
+
sampleRate?: number,
|
|
499
|
+
options?: ScopeOptions,
|
|
500
|
+
): PhaseScopeReport;
|
|
501
|
+
export function meteringPhaseScope(
|
|
502
|
+
left: Float32Array | MeteringStereoDecimatedRequest,
|
|
503
|
+
right?: Float32Array,
|
|
286
504
|
sampleRate = 22050,
|
|
287
|
-
options:
|
|
505
|
+
options: ScopeOptions = {},
|
|
288
506
|
): PhaseScopeReport {
|
|
289
|
-
const
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
507
|
+
const request =
|
|
508
|
+
left instanceof Float32Array
|
|
509
|
+
? { left, right: right as Float32Array, sampleRate, ...options }
|
|
510
|
+
: left;
|
|
511
|
+
const validate = request.validate !== false;
|
|
512
|
+
assertSamples('meteringPhaseScope', request.left, validate, 'left');
|
|
513
|
+
assertSamples('meteringPhaseScope', request.right, validate, 'right');
|
|
514
|
+
return requireModule().meteringPhaseScopeDecimated(
|
|
515
|
+
request.left,
|
|
516
|
+
request.right,
|
|
517
|
+
request.sampleRate ?? 22050,
|
|
518
|
+
request.maxPoints ?? 0,
|
|
519
|
+
);
|
|
293
520
|
}
|
|
294
521
|
|
|
295
522
|
/**
|
|
296
|
-
* Display-sized phase scope.
|
|
297
|
-
*
|
|
298
|
-
*
|
|
299
|
-
*
|
|
300
|
-
*
|
|
523
|
+
* Display-sized phase scope.
|
|
524
|
+
*
|
|
525
|
+
* @deprecated Pass `maxPoints` to {@link meteringPhaseScope} instead; it now
|
|
526
|
+
* folds `maxPoints` into the request, matching the Node surface. This alias is
|
|
527
|
+
* kept for backward compatibility and simply delegates.
|
|
301
528
|
*/
|
|
529
|
+
export function meteringPhaseScopeDecimated(
|
|
530
|
+
request: MeteringStereoDecimatedRequest,
|
|
531
|
+
): PhaseScopeReport;
|
|
302
532
|
export function meteringPhaseScopeDecimated(
|
|
303
533
|
left: Float32Array,
|
|
304
534
|
right: Float32Array,
|
|
535
|
+
sampleRate?: number,
|
|
536
|
+
maxPoints?: number,
|
|
537
|
+
options?: ValidateOptions,
|
|
538
|
+
): PhaseScopeReport;
|
|
539
|
+
export function meteringPhaseScopeDecimated(
|
|
540
|
+
left: Float32Array | MeteringStereoDecimatedRequest,
|
|
541
|
+
right?: Float32Array,
|
|
305
542
|
sampleRate = 22050,
|
|
306
543
|
maxPoints = 0,
|
|
307
544
|
options: ValidateOptions = {},
|
|
308
545
|
): PhaseScopeReport {
|
|
309
|
-
const
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
546
|
+
const request =
|
|
547
|
+
left instanceof Float32Array
|
|
548
|
+
? { left, right: right as Float32Array, sampleRate, maxPoints, ...options }
|
|
549
|
+
: left;
|
|
550
|
+
const validate = request.validate !== false;
|
|
551
|
+
assertSamples('meteringPhaseScopeDecimated', request.left, validate, 'left');
|
|
552
|
+
assertSamples('meteringPhaseScopeDecimated', request.right, validate, 'right');
|
|
553
|
+
return requireModule().meteringPhaseScopeDecimated(
|
|
554
|
+
request.left,
|
|
555
|
+
request.right,
|
|
556
|
+
request.sampleRate ?? 22050,
|
|
557
|
+
request.maxPoints ?? 0,
|
|
558
|
+
);
|
|
313
559
|
}
|
|
314
560
|
|
|
315
561
|
/**
|
|
@@ -318,14 +564,20 @@ export function meteringPhaseScopeDecimated(
|
|
|
318
564
|
* are averaged). For a true single-frame snapshot, use
|
|
319
565
|
* {@link meteringSpectrumFrame}.
|
|
320
566
|
*/
|
|
567
|
+
export function meteringSpectrum(request: MeteringSpectrumRequest): SpectrumReport;
|
|
321
568
|
export function meteringSpectrum(
|
|
322
569
|
samples: Float32Array,
|
|
323
|
-
sampleRate
|
|
570
|
+
sampleRate?: number,
|
|
324
571
|
options?: SpectrumOptions & ValidateOptions,
|
|
572
|
+
): SpectrumReport;
|
|
573
|
+
export function meteringSpectrum(
|
|
574
|
+
samples: Float32Array | MeteringSpectrumRequest,
|
|
575
|
+
sampleRate = 22050,
|
|
576
|
+
options: SpectrumOptions & ValidateOptions = {},
|
|
325
577
|
): SpectrumReport {
|
|
326
|
-
const
|
|
327
|
-
assertSamples('meteringSpectrum', samples, validate);
|
|
328
|
-
return requireModule().meteringSpectrum(samples, sampleRate
|
|
578
|
+
const request = samples instanceof Float32Array ? { samples, sampleRate, ...options } : samples;
|
|
579
|
+
assertSamples('meteringSpectrum', request.samples, request.validate !== false);
|
|
580
|
+
return requireModule().meteringSpectrum(request.samples, request.sampleRate ?? 22050, request);
|
|
329
581
|
}
|
|
330
582
|
|
|
331
583
|
/**
|
|
@@ -334,47 +586,80 @@ export function meteringSpectrum(
|
|
|
334
586
|
* time-averaged like {@link meteringSpectrum}. The analysis frame spans
|
|
335
587
|
* `[frameOffset, frameOffset + nFft)`; samples past the end are zero-padded.
|
|
336
588
|
*/
|
|
589
|
+
export function meteringSpectrumFrame(request: MeteringSpectrumFrameRequest): SpectrumReport;
|
|
337
590
|
export function meteringSpectrumFrame(
|
|
338
591
|
samples: Float32Array,
|
|
592
|
+
sampleRate?: number,
|
|
593
|
+
frameOffset?: number,
|
|
594
|
+
options?: SpectrumOptions & ValidateOptions,
|
|
595
|
+
): SpectrumReport;
|
|
596
|
+
export function meteringSpectrumFrame(
|
|
597
|
+
samples: Float32Array | MeteringSpectrumFrameRequest,
|
|
339
598
|
sampleRate = 22050,
|
|
340
599
|
frameOffset = 0,
|
|
341
|
-
options
|
|
600
|
+
options: SpectrumOptions & ValidateOptions = {},
|
|
342
601
|
): SpectrumReport {
|
|
343
|
-
const
|
|
344
|
-
|
|
345
|
-
|
|
602
|
+
const request =
|
|
603
|
+
samples instanceof Float32Array ? { samples, sampleRate, frameOffset, ...options } : samples;
|
|
604
|
+
assertSamples('meteringSpectrumFrame', request.samples, request.validate !== false);
|
|
605
|
+
return requireModule().meteringSpectrumFrame(
|
|
606
|
+
request.samples,
|
|
607
|
+
request.sampleRate ?? 22050,
|
|
608
|
+
request.frameOffset ?? 0,
|
|
609
|
+
request,
|
|
610
|
+
);
|
|
346
611
|
}
|
|
347
612
|
|
|
348
613
|
/** Compute per-channel min/max waveform buckets from interleaved audio. */
|
|
614
|
+
export function waveformPeaks(request: WaveformPeaksRequest): WaveformPeaksReport;
|
|
349
615
|
export function waveformPeaks(
|
|
350
616
|
samples: Float32Array,
|
|
351
617
|
channels: number,
|
|
618
|
+
options?: WaveformPeaksOptions,
|
|
619
|
+
): WaveformPeaksReport;
|
|
620
|
+
export function waveformPeaks(
|
|
621
|
+
samples: Float32Array | WaveformPeaksRequest,
|
|
622
|
+
channels?: number,
|
|
352
623
|
options: WaveformPeaksOptions = {},
|
|
353
624
|
): WaveformPeaksReport {
|
|
354
|
-
|
|
355
|
-
|
|
625
|
+
const request =
|
|
626
|
+
samples instanceof Float32Array
|
|
627
|
+
? { samples, channels: channels as number, ...options }
|
|
628
|
+
: samples;
|
|
629
|
+
assertSamples('waveformPeaks', request.samples, request.validate !== false);
|
|
630
|
+
if (request.channels <= 0 || request.samples.length % request.channels !== 0) {
|
|
356
631
|
throw new RangeError('waveformPeaks: samples length must be a multiple of channels');
|
|
357
632
|
}
|
|
358
|
-
const samplesPerBucket =
|
|
633
|
+
const samplesPerBucket = request.samplesPerBucket ?? 512;
|
|
359
634
|
if (samplesPerBucket <= 0) {
|
|
360
635
|
throw new RangeError('waveformPeaks: samplesPerBucket must be > 0');
|
|
361
636
|
}
|
|
362
|
-
return requireModule().waveformPeaks(samples, channels, samplesPerBucket);
|
|
637
|
+
return requireModule().waveformPeaks(request.samples, request.channels, samplesPerBucket);
|
|
363
638
|
}
|
|
364
639
|
|
|
365
640
|
/** Compute waveform peak buckets for several zoom levels. */
|
|
641
|
+
export function waveformPeakPyramid(request: WaveformPeakPyramidRequest): WaveformPeaksReport[];
|
|
366
642
|
export function waveformPeakPyramid(
|
|
367
643
|
samples: Float32Array,
|
|
368
644
|
channels: number,
|
|
645
|
+
options?: WaveformPeakPyramidOptions,
|
|
646
|
+
): WaveformPeaksReport[];
|
|
647
|
+
export function waveformPeakPyramid(
|
|
648
|
+
samples: Float32Array | WaveformPeakPyramidRequest,
|
|
649
|
+
channels?: number,
|
|
369
650
|
options: WaveformPeakPyramidOptions = {},
|
|
370
651
|
): WaveformPeaksReport[] {
|
|
371
|
-
|
|
372
|
-
|
|
652
|
+
const request =
|
|
653
|
+
samples instanceof Float32Array
|
|
654
|
+
? { samples, channels: channels as number, ...options }
|
|
655
|
+
: samples;
|
|
656
|
+
assertSamples('waveformPeakPyramid', request.samples, request.validate !== false);
|
|
657
|
+
if (request.channels <= 0 || request.samples.length % request.channels !== 0) {
|
|
373
658
|
throw new RangeError('waveformPeakPyramid: samples length must be a multiple of channels');
|
|
374
659
|
}
|
|
375
|
-
const levels =
|
|
660
|
+
const levels = request.samplesPerBucketLevels ?? [512, 1024, 2048, 4096];
|
|
376
661
|
if (levels.length === 0 || levels.some((level) => level <= 0)) {
|
|
377
662
|
throw new RangeError('waveformPeakPyramid: samplesPerBucketLevels must be non-empty and > 0');
|
|
378
663
|
}
|
|
379
|
-
return requireModule().waveformPeakPyramid(samples, channels, levels);
|
|
664
|
+
return requireModule().waveformPeakPyramid(request.samples, request.channels, levels);
|
|
380
665
|
}
|