@libraz/libsonare 1.1.0 → 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +164 -2
- package/dist/index.d.ts +1162 -18
- package/dist/index.js +1167 -14
- package/dist/index.js.map +1 -1
- package/dist/sonare-rt-module.js +2 -0
- package/dist/sonare-rt.js +2 -0
- package/dist/sonare-rt.wasm +0 -0
- package/dist/sonare.js +1 -1
- package/dist/sonare.wasm +0 -0
- package/dist/worklet.d.ts +447 -0
- package/dist/worklet.js +2078 -0
- package/dist/worklet.js.map +1 -0
- package/package.json +14 -4
- package/src/index.ts +1960 -63
- package/src/public_types.ts +461 -0
- package/src/sonare-rt.d.ts +93 -0
- package/src/sonare.js.d.ts +723 -2
- package/src/stream_types.ts +35 -0
- package/src/wasm_types.ts +706 -2
- package/src/worklet.ts +2140 -0
package/dist/index.js
CHANGED
|
@@ -15,7 +15,21 @@ var PitchClass = {
|
|
|
15
15
|
};
|
|
16
16
|
var Mode = {
|
|
17
17
|
Major: 0,
|
|
18
|
-
Minor: 1
|
|
18
|
+
Minor: 1,
|
|
19
|
+
Dorian: 2,
|
|
20
|
+
Phrygian: 3,
|
|
21
|
+
Lydian: 4,
|
|
22
|
+
Mixolydian: 5,
|
|
23
|
+
Locrian: 6
|
|
24
|
+
};
|
|
25
|
+
var KeyProfile = {
|
|
26
|
+
KrumhanslSchmuckler: 0,
|
|
27
|
+
Temperley: 1,
|
|
28
|
+
Shaath: 2,
|
|
29
|
+
FaraldoEDMT: 3,
|
|
30
|
+
FaraldoEDMA: 4,
|
|
31
|
+
FaraldoEDMM: 5,
|
|
32
|
+
BellmanBudge: 6
|
|
19
33
|
};
|
|
20
34
|
var ChordQuality = {
|
|
21
35
|
Major: 0,
|
|
@@ -26,7 +40,15 @@ var ChordQuality = {
|
|
|
26
40
|
Major7: 5,
|
|
27
41
|
Minor7: 6,
|
|
28
42
|
Sus2: 7,
|
|
29
|
-
Sus4: 8
|
|
43
|
+
Sus4: 8,
|
|
44
|
+
Unknown: 9,
|
|
45
|
+
Add9: 10,
|
|
46
|
+
MinorAdd9: 11,
|
|
47
|
+
Dim7: 12,
|
|
48
|
+
HalfDim7: 13,
|
|
49
|
+
Major9: 14,
|
|
50
|
+
Dominant9: 15,
|
|
51
|
+
Sus2Add4: 16
|
|
30
52
|
};
|
|
31
53
|
var SectionType = {
|
|
32
54
|
Intro: 0,
|
|
@@ -35,10 +57,47 @@ var SectionType = {
|
|
|
35
57
|
Chorus: 3,
|
|
36
58
|
Bridge: 4,
|
|
37
59
|
Instrumental: 5,
|
|
38
|
-
Outro: 6
|
|
60
|
+
Outro: 6,
|
|
61
|
+
Unknown: 7
|
|
39
62
|
};
|
|
40
63
|
|
|
41
64
|
// src/index.ts
|
|
65
|
+
var EXPECTED_ENGINE_ABI_VERSION = 2;
|
|
66
|
+
function automationCurveCode(curve) {
|
|
67
|
+
switch (curve) {
|
|
68
|
+
case "linear":
|
|
69
|
+
return 0;
|
|
70
|
+
case "exponential":
|
|
71
|
+
return 1;
|
|
72
|
+
case "hold":
|
|
73
|
+
return 2;
|
|
74
|
+
case "s-curve":
|
|
75
|
+
return 3;
|
|
76
|
+
default:
|
|
77
|
+
throw new Error(`Invalid automation curve: ${curve}`);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
function panLawCode(panLaw) {
|
|
81
|
+
if (typeof panLaw === "number") {
|
|
82
|
+
return panLaw;
|
|
83
|
+
}
|
|
84
|
+
switch (panLaw) {
|
|
85
|
+
case "const4.5dB":
|
|
86
|
+
return 1;
|
|
87
|
+
case "const6dB":
|
|
88
|
+
return 2;
|
|
89
|
+
case "linear0dB":
|
|
90
|
+
return 3;
|
|
91
|
+
default:
|
|
92
|
+
return 0;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
function meterTapCode(tap) {
|
|
96
|
+
return tap === "preFader" || tap === 0 ? 0 : 1;
|
|
97
|
+
}
|
|
98
|
+
function sendTimingCode(timing) {
|
|
99
|
+
return timing === "preFader" || timing === 0 ? 0 : 1;
|
|
100
|
+
}
|
|
42
101
|
var module = null;
|
|
43
102
|
var initPromise = null;
|
|
44
103
|
async function init(options) {
|
|
@@ -68,17 +127,206 @@ function version() {
|
|
|
68
127
|
}
|
|
69
128
|
return module.version();
|
|
70
129
|
}
|
|
130
|
+
function engineAbiVersion() {
|
|
131
|
+
if (!module) {
|
|
132
|
+
throw new Error("Module not initialized. Call init() first.");
|
|
133
|
+
}
|
|
134
|
+
return module.engineAbiVersion();
|
|
135
|
+
}
|
|
136
|
+
function engineCapabilities() {
|
|
137
|
+
const abiVersion = engineAbiVersion();
|
|
138
|
+
const sharedArrayBuffer = typeof globalThis.SharedArrayBuffer === "function";
|
|
139
|
+
const atomics = typeof globalThis.Atomics === "object";
|
|
140
|
+
const audioWorklet = typeof AudioWorkletNode !== "undefined" || typeof globalThis.AudioWorkletProcessor !== "undefined";
|
|
141
|
+
return {
|
|
142
|
+
engineAbiVersion: abiVersion,
|
|
143
|
+
expectedEngineAbiVersion: EXPECTED_ENGINE_ABI_VERSION,
|
|
144
|
+
abiCompatible: abiVersion === EXPECTED_ENGINE_ABI_VERSION,
|
|
145
|
+
sharedArrayBuffer,
|
|
146
|
+
atomics,
|
|
147
|
+
audioWorklet,
|
|
148
|
+
mode: sharedArrayBuffer && atomics ? "sab" : "postMessage"
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
var RealtimeEngine = class {
|
|
152
|
+
constructor(sampleRate = 48e3, maxBlockSize = 128, commandCapacity = 1024, telemetryCapacity = 1024) {
|
|
153
|
+
if (!module) {
|
|
154
|
+
throw new Error("Module not initialized. Call init() first.");
|
|
155
|
+
}
|
|
156
|
+
const capabilities = engineCapabilities();
|
|
157
|
+
if (!capabilities.abiCompatible) {
|
|
158
|
+
throw new Error(
|
|
159
|
+
`Engine ABI mismatch: wasm=${capabilities.engineAbiVersion}, expected=${capabilities.expectedEngineAbiVersion}`
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
this.native = new module.RealtimeEngine(
|
|
163
|
+
sampleRate,
|
|
164
|
+
maxBlockSize,
|
|
165
|
+
commandCapacity,
|
|
166
|
+
telemetryCapacity
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
prepare(sampleRate, maxBlockSize, commandCapacity = 1024, telemetryCapacity = 1024) {
|
|
170
|
+
this.native.prepare(sampleRate, maxBlockSize, commandCapacity, telemetryCapacity);
|
|
171
|
+
}
|
|
172
|
+
/** Queue a sample-accurate parameter change (engine kSetParam). */
|
|
173
|
+
setParameter(paramId, value, renderFrame = -1) {
|
|
174
|
+
this.native.setParameter(paramId, value, renderFrame);
|
|
175
|
+
}
|
|
176
|
+
/** Queue a smoothed parameter change (engine kSetParamSmoothed). */
|
|
177
|
+
setParameterSmoothed(paramId, value, renderFrame = -1) {
|
|
178
|
+
this.native.setParameterSmoothed(paramId, value, renderFrame);
|
|
179
|
+
}
|
|
180
|
+
/** Read back the current transport state snapshot. */
|
|
181
|
+
getTransportState() {
|
|
182
|
+
return this.native.getTransportState();
|
|
183
|
+
}
|
|
184
|
+
play(renderFrame = -1) {
|
|
185
|
+
this.native.play(renderFrame);
|
|
186
|
+
}
|
|
187
|
+
stop(renderFrame = -1) {
|
|
188
|
+
this.native.stop(renderFrame);
|
|
189
|
+
}
|
|
190
|
+
seekSample(timelineSample, renderFrame = -1) {
|
|
191
|
+
this.native.seekSample(timelineSample, renderFrame);
|
|
192
|
+
}
|
|
193
|
+
seekPpq(ppq, renderFrame = -1) {
|
|
194
|
+
this.native.seekPpq(ppq, renderFrame);
|
|
195
|
+
}
|
|
196
|
+
setTempo(bpm) {
|
|
197
|
+
this.native.setTempo(bpm);
|
|
198
|
+
}
|
|
199
|
+
setTimeSignature(numerator, denominator) {
|
|
200
|
+
this.native.setTimeSignature(numerator, denominator);
|
|
201
|
+
}
|
|
202
|
+
setLoop(startPpq, endPpq, enabled = true) {
|
|
203
|
+
this.native.setLoop(startPpq, endPpq, enabled);
|
|
204
|
+
}
|
|
205
|
+
addParameter(info) {
|
|
206
|
+
this.native.addParameter(info);
|
|
207
|
+
}
|
|
208
|
+
parameterCount() {
|
|
209
|
+
return this.native.parameterCount();
|
|
210
|
+
}
|
|
211
|
+
parameterInfoByIndex(index) {
|
|
212
|
+
return this.native.parameterInfoByIndex(index);
|
|
213
|
+
}
|
|
214
|
+
parameterInfo(id) {
|
|
215
|
+
return this.native.parameterInfo(id);
|
|
216
|
+
}
|
|
217
|
+
setAutomationLane(paramId, points) {
|
|
218
|
+
this.native.setAutomationLane(paramId, points);
|
|
219
|
+
}
|
|
220
|
+
automationLaneCount() {
|
|
221
|
+
return this.native.automationLaneCount();
|
|
222
|
+
}
|
|
223
|
+
setMarkers(markers) {
|
|
224
|
+
this.native.setMarkers(markers);
|
|
225
|
+
}
|
|
226
|
+
markerCount() {
|
|
227
|
+
return this.native.markerCount();
|
|
228
|
+
}
|
|
229
|
+
markerByIndex(index) {
|
|
230
|
+
return this.native.markerByIndex(index);
|
|
231
|
+
}
|
|
232
|
+
marker(id) {
|
|
233
|
+
return this.native.marker(id);
|
|
234
|
+
}
|
|
235
|
+
seekMarker(markerId, renderFrame = -1) {
|
|
236
|
+
this.native.seekMarker(markerId, renderFrame);
|
|
237
|
+
}
|
|
238
|
+
setLoopFromMarkers(startMarkerId, endMarkerId) {
|
|
239
|
+
this.native.setLoopFromMarkers(startMarkerId, endMarkerId);
|
|
240
|
+
}
|
|
241
|
+
setMetronome(config) {
|
|
242
|
+
this.native.setMetronome(config);
|
|
243
|
+
}
|
|
244
|
+
metronome() {
|
|
245
|
+
return this.native.metronome();
|
|
246
|
+
}
|
|
247
|
+
countInEndSample(startSample, bars) {
|
|
248
|
+
return Number(this.native.countInEndSample(startSample, bars));
|
|
249
|
+
}
|
|
250
|
+
setGraph(spec) {
|
|
251
|
+
this.native.setGraph(spec);
|
|
252
|
+
}
|
|
253
|
+
graphNodeCount() {
|
|
254
|
+
return this.native.graphNodeCount();
|
|
255
|
+
}
|
|
256
|
+
graphConnectionCount() {
|
|
257
|
+
return this.native.graphConnectionCount();
|
|
258
|
+
}
|
|
259
|
+
setClips(clips) {
|
|
260
|
+
this.native.setClips(clips);
|
|
261
|
+
}
|
|
262
|
+
clipCount() {
|
|
263
|
+
return this.native.clipCount();
|
|
264
|
+
}
|
|
265
|
+
setCaptureBuffer(numChannels, capacityFrames) {
|
|
266
|
+
this.native.setCaptureBuffer(numChannels, capacityFrames);
|
|
267
|
+
}
|
|
268
|
+
armCapture(armed = true) {
|
|
269
|
+
this.native.armCapture(armed);
|
|
270
|
+
}
|
|
271
|
+
setCapturePunch(startSample, endSample, enabled = true) {
|
|
272
|
+
this.native.setCapturePunch(startSample, endSample, enabled);
|
|
273
|
+
}
|
|
274
|
+
resetCapture() {
|
|
275
|
+
this.native.resetCapture();
|
|
276
|
+
}
|
|
277
|
+
captureStatus() {
|
|
278
|
+
return this.native.captureStatus();
|
|
279
|
+
}
|
|
280
|
+
capturedAudio() {
|
|
281
|
+
return this.native.capturedAudio();
|
|
282
|
+
}
|
|
283
|
+
process(channels) {
|
|
284
|
+
return this.native.process(channels);
|
|
285
|
+
}
|
|
286
|
+
processWithMonitor(channels) {
|
|
287
|
+
return this.native.processWithMonitor(channels);
|
|
288
|
+
}
|
|
289
|
+
renderOffline(channels, blockSize = 128) {
|
|
290
|
+
return this.native.renderOffline(channels, blockSize);
|
|
291
|
+
}
|
|
292
|
+
bounceOffline(options) {
|
|
293
|
+
return this.native.bounceOffline(options);
|
|
294
|
+
}
|
|
295
|
+
freezeOffline(options) {
|
|
296
|
+
return this.native.freezeOffline(options);
|
|
297
|
+
}
|
|
298
|
+
drainTelemetry(maxRecords = 1024) {
|
|
299
|
+
return this.native.drainTelemetry(maxRecords);
|
|
300
|
+
}
|
|
301
|
+
drainMeterTelemetry(maxRecords = 1024) {
|
|
302
|
+
return this.native.drainMeterTelemetry(maxRecords);
|
|
303
|
+
}
|
|
304
|
+
destroy() {
|
|
305
|
+
this.native.delete();
|
|
306
|
+
}
|
|
307
|
+
};
|
|
71
308
|
function detectBpm(samples, sampleRate) {
|
|
72
309
|
if (!module) {
|
|
73
310
|
throw new Error("Module not initialized. Call init() first.");
|
|
74
311
|
}
|
|
75
312
|
return module.detectBpm(samples, sampleRate);
|
|
76
313
|
}
|
|
77
|
-
function detectKey(samples, sampleRate) {
|
|
314
|
+
function detectKey(samples, sampleRate, options = {}) {
|
|
78
315
|
if (!module) {
|
|
79
316
|
throw new Error("Module not initialized. Call init() first.");
|
|
80
317
|
}
|
|
81
|
-
const result = module.
|
|
318
|
+
const result = module._detectKeyWithOptions(
|
|
319
|
+
samples,
|
|
320
|
+
sampleRate,
|
|
321
|
+
options.nFft ?? 4096,
|
|
322
|
+
options.hopLength ?? 512,
|
|
323
|
+
options.useHpss ?? false,
|
|
324
|
+
options.loudnessWeighted ?? false,
|
|
325
|
+
options.highPassHz ?? 0,
|
|
326
|
+
keyModeValues(options.modes),
|
|
327
|
+
keyProfileValue(options.profile),
|
|
328
|
+
options.genreHint ?? ""
|
|
329
|
+
);
|
|
82
330
|
return {
|
|
83
331
|
root: result.root,
|
|
84
332
|
mode: result.mode,
|
|
@@ -87,6 +335,88 @@ function detectKey(samples, sampleRate) {
|
|
|
87
335
|
shortName: result.shortName
|
|
88
336
|
};
|
|
89
337
|
}
|
|
338
|
+
function convertKeyCandidate(wasm) {
|
|
339
|
+
return {
|
|
340
|
+
key: {
|
|
341
|
+
root: wasm.key.root,
|
|
342
|
+
mode: wasm.key.mode,
|
|
343
|
+
confidence: wasm.key.confidence,
|
|
344
|
+
name: wasm.key.name,
|
|
345
|
+
shortName: wasm.key.shortName
|
|
346
|
+
},
|
|
347
|
+
correlation: wasm.correlation
|
|
348
|
+
};
|
|
349
|
+
}
|
|
350
|
+
function keyModeValues(modes) {
|
|
351
|
+
if (!modes) {
|
|
352
|
+
return [];
|
|
353
|
+
}
|
|
354
|
+
if (modes === "major-minor") {
|
|
355
|
+
return [Mode.Major, Mode.Minor];
|
|
356
|
+
}
|
|
357
|
+
if (modes === "all" || modes === "modal") {
|
|
358
|
+
return [
|
|
359
|
+
Mode.Major,
|
|
360
|
+
Mode.Minor,
|
|
361
|
+
Mode.Dorian,
|
|
362
|
+
Mode.Phrygian,
|
|
363
|
+
Mode.Lydian,
|
|
364
|
+
Mode.Mixolydian,
|
|
365
|
+
Mode.Locrian
|
|
366
|
+
];
|
|
367
|
+
}
|
|
368
|
+
const names = {
|
|
369
|
+
major: Mode.Major,
|
|
370
|
+
minor: Mode.Minor,
|
|
371
|
+
dorian: Mode.Dorian,
|
|
372
|
+
phrygian: Mode.Phrygian,
|
|
373
|
+
lydian: Mode.Lydian,
|
|
374
|
+
mixolydian: Mode.Mixolydian,
|
|
375
|
+
locrian: Mode.Locrian
|
|
376
|
+
};
|
|
377
|
+
return modes.map((mode) => typeof mode === "number" ? mode : names[mode]);
|
|
378
|
+
}
|
|
379
|
+
function keyProfileValue(profile) {
|
|
380
|
+
if (profile === void 0) {
|
|
381
|
+
return -1;
|
|
382
|
+
}
|
|
383
|
+
if (typeof profile === "number") {
|
|
384
|
+
return profile;
|
|
385
|
+
}
|
|
386
|
+
const names = {
|
|
387
|
+
ks: KeyProfile.KrumhanslSchmuckler,
|
|
388
|
+
krumhansl: KeyProfile.KrumhanslSchmuckler,
|
|
389
|
+
temperley: KeyProfile.Temperley,
|
|
390
|
+
shaath: KeyProfile.Shaath,
|
|
391
|
+
keyfinder: KeyProfile.Shaath,
|
|
392
|
+
"faraldo-edmt": KeyProfile.FaraldoEDMT,
|
|
393
|
+
edmt: KeyProfile.FaraldoEDMT,
|
|
394
|
+
"faraldo-edma": KeyProfile.FaraldoEDMA,
|
|
395
|
+
edma: KeyProfile.FaraldoEDMA,
|
|
396
|
+
"faraldo-edmm": KeyProfile.FaraldoEDMM,
|
|
397
|
+
edmm: KeyProfile.FaraldoEDMM,
|
|
398
|
+
"bellman-budge": KeyProfile.BellmanBudge,
|
|
399
|
+
bellman: KeyProfile.BellmanBudge
|
|
400
|
+
};
|
|
401
|
+
return names[profile];
|
|
402
|
+
}
|
|
403
|
+
function detectKeyCandidates(samples, sampleRate, options = {}) {
|
|
404
|
+
if (!module) {
|
|
405
|
+
throw new Error("Module not initialized. Call init() first.");
|
|
406
|
+
}
|
|
407
|
+
return module._detectKeyCandidates(
|
|
408
|
+
samples,
|
|
409
|
+
sampleRate,
|
|
410
|
+
options.nFft ?? 4096,
|
|
411
|
+
options.hopLength ?? 512,
|
|
412
|
+
options.useHpss ?? false,
|
|
413
|
+
options.loudnessWeighted ?? false,
|
|
414
|
+
options.highPassHz ?? 0,
|
|
415
|
+
keyModeValues(options.modes),
|
|
416
|
+
keyProfileValue(options.profile),
|
|
417
|
+
options.genreHint ?? ""
|
|
418
|
+
).map(convertKeyCandidate);
|
|
419
|
+
}
|
|
90
420
|
function detectOnsets(samples, sampleRate) {
|
|
91
421
|
if (!module) {
|
|
92
422
|
throw new Error("Module not initialized. Call init() first.");
|
|
@@ -99,6 +429,58 @@ function detectBeats(samples, sampleRate) {
|
|
|
99
429
|
}
|
|
100
430
|
return module.detectBeats(samples, sampleRate);
|
|
101
431
|
}
|
|
432
|
+
function detectDownbeats(samples, sampleRate) {
|
|
433
|
+
if (!module) {
|
|
434
|
+
throw new Error("Module not initialized. Call init() first.");
|
|
435
|
+
}
|
|
436
|
+
return module.detectDownbeats(samples, sampleRate);
|
|
437
|
+
}
|
|
438
|
+
function convertChordAnalysisResult(wasm) {
|
|
439
|
+
return {
|
|
440
|
+
chords: wasm.chords.map((c) => ({
|
|
441
|
+
root: c.root,
|
|
442
|
+
bass: c.bass,
|
|
443
|
+
quality: c.quality,
|
|
444
|
+
start: c.start,
|
|
445
|
+
end: c.end,
|
|
446
|
+
confidence: c.confidence,
|
|
447
|
+
name: c.name
|
|
448
|
+
}))
|
|
449
|
+
};
|
|
450
|
+
}
|
|
451
|
+
function detectChords(samples, sampleRate, options = {}) {
|
|
452
|
+
if (!module) {
|
|
453
|
+
throw new Error("Module not initialized. Call init() first.");
|
|
454
|
+
}
|
|
455
|
+
const result = module.detectChords(
|
|
456
|
+
samples,
|
|
457
|
+
sampleRate,
|
|
458
|
+
options.minDuration ?? 0.3,
|
|
459
|
+
options.smoothingWindow ?? 2,
|
|
460
|
+
options.threshold ?? 0.5,
|
|
461
|
+
options.useTriadsOnly ?? false,
|
|
462
|
+
options.nFft ?? 2048,
|
|
463
|
+
options.hopLength ?? 512,
|
|
464
|
+
options.useBeatSync ?? true,
|
|
465
|
+
options.useHmm ?? false,
|
|
466
|
+
options.hmmBeamWidth ?? 24,
|
|
467
|
+
options.useKeyContext ?? false,
|
|
468
|
+
options.keyRoot ?? PitchClass.C,
|
|
469
|
+
options.keyMode ?? Mode.Major,
|
|
470
|
+
options.detectInversions ?? false,
|
|
471
|
+
chordChromaMethodValue(options.chromaMethod ?? "stft")
|
|
472
|
+
);
|
|
473
|
+
return convertChordAnalysisResult(result);
|
|
474
|
+
}
|
|
475
|
+
function chordChromaMethodValue(method) {
|
|
476
|
+
if (method === "stft") {
|
|
477
|
+
return 0;
|
|
478
|
+
}
|
|
479
|
+
if (method === "nnls") {
|
|
480
|
+
return 1;
|
|
481
|
+
}
|
|
482
|
+
throw new Error(`Invalid chord chroma method: ${method}`);
|
|
483
|
+
}
|
|
102
484
|
function convertAnalysisResult(wasm) {
|
|
103
485
|
const beatTimes = new Float32Array(wasm.beats.length);
|
|
104
486
|
for (let i = 0; i < wasm.beats.length; i++) {
|
|
@@ -119,6 +501,7 @@ function convertAnalysisResult(wasm) {
|
|
|
119
501
|
beats: wasm.beats,
|
|
120
502
|
chords: wasm.chords.map((c) => ({
|
|
121
503
|
root: c.root,
|
|
504
|
+
bass: c.bass,
|
|
122
505
|
quality: c.quality,
|
|
123
506
|
start: c.start,
|
|
124
507
|
end: c.end,
|
|
@@ -146,6 +529,31 @@ function analyze(samples, sampleRate) {
|
|
|
146
529
|
const result = module.analyze(samples, sampleRate);
|
|
147
530
|
return convertAnalysisResult(result);
|
|
148
531
|
}
|
|
532
|
+
function analyzeImpulseResponse(samples, sampleRate, nOctaveBands = 6) {
|
|
533
|
+
if (!module) {
|
|
534
|
+
throw new Error("Module not initialized. Call init() first.");
|
|
535
|
+
}
|
|
536
|
+
const result = module.analyzeImpulseResponse(
|
|
537
|
+
samples,
|
|
538
|
+
sampleRate,
|
|
539
|
+
nOctaveBands
|
|
540
|
+
);
|
|
541
|
+
return result;
|
|
542
|
+
}
|
|
543
|
+
function detectAcoustic(samples, sampleRate, nOctaveBands = 6, nThirdOctaveSubbands = 24, minDecayDb = 30, noiseFloorMarginDb = 10) {
|
|
544
|
+
if (!module) {
|
|
545
|
+
throw new Error("Module not initialized. Call init() first.");
|
|
546
|
+
}
|
|
547
|
+
const result = module.detectAcoustic(
|
|
548
|
+
samples,
|
|
549
|
+
sampleRate,
|
|
550
|
+
nOctaveBands,
|
|
551
|
+
nThirdOctaveSubbands,
|
|
552
|
+
minDecayDb,
|
|
553
|
+
noiseFloorMarginDb
|
|
554
|
+
);
|
|
555
|
+
return result;
|
|
556
|
+
}
|
|
149
557
|
function analyzeWithProgress(samples, sampleRate, onProgress) {
|
|
150
558
|
if (!module) {
|
|
151
559
|
throw new Error("Module not initialized. Call init() first.");
|
|
@@ -183,6 +591,24 @@ function pitchShift(samples, sampleRate, semitones) {
|
|
|
183
591
|
}
|
|
184
592
|
return module.pitchShift(samples, sampleRate, semitones);
|
|
185
593
|
}
|
|
594
|
+
function pitchCorrectToMidi(samples, sampleRate, currentMidi, targetMidi) {
|
|
595
|
+
if (!module) {
|
|
596
|
+
throw new Error("Module not initialized. Call init() first.");
|
|
597
|
+
}
|
|
598
|
+
return module.pitchCorrectToMidi(samples, sampleRate, currentMidi, targetMidi);
|
|
599
|
+
}
|
|
600
|
+
function noteStretch(samples, sampleRate, onsetSample, offsetSample, stretchRatio) {
|
|
601
|
+
if (!module) {
|
|
602
|
+
throw new Error("Module not initialized. Call init() first.");
|
|
603
|
+
}
|
|
604
|
+
return module.noteStretch(samples, sampleRate, onsetSample, offsetSample, stretchRatio);
|
|
605
|
+
}
|
|
606
|
+
function voiceChange(samples, sampleRate, pitchSemitones, formantFactor) {
|
|
607
|
+
if (!module) {
|
|
608
|
+
throw new Error("Module not initialized. Call init() first.");
|
|
609
|
+
}
|
|
610
|
+
return module.voiceChange(samples, sampleRate, pitchSemitones, formantFactor);
|
|
611
|
+
}
|
|
186
612
|
function normalize(samples, sampleRate, targetDb = 0) {
|
|
187
613
|
if (!module) {
|
|
188
614
|
throw new Error("Module not initialized. Call init() first.");
|
|
@@ -252,6 +678,24 @@ function masteringStereoAnalyze(analysisName, left, right, sampleRate, params =
|
|
|
252
678
|
}
|
|
253
679
|
return module.masteringStereoAnalyze(analysisName, left, right, sampleRate, params);
|
|
254
680
|
}
|
|
681
|
+
function masteringAssistantSuggest(samples, sampleRate, params = {}) {
|
|
682
|
+
if (!module) {
|
|
683
|
+
throw new Error("Module not initialized. Call init() first.");
|
|
684
|
+
}
|
|
685
|
+
return module.masteringAssistantSuggest(samples, sampleRate, params);
|
|
686
|
+
}
|
|
687
|
+
function masteringAudioProfile(samples, sampleRate, params = {}) {
|
|
688
|
+
if (!module) {
|
|
689
|
+
throw new Error("Module not initialized. Call init() first.");
|
|
690
|
+
}
|
|
691
|
+
return module.masteringAudioProfile(samples, sampleRate, params);
|
|
692
|
+
}
|
|
693
|
+
function masteringStreamingPreview(samples, sampleRate, platforms = []) {
|
|
694
|
+
if (!module) {
|
|
695
|
+
throw new Error("Module not initialized. Call init() first.");
|
|
696
|
+
}
|
|
697
|
+
return module.masteringStreamingPreview(samples, sampleRate, platforms);
|
|
698
|
+
}
|
|
255
699
|
function masteringChain(samples, sampleRate, config) {
|
|
256
700
|
if (!module) {
|
|
257
701
|
throw new Error("Module not initialized. Call init() first.");
|
|
@@ -314,6 +758,32 @@ function masterAudioStereo(left, right, sampleRate, presetName, overrides = null
|
|
|
314
758
|
}
|
|
315
759
|
return module.masterAudioStereo(presetName, left, right, sampleRate, overrides);
|
|
316
760
|
}
|
|
761
|
+
function mixingScenePresetNames() {
|
|
762
|
+
if (!module) {
|
|
763
|
+
throw new Error("Module not initialized. Call init() first.");
|
|
764
|
+
}
|
|
765
|
+
return module.mixingScenePresetNames();
|
|
766
|
+
}
|
|
767
|
+
function mixingScenePresetJson(preset) {
|
|
768
|
+
if (!module) {
|
|
769
|
+
throw new Error("Module not initialized. Call init() first.");
|
|
770
|
+
}
|
|
771
|
+
return module.mixingScenePresetJson(preset);
|
|
772
|
+
}
|
|
773
|
+
function mixStereo(leftChannels, rightChannels, sampleRate = 48e3, options = {}) {
|
|
774
|
+
if (!module) {
|
|
775
|
+
throw new Error("Module not initialized. Call init() first.");
|
|
776
|
+
}
|
|
777
|
+
if (leftChannels.length === 0 || leftChannels.length !== rightChannels.length) {
|
|
778
|
+
throw new Error("leftChannels and rightChannels must have the same non-zero length.");
|
|
779
|
+
}
|
|
780
|
+
return module.mixStereo(
|
|
781
|
+
leftChannels,
|
|
782
|
+
rightChannels,
|
|
783
|
+
sampleRate,
|
|
784
|
+
options
|
|
785
|
+
);
|
|
786
|
+
}
|
|
317
787
|
var StreamingMasteringChain = class {
|
|
318
788
|
constructor(config) {
|
|
319
789
|
if (!module) {
|
|
@@ -363,6 +833,445 @@ var StreamingMasteringChain = class {
|
|
|
363
833
|
this.chain.delete();
|
|
364
834
|
}
|
|
365
835
|
};
|
|
836
|
+
var StreamingEqualizer = class {
|
|
837
|
+
constructor(config = {}) {
|
|
838
|
+
if (!module) {
|
|
839
|
+
throw new Error("Module not initialized. Call init() first.");
|
|
840
|
+
}
|
|
841
|
+
this.eq = module.createEqualizer(config);
|
|
842
|
+
}
|
|
843
|
+
/**
|
|
844
|
+
* Configure the band at `index` (0..23). Omitted fields use C++ defaults.
|
|
845
|
+
*/
|
|
846
|
+
setBand(index, band) {
|
|
847
|
+
this.eq.setBand(index, band);
|
|
848
|
+
}
|
|
849
|
+
/** Disable and reset every band. */
|
|
850
|
+
clear() {
|
|
851
|
+
this.eq.clear();
|
|
852
|
+
}
|
|
853
|
+
/**
|
|
854
|
+
* Set the global phase mode: 1=ZeroLatency, 2=NaturalPhase, 3=LinearPhase.
|
|
855
|
+
*/
|
|
856
|
+
setPhaseMode(mode) {
|
|
857
|
+
this.eq.setPhaseMode(mode);
|
|
858
|
+
}
|
|
859
|
+
/** Enable or disable output auto-gain compensation. */
|
|
860
|
+
setAutoGain(enabled) {
|
|
861
|
+
this.eq.setAutoGain(enabled);
|
|
862
|
+
}
|
|
863
|
+
/** Set all-band EQ gain scale as a 0.0..2.0 multiplier. */
|
|
864
|
+
setGainScale(scale) {
|
|
865
|
+
this.eq.setGainScale(scale);
|
|
866
|
+
}
|
|
867
|
+
/** Set post-EQ output gain in dB. */
|
|
868
|
+
setOutputGainDb(gainDb) {
|
|
869
|
+
this.eq.setOutputGainDb(gainDb);
|
|
870
|
+
}
|
|
871
|
+
/** Set post-EQ stereo balance in -1.0..1.0; mono input ignores pan. */
|
|
872
|
+
setOutputPan(pan) {
|
|
873
|
+
this.eq.setOutputPan(pan);
|
|
874
|
+
}
|
|
875
|
+
/**
|
|
876
|
+
* Provide a mono external sidechain key for dynamic bands that opt into
|
|
877
|
+
* `external_sidechain`. The samples are copied into an owned buffer.
|
|
878
|
+
*/
|
|
879
|
+
setSidechainMono(samples) {
|
|
880
|
+
this.eq.setSidechainMono(samples);
|
|
881
|
+
}
|
|
882
|
+
/**
|
|
883
|
+
* Provide a stereo external sidechain key. Both channels must match length.
|
|
884
|
+
*/
|
|
885
|
+
setSidechainStereo(left, right) {
|
|
886
|
+
if (left.length !== right.length) {
|
|
887
|
+
throw new Error("Sidechain channel lengths must match.");
|
|
888
|
+
}
|
|
889
|
+
this.eq.setSidechainStereo(left, right);
|
|
890
|
+
}
|
|
891
|
+
/** Release any borrowed external sidechain buffers. */
|
|
892
|
+
clearSidechain() {
|
|
893
|
+
this.eq.clearSidechain();
|
|
894
|
+
}
|
|
895
|
+
/** Auto-gain applied on the most recent block, in dB. */
|
|
896
|
+
lastAutoGainDb() {
|
|
897
|
+
return this.eq.lastAutoGainDb();
|
|
898
|
+
}
|
|
899
|
+
/** Reported processing latency in samples (non-zero for linear-phase bands). */
|
|
900
|
+
latencySamples() {
|
|
901
|
+
return this.eq.latencySamples();
|
|
902
|
+
}
|
|
903
|
+
/**
|
|
904
|
+
* Process one mono block, returning the equalized samples (same length).
|
|
905
|
+
*/
|
|
906
|
+
processMono(samples) {
|
|
907
|
+
return this.eq.processMono(samples);
|
|
908
|
+
}
|
|
909
|
+
/**
|
|
910
|
+
* Process one stereo block, returning the equalized channels.
|
|
911
|
+
*/
|
|
912
|
+
processStereo(left, right) {
|
|
913
|
+
if (left.length !== right.length) {
|
|
914
|
+
throw new Error("Stereo channel lengths must match.");
|
|
915
|
+
}
|
|
916
|
+
return this.eq.processStereo(left, right);
|
|
917
|
+
}
|
|
918
|
+
/**
|
|
919
|
+
* Read the latest pre/post spectrum snapshot for metering. `seq` increments
|
|
920
|
+
* each time a new snapshot is published.
|
|
921
|
+
*/
|
|
922
|
+
spectrum() {
|
|
923
|
+
return this.eq.spectrum();
|
|
924
|
+
}
|
|
925
|
+
/**
|
|
926
|
+
* Configure bands so the source spectrum matches the reference spectrum.
|
|
927
|
+
*
|
|
928
|
+
* @param source - Source audio (mono samples)
|
|
929
|
+
* @param reference - Reference audio (mono samples)
|
|
930
|
+
* @param options - `sampleRate` (default 48000) and `maxBands` (default 8)
|
|
931
|
+
*/
|
|
932
|
+
match(source, reference, options = {}) {
|
|
933
|
+
this.eq.match(source, reference, options);
|
|
934
|
+
}
|
|
935
|
+
/** Release the underlying WASM object. Safe to call only once. */
|
|
936
|
+
delete() {
|
|
937
|
+
this.eq.delete();
|
|
938
|
+
}
|
|
939
|
+
};
|
|
940
|
+
var StreamingRetune = class {
|
|
941
|
+
constructor(config = {}) {
|
|
942
|
+
if (!module) {
|
|
943
|
+
throw new Error("Module not initialized. Call init() first.");
|
|
944
|
+
}
|
|
945
|
+
this.retune = module.createStreamingRetune(config);
|
|
946
|
+
}
|
|
947
|
+
/**
|
|
948
|
+
* Allocate and initialize native state for the given sample rate and maximum
|
|
949
|
+
* process block size.
|
|
950
|
+
*/
|
|
951
|
+
prepare(sampleRate, maxBlockSize) {
|
|
952
|
+
this.retune.prepare(sampleRate, maxBlockSize);
|
|
953
|
+
}
|
|
954
|
+
/** Reset delay, grain, and overlap-add state without changing config. */
|
|
955
|
+
reset() {
|
|
956
|
+
this.retune.reset();
|
|
957
|
+
}
|
|
958
|
+
/**
|
|
959
|
+
* Update retune settings. Changing `grainSize` takes effect after the next
|
|
960
|
+
* {@link prepare} call.
|
|
961
|
+
*/
|
|
962
|
+
setConfig(config) {
|
|
963
|
+
this.retune.setConfig(config);
|
|
964
|
+
}
|
|
965
|
+
/** Current native config. */
|
|
966
|
+
config() {
|
|
967
|
+
return this.retune.config();
|
|
968
|
+
}
|
|
969
|
+
/** Resolved grain size in samples after {@link prepare}. */
|
|
970
|
+
grainSize() {
|
|
971
|
+
return this.retune.grainSize();
|
|
972
|
+
}
|
|
973
|
+
/** Process one mono block, returning the shifted samples (same length). */
|
|
974
|
+
processMono(samples) {
|
|
975
|
+
return this.retune.processMono(samples);
|
|
976
|
+
}
|
|
977
|
+
/** Release the underlying WASM object. Safe to call only once. */
|
|
978
|
+
delete() {
|
|
979
|
+
this.retune.delete();
|
|
980
|
+
}
|
|
981
|
+
};
|
|
982
|
+
function mixerScenePresetJson(preset) {
|
|
983
|
+
if (!module) {
|
|
984
|
+
throw new Error("Module not initialized. Call init() first.");
|
|
985
|
+
}
|
|
986
|
+
return module.mixerPresetJson(preset);
|
|
987
|
+
}
|
|
988
|
+
var Mixer = class _Mixer {
|
|
989
|
+
constructor(mixer) {
|
|
990
|
+
this.mixer = mixer;
|
|
991
|
+
}
|
|
992
|
+
/**
|
|
993
|
+
* Build a mixer from a scene JSON string.
|
|
994
|
+
*
|
|
995
|
+
* @param json - Scene JSON (strips, buses, sends, connections, inserts)
|
|
996
|
+
* @param sampleRate - Sample rate in Hz (default: 48000)
|
|
997
|
+
* @param blockSize - Maximum block size per {@link processStereo} call (default: 512)
|
|
998
|
+
*/
|
|
999
|
+
static fromSceneJson(json, sampleRate = 48e3, blockSize = 512) {
|
|
1000
|
+
if (!module) {
|
|
1001
|
+
throw new Error("Module not initialized. Call init() first.");
|
|
1002
|
+
}
|
|
1003
|
+
return new _Mixer(module.createMixerFromSceneJson(json, sampleRate, blockSize));
|
|
1004
|
+
}
|
|
1005
|
+
/** Rebuild and compile the routing graph from the current scene topology. */
|
|
1006
|
+
compile() {
|
|
1007
|
+
this.mixer.compile();
|
|
1008
|
+
}
|
|
1009
|
+
/**
|
|
1010
|
+
* Mix one block of per-strip stereo audio into the stereo master.
|
|
1011
|
+
*
|
|
1012
|
+
* @param leftChannels - `leftChannels[i]` is the left channel of strip `i`
|
|
1013
|
+
* @param rightChannels - `rightChannels[i]` is the right channel of strip `i`
|
|
1014
|
+
* @returns Mixed stereo master (`left`, `right`, `sampleRate`)
|
|
1015
|
+
*/
|
|
1016
|
+
processStereo(leftChannels, rightChannels) {
|
|
1017
|
+
if (leftChannels.length !== rightChannels.length) {
|
|
1018
|
+
throw new Error("leftChannels and rightChannels must have the same length.");
|
|
1019
|
+
}
|
|
1020
|
+
return this.mixer.processStereo(leftChannels, rightChannels);
|
|
1021
|
+
}
|
|
1022
|
+
/**
|
|
1023
|
+
* Mix one block into caller-owned output arrays.
|
|
1024
|
+
*
|
|
1025
|
+
* This avoids allocating the result object and result `Float32Array`s. It is
|
|
1026
|
+
* intended for realtime bridges such as AudioWorklet; the input channel count
|
|
1027
|
+
* must match the scene strip count and all arrays must have the same length.
|
|
1028
|
+
*/
|
|
1029
|
+
processStereoInto(leftChannels, rightChannels, outLeft, outRight) {
|
|
1030
|
+
if (leftChannels.length !== rightChannels.length) {
|
|
1031
|
+
throw new Error("leftChannels and rightChannels must have the same length.");
|
|
1032
|
+
}
|
|
1033
|
+
if (outLeft.length !== outRight.length) {
|
|
1034
|
+
throw new Error("outLeft and outRight must have the same length.");
|
|
1035
|
+
}
|
|
1036
|
+
this.mixer.processStereoInto(leftChannels, rightChannels, outLeft, outRight);
|
|
1037
|
+
}
|
|
1038
|
+
/**
|
|
1039
|
+
* Create reusable WASM-heap input/output views for realtime-style processing.
|
|
1040
|
+
*
|
|
1041
|
+
* Fill `leftInputs[i]` / `rightInputs[i]`, call `process()`, then read
|
|
1042
|
+
* `outLeft` / `outRight`. The views are owned by this mixer and become invalid
|
|
1043
|
+
* after {@link delete}.
|
|
1044
|
+
*/
|
|
1045
|
+
createRealtimeBuffer() {
|
|
1046
|
+
const stripCount = this.stripCount();
|
|
1047
|
+
const leftInputs = [];
|
|
1048
|
+
const rightInputs = [];
|
|
1049
|
+
for (let index = 0; index < stripCount; index++) {
|
|
1050
|
+
leftInputs.push(this.mixer.inputLeftView(index));
|
|
1051
|
+
rightInputs.push(this.mixer.inputRightView(index));
|
|
1052
|
+
}
|
|
1053
|
+
const outLeft = this.mixer.outputLeftView();
|
|
1054
|
+
const outRight = this.mixer.outputRightView();
|
|
1055
|
+
return {
|
|
1056
|
+
leftInputs,
|
|
1057
|
+
rightInputs,
|
|
1058
|
+
outLeft,
|
|
1059
|
+
outRight,
|
|
1060
|
+
process: (numSamples = outLeft.length) => this.mixer.processPreparedStereo(numSamples)
|
|
1061
|
+
};
|
|
1062
|
+
}
|
|
1063
|
+
/** Number of strips in the mixer (e.g. strips loaded from the scene). */
|
|
1064
|
+
stripCount() {
|
|
1065
|
+
return this.mixer.stripCount();
|
|
1066
|
+
}
|
|
1067
|
+
/**
|
|
1068
|
+
* Schedule sample-accurate insert-parameter automation on a strip's insert.
|
|
1069
|
+
*
|
|
1070
|
+
* @param stripIndex - Strip index in `[0, stripCount())`
|
|
1071
|
+
* @param insertIndex - Index into the strip's combined insert sequence
|
|
1072
|
+
* (`[pre-inserts... post-inserts...]`)
|
|
1073
|
+
* @param paramId - Processor-specific parameter id
|
|
1074
|
+
* @param samplePos - Absolute samples from the start of processing (the mixer
|
|
1075
|
+
* advances an internal position from 0 on the first {@link processStereo}
|
|
1076
|
+
* call; recompiling resets it to 0)
|
|
1077
|
+
* @param value - Target parameter value
|
|
1078
|
+
* @param curve - Interpolation curve (default: `'linear'`)
|
|
1079
|
+
* @throws If the strip index is out of range or the schedule call fails
|
|
1080
|
+
* (unknown curve, out-of-range insert index, or full event lane)
|
|
1081
|
+
*/
|
|
1082
|
+
scheduleInsertAutomation(stripIndex, insertIndex, paramId, samplePos, value, curve = "linear") {
|
|
1083
|
+
this.mixer.scheduleInsertAutomation(
|
|
1084
|
+
stripIndex,
|
|
1085
|
+
insertIndex,
|
|
1086
|
+
paramId,
|
|
1087
|
+
samplePos,
|
|
1088
|
+
value,
|
|
1089
|
+
automationCurveCode(curve)
|
|
1090
|
+
);
|
|
1091
|
+
}
|
|
1092
|
+
/**
|
|
1093
|
+
* Resolve a strip's index in `[0, stripCount())` from its scene id, or `null`
|
|
1094
|
+
* when no strip with that id exists (matches the Node binding's `number | null`).
|
|
1095
|
+
*/
|
|
1096
|
+
stripById(id) {
|
|
1097
|
+
const index = this.mixer.stripById(id);
|
|
1098
|
+
return index < 0 ? null : index;
|
|
1099
|
+
}
|
|
1100
|
+
/**
|
|
1101
|
+
* Add a bus to the mixer topology. `role` is one of `'master'`, `'aux'`, or
|
|
1102
|
+
* `'submix'` (defaults to `'aux'`). Marks the routing graph dirty; call
|
|
1103
|
+
* {@link compile} (or {@link processStereo}) to rebuild.
|
|
1104
|
+
*/
|
|
1105
|
+
addBus(id, role = "aux") {
|
|
1106
|
+
this.mixer.addBus(id, role);
|
|
1107
|
+
}
|
|
1108
|
+
/** Remove a bus by id. Marks the routing graph dirty. */
|
|
1109
|
+
removeBus(id) {
|
|
1110
|
+
this.mixer.removeBus(id);
|
|
1111
|
+
}
|
|
1112
|
+
/** Number of buses in the mixer topology. */
|
|
1113
|
+
busCount() {
|
|
1114
|
+
return this.mixer.busCount();
|
|
1115
|
+
}
|
|
1116
|
+
/**
|
|
1117
|
+
* Add a VCA group with the given gain offset (dB). `members` is a list of
|
|
1118
|
+
* strip ids governed by the group (may be empty).
|
|
1119
|
+
*/
|
|
1120
|
+
addVcaGroup(id, gainDb = 0, members = []) {
|
|
1121
|
+
this.mixer.addVcaGroup(id, gainDb, members);
|
|
1122
|
+
}
|
|
1123
|
+
/** Remove a VCA group by id. */
|
|
1124
|
+
removeVcaGroup(id) {
|
|
1125
|
+
this.mixer.removeVcaGroup(id);
|
|
1126
|
+
}
|
|
1127
|
+
/** Number of VCA groups in the mixer topology. */
|
|
1128
|
+
vcaGroupCount() {
|
|
1129
|
+
return this.mixer.vcaGroupCount();
|
|
1130
|
+
}
|
|
1131
|
+
/**
|
|
1132
|
+
* Set a strip's solo state. Takes effect on the next process without a
|
|
1133
|
+
* graph recompile.
|
|
1134
|
+
*/
|
|
1135
|
+
setSoloed(stripIndex, soloed) {
|
|
1136
|
+
this.mixer.setSoloed(stripIndex, soloed);
|
|
1137
|
+
}
|
|
1138
|
+
/**
|
|
1139
|
+
* Mark a strip solo-safe so it is never implied-muted by another strip's
|
|
1140
|
+
* solo. Takes effect on the next process without a graph recompile.
|
|
1141
|
+
*/
|
|
1142
|
+
setSoloSafe(stripIndex, soloSafe) {
|
|
1143
|
+
this.mixer.setSoloSafe(stripIndex, soloSafe);
|
|
1144
|
+
}
|
|
1145
|
+
/** Invert the polarity of the left and/or right channel of a strip. */
|
|
1146
|
+
setPolarityInvert(stripIndex, invertLeft, invertRight) {
|
|
1147
|
+
this.mixer.setPolarityInvert(stripIndex, invertLeft, invertRight);
|
|
1148
|
+
}
|
|
1149
|
+
/** Set the strip's pan law. */
|
|
1150
|
+
setPanLaw(stripIndex, panLaw) {
|
|
1151
|
+
this.mixer.setPanLaw(stripIndex, panLawCode(panLaw));
|
|
1152
|
+
}
|
|
1153
|
+
/**
|
|
1154
|
+
* Set a per-strip channel delay in samples. This changes the strip's reported
|
|
1155
|
+
* latency; recompile to re-run latency compensation.
|
|
1156
|
+
*/
|
|
1157
|
+
setChannelDelaySamples(stripIndex, delaySamples) {
|
|
1158
|
+
this.mixer.setChannelDelaySamples(stripIndex, delaySamples);
|
|
1159
|
+
}
|
|
1160
|
+
/** Set the strip's live VCA gain offset in dB (not persisted to the scene). */
|
|
1161
|
+
setVcaOffsetDb(stripIndex, offsetDb) {
|
|
1162
|
+
this.mixer.setVcaOffsetDb(stripIndex, offsetDb);
|
|
1163
|
+
}
|
|
1164
|
+
/** Set independent left/right pan positions (dual-pan mode). */
|
|
1165
|
+
setDualPan(stripIndex, leftPan, rightPan) {
|
|
1166
|
+
this.mixer.setDualPan(stripIndex, leftPan, rightPan);
|
|
1167
|
+
}
|
|
1168
|
+
/**
|
|
1169
|
+
* Add a send to a strip after construction.
|
|
1170
|
+
*
|
|
1171
|
+
* @param stripIndex - Strip index in `[0, stripCount())`
|
|
1172
|
+
* @param id - Send id
|
|
1173
|
+
* @param destinationBusId - Destination bus id
|
|
1174
|
+
* @param sendDb - Initial send level in dB
|
|
1175
|
+
* @param timing - `'preFader'` or `'postFader'` (default: `'postFader'`)
|
|
1176
|
+
* @returns The new send's index
|
|
1177
|
+
*/
|
|
1178
|
+
addSend(stripIndex, id, destinationBusId, sendDb, timing = "postFader") {
|
|
1179
|
+
return this.mixer.addSend(stripIndex, id, destinationBusId, sendDb, sendTimingCode(timing));
|
|
1180
|
+
}
|
|
1181
|
+
/** Set the send level (in dB) for an existing send by index. */
|
|
1182
|
+
setSendDb(stripIndex, sendIndex, sendDb) {
|
|
1183
|
+
this.mixer.setSendDb(stripIndex, sendIndex, sendDb);
|
|
1184
|
+
}
|
|
1185
|
+
/**
|
|
1186
|
+
* Read a strip's meter snapshot at the given tap point.
|
|
1187
|
+
*
|
|
1188
|
+
* @param stripIndex - Strip index in `[0, stripCount())`
|
|
1189
|
+
* @param tap - `'preFader'` or `'postFader'` (default: `'postFader'`)
|
|
1190
|
+
*/
|
|
1191
|
+
meterTap(stripIndex, tap = "postFader") {
|
|
1192
|
+
return this.mixer.meterTap(stripIndex, meterTapCode(tap));
|
|
1193
|
+
}
|
|
1194
|
+
/**
|
|
1195
|
+
* Read a strip's meter snapshot. Alias of {@link meterTap}, provided for
|
|
1196
|
+
* cross-binding (Node/Python) parity.
|
|
1197
|
+
*
|
|
1198
|
+
* @param stripIndex - Strip index in `[0, stripCount())`
|
|
1199
|
+
* @param tap - `'preFader'` or `'postFader'` (default: `'postFader'`)
|
|
1200
|
+
*/
|
|
1201
|
+
stripMeter(stripIndex, tap = "postFader") {
|
|
1202
|
+
return this.mixer.stripMeter(stripIndex, meterTapCode(tap));
|
|
1203
|
+
}
|
|
1204
|
+
/**
|
|
1205
|
+
* Schedule sample-accurate fader automation on a strip.
|
|
1206
|
+
*
|
|
1207
|
+
* @param stripIndex - Strip index in `[0, stripCount())`
|
|
1208
|
+
* @param samplePos - Absolute samples from the start of processing
|
|
1209
|
+
* @param faderDb - Target fader level in dB
|
|
1210
|
+
* @param curve - Interpolation curve (default: `'linear'`)
|
|
1211
|
+
*/
|
|
1212
|
+
scheduleFaderAutomation(stripIndex, samplePos, faderDb, curve = "linear") {
|
|
1213
|
+
this.mixer.scheduleFaderAutomation(stripIndex, samplePos, faderDb, automationCurveCode(curve));
|
|
1214
|
+
}
|
|
1215
|
+
/**
|
|
1216
|
+
* Schedule sample-accurate pan automation on a strip.
|
|
1217
|
+
*
|
|
1218
|
+
* @param stripIndex - Strip index in `[0, stripCount())`
|
|
1219
|
+
* @param samplePos - Absolute samples from the start of processing
|
|
1220
|
+
* @param pan - Target pan position
|
|
1221
|
+
* @param curve - Interpolation curve (default: `'linear'`)
|
|
1222
|
+
*/
|
|
1223
|
+
schedulePanAutomation(stripIndex, samplePos, pan, curve = "linear") {
|
|
1224
|
+
this.mixer.schedulePanAutomation(stripIndex, samplePos, pan, automationCurveCode(curve));
|
|
1225
|
+
}
|
|
1226
|
+
/**
|
|
1227
|
+
* Schedule sample-accurate width automation on a strip.
|
|
1228
|
+
*
|
|
1229
|
+
* @param stripIndex - Strip index in `[0, stripCount())`
|
|
1230
|
+
* @param samplePos - Absolute samples from the start of processing
|
|
1231
|
+
* @param width - Target stereo width
|
|
1232
|
+
* @param curve - Interpolation curve (default: `'linear'`)
|
|
1233
|
+
*/
|
|
1234
|
+
scheduleWidthAutomation(stripIndex, samplePos, width, curve = "linear") {
|
|
1235
|
+
this.mixer.scheduleWidthAutomation(stripIndex, samplePos, width, automationCurveCode(curve));
|
|
1236
|
+
}
|
|
1237
|
+
/**
|
|
1238
|
+
* Schedule sample-accurate send-level automation on a strip's send.
|
|
1239
|
+
*
|
|
1240
|
+
* @param stripIndex - Strip index in `[0, stripCount())`
|
|
1241
|
+
* @param sendIndex - Send index in the strip's add order
|
|
1242
|
+
* @param samplePos - Absolute samples from the start of processing
|
|
1243
|
+
* @param db - Target send level in dB
|
|
1244
|
+
* @param curve - Interpolation curve (default: `'linear'`)
|
|
1245
|
+
*/
|
|
1246
|
+
scheduleSendAutomation(stripIndex, sendIndex, samplePos, db, curve = "linear") {
|
|
1247
|
+
this.mixer.scheduleSendAutomation(
|
|
1248
|
+
stripIndex,
|
|
1249
|
+
sendIndex,
|
|
1250
|
+
samplePos,
|
|
1251
|
+
db,
|
|
1252
|
+
automationCurveCode(curve)
|
|
1253
|
+
);
|
|
1254
|
+
}
|
|
1255
|
+
/**
|
|
1256
|
+
* Read up to `maxPoints` of a strip's most recent goniometer samples
|
|
1257
|
+
* (oldest to newest).
|
|
1258
|
+
*/
|
|
1259
|
+
readGoniometerLatest(stripIndex, maxPoints) {
|
|
1260
|
+
return this.mixer.readGoniometerLatest(stripIndex, maxPoints);
|
|
1261
|
+
}
|
|
1262
|
+
/** Serialize the current scene (strips, buses, sends, connections) to JSON. */
|
|
1263
|
+
toSceneJson() {
|
|
1264
|
+
return this.mixer.toSceneJson();
|
|
1265
|
+
}
|
|
1266
|
+
/** Release the underlying WASM object. Safe to call only once. */
|
|
1267
|
+
delete() {
|
|
1268
|
+
this.mixer.delete();
|
|
1269
|
+
}
|
|
1270
|
+
/** Alias for {@link delete}, provided for cross-binding (Node) compatibility. */
|
|
1271
|
+
destroy() {
|
|
1272
|
+
this.delete();
|
|
1273
|
+
}
|
|
1274
|
+
};
|
|
366
1275
|
function trim(samples, sampleRate, thresholdDb = -60) {
|
|
367
1276
|
if (!module) {
|
|
368
1277
|
throw new Error("Module not initialized. Call init() first.");
|
|
@@ -393,6 +1302,51 @@ function mfcc(samples, sampleRate, nFft = 2048, hopLength = 512, nMels = 128, nM
|
|
|
393
1302
|
}
|
|
394
1303
|
return module.mfcc(samples, sampleRate, nFft, hopLength, nMels, nMfcc);
|
|
395
1304
|
}
|
|
1305
|
+
function melToStft(melPower, nMels, nFrames, sampleRate, nFft = 2048, hopLength = 512, fmin = 0, fmax = 0) {
|
|
1306
|
+
if (!module) {
|
|
1307
|
+
throw new Error("Module not initialized. Call init() first.");
|
|
1308
|
+
}
|
|
1309
|
+
return module.melToStft(melPower, nMels, nFrames, sampleRate, nFft, hopLength, fmin, fmax);
|
|
1310
|
+
}
|
|
1311
|
+
function melToAudio(melPower, nMels, nFrames, sampleRate, nFft = 2048, hopLength = 512, nIter = 32, fmin = 0, fmax = 0) {
|
|
1312
|
+
if (!module) {
|
|
1313
|
+
throw new Error("Module not initialized. Call init() first.");
|
|
1314
|
+
}
|
|
1315
|
+
return module.melToAudio(
|
|
1316
|
+
melPower,
|
|
1317
|
+
nMels,
|
|
1318
|
+
nFrames,
|
|
1319
|
+
sampleRate,
|
|
1320
|
+
nFft,
|
|
1321
|
+
hopLength,
|
|
1322
|
+
nIter,
|
|
1323
|
+
fmin,
|
|
1324
|
+
fmax
|
|
1325
|
+
);
|
|
1326
|
+
}
|
|
1327
|
+
function mfccToMel(mfccCoefficients, nMfcc, nFrames, nMels = 128) {
|
|
1328
|
+
if (!module) {
|
|
1329
|
+
throw new Error("Module not initialized. Call init() first.");
|
|
1330
|
+
}
|
|
1331
|
+
return module.mfccToMel(mfccCoefficients, nMfcc, nFrames, nMels);
|
|
1332
|
+
}
|
|
1333
|
+
function mfccToAudio(mfccCoefficients, nMfcc, nFrames, nMels, sampleRate, nFft = 2048, hopLength = 512, nIter = 32, fmin = 0, fmax = 0) {
|
|
1334
|
+
if (!module) {
|
|
1335
|
+
throw new Error("Module not initialized. Call init() first.");
|
|
1336
|
+
}
|
|
1337
|
+
return module.mfccToAudio(
|
|
1338
|
+
mfccCoefficients,
|
|
1339
|
+
nMfcc,
|
|
1340
|
+
nFrames,
|
|
1341
|
+
nMels,
|
|
1342
|
+
sampleRate,
|
|
1343
|
+
nFft,
|
|
1344
|
+
hopLength,
|
|
1345
|
+
nIter,
|
|
1346
|
+
fmin,
|
|
1347
|
+
fmax
|
|
1348
|
+
);
|
|
1349
|
+
}
|
|
396
1350
|
function chroma(samples, sampleRate, nFft = 2048, hopLength = 512) {
|
|
397
1351
|
if (!module) {
|
|
398
1352
|
throw new Error("Module not initialized. Call init() first.");
|
|
@@ -603,17 +1557,89 @@ function tonnetz(chromagram, nChroma, nFrames) {
|
|
|
603
1557
|
}
|
|
604
1558
|
return module.tonnetz(chromagram, nChroma, nFrames);
|
|
605
1559
|
}
|
|
606
|
-
function tempogram(
|
|
1560
|
+
function tempogram(onsetEnvelope2, sampleRate, hopLength = 512, winLength = 384, mode = "autocorrelation") {
|
|
1561
|
+
if (!module) {
|
|
1562
|
+
throw new Error("Module not initialized. Call init() first.");
|
|
1563
|
+
}
|
|
1564
|
+
return module.tempogram(onsetEnvelope2, sampleRate, hopLength, winLength, mode);
|
|
1565
|
+
}
|
|
1566
|
+
function cyclicTempogram(onsetEnvelope2, sampleRate, hopLength = 512, winLength = 384, bpmMin = 60, nBins = 60) {
|
|
1567
|
+
if (!module) {
|
|
1568
|
+
throw new Error("Module not initialized. Call init() first.");
|
|
1569
|
+
}
|
|
1570
|
+
return module.cyclicTempogram(onsetEnvelope2, sampleRate, hopLength, winLength, bpmMin, nBins);
|
|
1571
|
+
}
|
|
1572
|
+
function plp(onsetEnvelope2, sampleRate, hopLength = 512, tempoMin = 30, tempoMax = 300, winLength = 384) {
|
|
1573
|
+
if (!module) {
|
|
1574
|
+
throw new Error("Module not initialized. Call init() first.");
|
|
1575
|
+
}
|
|
1576
|
+
return module.plp(onsetEnvelope2, sampleRate, hopLength, tempoMin, tempoMax, winLength);
|
|
1577
|
+
}
|
|
1578
|
+
function nnlsChroma(samples, sampleRate = 22050) {
|
|
1579
|
+
if (!module) {
|
|
1580
|
+
throw new Error("Module not initialized. Call init() first.");
|
|
1581
|
+
}
|
|
1582
|
+
return module.nnlsChroma(samples, sampleRate);
|
|
1583
|
+
}
|
|
1584
|
+
function cqt(samples, sampleRate = 22050, hopLength = 512, fmin = 32.70319566257483, nBins = 84, binsPerOctave = 12) {
|
|
1585
|
+
if (!module) {
|
|
1586
|
+
throw new Error("Module not initialized. Call init() first.");
|
|
1587
|
+
}
|
|
1588
|
+
return module.cqt(samples, sampleRate, hopLength, fmin, nBins, binsPerOctave);
|
|
1589
|
+
}
|
|
1590
|
+
function vqt(samples, sampleRate = 22050, hopLength = 512, fmin = 32.70319566257483, nBins = 84, binsPerOctave = 12, gamma = 0) {
|
|
1591
|
+
if (!module) {
|
|
1592
|
+
throw new Error("Module not initialized. Call init() first.");
|
|
1593
|
+
}
|
|
1594
|
+
return module.vqt(samples, sampleRate, hopLength, fmin, nBins, binsPerOctave, gamma);
|
|
1595
|
+
}
|
|
1596
|
+
function analyzeSections(samples, sampleRate = 22050, nFft = 2048, hopLength = 512, minSectionSec = 8) {
|
|
1597
|
+
if (!module) {
|
|
1598
|
+
throw new Error("Module not initialized. Call init() first.");
|
|
1599
|
+
}
|
|
1600
|
+
return module.analyzeSections(samples, sampleRate, nFft, hopLength, minSectionSec).map((s) => ({ ...s, type: s.type }));
|
|
1601
|
+
}
|
|
1602
|
+
function analyzeMelody(samples, sampleRate = 22050, fmin = 65, fmax = 2093, frameLength = 2048, hopLength = 512, threshold = 0.1) {
|
|
1603
|
+
if (!module) {
|
|
1604
|
+
throw new Error("Module not initialized. Call init() first.");
|
|
1605
|
+
}
|
|
1606
|
+
return module.analyzeMelody(samples, sampleRate, fmin, fmax, frameLength, hopLength, threshold);
|
|
1607
|
+
}
|
|
1608
|
+
function onsetEnvelope(samples, sampleRate = 22050, nFft = 2048, hopLength = 512, nMels = 128) {
|
|
1609
|
+
if (!module) {
|
|
1610
|
+
throw new Error("Module not initialized. Call init() first.");
|
|
1611
|
+
}
|
|
1612
|
+
return module.onsetEnvelope(samples, sampleRate, nFft, hopLength, nMels);
|
|
1613
|
+
}
|
|
1614
|
+
function fourierTempogram(onsetEnvelope2, sampleRate = 22050, hopLength = 512, winLength = 384) {
|
|
1615
|
+
if (!module) {
|
|
1616
|
+
throw new Error("Module not initialized. Call init() first.");
|
|
1617
|
+
}
|
|
1618
|
+
return module.fourierTempogram(onsetEnvelope2, sampleRate, hopLength, winLength);
|
|
1619
|
+
}
|
|
1620
|
+
function tempogramRatio(tempogramData, winLength = 384, sampleRate = 22050, hopLength = 512) {
|
|
1621
|
+
if (!module) {
|
|
1622
|
+
throw new Error("Module not initialized. Call init() first.");
|
|
1623
|
+
}
|
|
1624
|
+
return module.tempogramRatio(tempogramData, winLength, sampleRate, hopLength);
|
|
1625
|
+
}
|
|
1626
|
+
function lufs(samples, sampleRate = 22050) {
|
|
1627
|
+
if (!module) {
|
|
1628
|
+
throw new Error("Module not initialized. Call init() first.");
|
|
1629
|
+
}
|
|
1630
|
+
return module.lufs(samples, sampleRate);
|
|
1631
|
+
}
|
|
1632
|
+
function momentaryLufs(samples, sampleRate = 22050) {
|
|
607
1633
|
if (!module) {
|
|
608
1634
|
throw new Error("Module not initialized. Call init() first.");
|
|
609
1635
|
}
|
|
610
|
-
return module.
|
|
1636
|
+
return module.momentaryLufs(samples, sampleRate);
|
|
611
1637
|
}
|
|
612
|
-
function
|
|
1638
|
+
function shortTermLufs(samples, sampleRate = 22050) {
|
|
613
1639
|
if (!module) {
|
|
614
1640
|
throw new Error("Module not initialized. Call init() first.");
|
|
615
1641
|
}
|
|
616
|
-
return module.
|
|
1642
|
+
return module.shortTermLufs(samples, sampleRate);
|
|
617
1643
|
}
|
|
618
1644
|
function resample(samples, srcSr, targetSr) {
|
|
619
1645
|
if (!module) {
|
|
@@ -650,8 +1676,11 @@ var Audio = class _Audio {
|
|
|
650
1676
|
detectBpm() {
|
|
651
1677
|
return detectBpm(this._samples, this._sampleRate);
|
|
652
1678
|
}
|
|
653
|
-
detectKey() {
|
|
654
|
-
return detectKey(this._samples, this._sampleRate);
|
|
1679
|
+
detectKey(options = {}) {
|
|
1680
|
+
return detectKey(this._samples, this._sampleRate, options);
|
|
1681
|
+
}
|
|
1682
|
+
detectKeyCandidates(options = {}) {
|
|
1683
|
+
return detectKeyCandidates(this._samples, this._sampleRate, options);
|
|
655
1684
|
}
|
|
656
1685
|
detectOnsets() {
|
|
657
1686
|
return detectOnsets(this._samples, this._sampleRate);
|
|
@@ -659,6 +1688,12 @@ var Audio = class _Audio {
|
|
|
659
1688
|
detectBeats() {
|
|
660
1689
|
return detectBeats(this._samples, this._sampleRate);
|
|
661
1690
|
}
|
|
1691
|
+
detectDownbeats() {
|
|
1692
|
+
return detectDownbeats(this._samples, this._sampleRate);
|
|
1693
|
+
}
|
|
1694
|
+
detectChords(options = {}) {
|
|
1695
|
+
return detectChords(this._samples, this._sampleRate, options);
|
|
1696
|
+
}
|
|
662
1697
|
analyze() {
|
|
663
1698
|
return analyze(this._samples, this._sampleRate);
|
|
664
1699
|
}
|
|
@@ -681,6 +1716,15 @@ var Audio = class _Audio {
|
|
|
681
1716
|
pitchShift(semitones) {
|
|
682
1717
|
return pitchShift(this._samples, this._sampleRate, semitones);
|
|
683
1718
|
}
|
|
1719
|
+
pitchCorrectToMidi(currentMidi, targetMidi) {
|
|
1720
|
+
return pitchCorrectToMidi(this._samples, this._sampleRate, currentMidi, targetMidi);
|
|
1721
|
+
}
|
|
1722
|
+
noteStretch(onsetSample, offsetSample, stretchRatio) {
|
|
1723
|
+
return noteStretch(this._samples, this._sampleRate, onsetSample, offsetSample, stretchRatio);
|
|
1724
|
+
}
|
|
1725
|
+
voiceChange(pitchSemitones, formantFactor) {
|
|
1726
|
+
return voiceChange(this._samples, this._sampleRate, pitchSemitones, formantFactor);
|
|
1727
|
+
}
|
|
684
1728
|
normalize(targetDb = 0) {
|
|
685
1729
|
return normalize(this._samples, this._sampleRate, targetDb);
|
|
686
1730
|
}
|
|
@@ -715,6 +1759,21 @@ var Audio = class _Audio {
|
|
|
715
1759
|
chroma(nFft = 2048, hopLength = 512) {
|
|
716
1760
|
return chroma(this._samples, this._sampleRate, nFft, hopLength);
|
|
717
1761
|
}
|
|
1762
|
+
nnlsChroma() {
|
|
1763
|
+
return nnlsChroma(this._samples, this._sampleRate);
|
|
1764
|
+
}
|
|
1765
|
+
onsetEnvelope(nFft = 2048, hopLength = 512, nMels = 128) {
|
|
1766
|
+
return onsetEnvelope(this._samples, this._sampleRate, nFft, hopLength, nMels);
|
|
1767
|
+
}
|
|
1768
|
+
lufs() {
|
|
1769
|
+
return lufs(this._samples, this._sampleRate);
|
|
1770
|
+
}
|
|
1771
|
+
momentaryLufs() {
|
|
1772
|
+
return momentaryLufs(this._samples, this._sampleRate);
|
|
1773
|
+
}
|
|
1774
|
+
shortTermLufs() {
|
|
1775
|
+
return shortTermLufs(this._samples, this._sampleRate);
|
|
1776
|
+
}
|
|
718
1777
|
spectralCentroid(nFft = 2048, hopLength = 512) {
|
|
719
1778
|
return spectralCentroid(this._samples, this._sampleRate, nFft, hopLength);
|
|
720
1779
|
}
|
|
@@ -761,16 +1820,64 @@ var StreamAnalyzer = class {
|
|
|
761
1820
|
if (!module) {
|
|
762
1821
|
throw new Error("Module not initialized. Call init() first.");
|
|
763
1822
|
}
|
|
764
|
-
|
|
1823
|
+
const wasmModule = module;
|
|
1824
|
+
const args = [
|
|
765
1825
|
config.sampleRate,
|
|
766
1826
|
config.nFft ?? 2048,
|
|
767
1827
|
config.hopLength ?? 512,
|
|
768
1828
|
config.nMels ?? 128,
|
|
1829
|
+
config.fmin ?? 0,
|
|
1830
|
+
config.fmax ?? 0,
|
|
1831
|
+
config.tuningRefHz ?? 440,
|
|
1832
|
+
config.computeMagnitude ?? true,
|
|
769
1833
|
config.computeMel ?? true,
|
|
770
1834
|
config.computeChroma ?? true,
|
|
771
1835
|
config.computeOnset ?? true,
|
|
772
|
-
config.
|
|
773
|
-
|
|
1836
|
+
config.computeSpectral ?? true,
|
|
1837
|
+
config.emitEveryNFrames ?? 1,
|
|
1838
|
+
config.magnitudeDownsample ?? 1,
|
|
1839
|
+
config.keyUpdateIntervalSec ?? 5,
|
|
1840
|
+
config.bpmUpdateIntervalSec ?? 10,
|
|
1841
|
+
config.window ?? 0,
|
|
1842
|
+
config.outputFormat ?? 0
|
|
1843
|
+
];
|
|
1844
|
+
const isArityError = (error) => {
|
|
1845
|
+
const message = String(error?.message ?? error);
|
|
1846
|
+
return message.includes("invalid number of parameters");
|
|
1847
|
+
};
|
|
1848
|
+
const createLegacy = () => {
|
|
1849
|
+
const LegacyStreamAnalyzer = wasmModule.StreamAnalyzer;
|
|
1850
|
+
return new LegacyStreamAnalyzer(
|
|
1851
|
+
args[0],
|
|
1852
|
+
args[1],
|
|
1853
|
+
args[2],
|
|
1854
|
+
args[3],
|
|
1855
|
+
args[8],
|
|
1856
|
+
args[9],
|
|
1857
|
+
args[10],
|
|
1858
|
+
args[12]
|
|
1859
|
+
);
|
|
1860
|
+
};
|
|
1861
|
+
const hasExtendedConfig = config.fmin !== void 0 || config.fmax !== void 0 || config.tuningRefHz !== void 0 || config.computeMagnitude !== void 0 || config.computeSpectral !== void 0 || config.magnitudeDownsample !== void 0 || config.keyUpdateIntervalSec !== void 0 || config.bpmUpdateIntervalSec !== void 0 || config.window !== void 0 || config.outputFormat !== void 0;
|
|
1862
|
+
if (hasExtendedConfig) {
|
|
1863
|
+
try {
|
|
1864
|
+
this.analyzer = new wasmModule.StreamAnalyzer(...args);
|
|
1865
|
+
} catch (error) {
|
|
1866
|
+
if (!isArityError(error)) {
|
|
1867
|
+
throw error;
|
|
1868
|
+
}
|
|
1869
|
+
this.analyzer = createLegacy();
|
|
1870
|
+
}
|
|
1871
|
+
} else {
|
|
1872
|
+
try {
|
|
1873
|
+
this.analyzer = createLegacy();
|
|
1874
|
+
} catch (error) {
|
|
1875
|
+
if (!isArityError(error)) {
|
|
1876
|
+
throw error;
|
|
1877
|
+
}
|
|
1878
|
+
this.analyzer = new wasmModule.StreamAnalyzer(...args);
|
|
1879
|
+
}
|
|
1880
|
+
}
|
|
774
1881
|
}
|
|
775
1882
|
/**
|
|
776
1883
|
* Process audio samples.
|
|
@@ -804,6 +1911,12 @@ var StreamAnalyzer = class {
|
|
|
804
1911
|
readFrames(maxFrames) {
|
|
805
1912
|
return this.analyzer.readFramesSoa(maxFrames);
|
|
806
1913
|
}
|
|
1914
|
+
readFramesU8(maxFrames) {
|
|
1915
|
+
return this.analyzer.readFramesU8(maxFrames);
|
|
1916
|
+
}
|
|
1917
|
+
readFramesI16(maxFrames) {
|
|
1918
|
+
return this.analyzer.readFramesI16(maxFrames);
|
|
1919
|
+
}
|
|
807
1920
|
/**
|
|
808
1921
|
* Reset the analyzer state.
|
|
809
1922
|
*
|
|
@@ -833,6 +1946,7 @@ var StreamAnalyzer = class {
|
|
|
833
1946
|
chordRoot: s.estimate.chordRoot,
|
|
834
1947
|
chordQuality: s.estimate.chordQuality,
|
|
835
1948
|
chordConfidence: s.estimate.chordConfidence,
|
|
1949
|
+
chordStartTime: s.estimate.chordStartTime,
|
|
836
1950
|
chordProgression: s.estimate.chordProgression.map((c) => ({
|
|
837
1951
|
root: c.root,
|
|
838
1952
|
quality: c.quality,
|
|
@@ -925,25 +2039,43 @@ var StreamAnalyzer = class {
|
|
|
925
2039
|
export {
|
|
926
2040
|
Audio,
|
|
927
2041
|
ChordQuality,
|
|
2042
|
+
EXPECTED_ENGINE_ABI_VERSION,
|
|
2043
|
+
KeyProfile,
|
|
2044
|
+
Mixer,
|
|
928
2045
|
Mode,
|
|
929
2046
|
PitchClass as Pitch,
|
|
930
2047
|
PitchClass,
|
|
2048
|
+
RealtimeEngine,
|
|
931
2049
|
SectionType,
|
|
932
2050
|
StreamAnalyzer,
|
|
2051
|
+
StreamingEqualizer,
|
|
933
2052
|
StreamingMasteringChain,
|
|
2053
|
+
StreamingRetune,
|
|
934
2054
|
amplitudeToDb,
|
|
935
2055
|
analyze,
|
|
2056
|
+
analyzeImpulseResponse,
|
|
2057
|
+
analyzeMelody,
|
|
2058
|
+
analyzeSections,
|
|
936
2059
|
analyzeWithProgress,
|
|
937
2060
|
chroma,
|
|
2061
|
+
cqt,
|
|
2062
|
+
cyclicTempogram,
|
|
938
2063
|
dbToAmplitude,
|
|
939
2064
|
dbToPower,
|
|
940
2065
|
deemphasis,
|
|
2066
|
+
detectAcoustic,
|
|
941
2067
|
detectBeats,
|
|
942
2068
|
detectBpm,
|
|
2069
|
+
detectChords,
|
|
2070
|
+
detectDownbeats,
|
|
943
2071
|
detectKey,
|
|
2072
|
+
detectKeyCandidates,
|
|
944
2073
|
detectOnsets,
|
|
2074
|
+
engineAbiVersion,
|
|
2075
|
+
engineCapabilities,
|
|
945
2076
|
fixFrames,
|
|
946
2077
|
fixLength,
|
|
2078
|
+
fourierTempogram,
|
|
947
2079
|
frameSignal,
|
|
948
2080
|
framesToSamples,
|
|
949
2081
|
framesToTime,
|
|
@@ -954,9 +2086,12 @@ export {
|
|
|
954
2086
|
hzToNote,
|
|
955
2087
|
init,
|
|
956
2088
|
isInitialized,
|
|
2089
|
+
lufs,
|
|
957
2090
|
masterAudio,
|
|
958
2091
|
masterAudioStereo,
|
|
959
2092
|
mastering,
|
|
2093
|
+
masteringAssistantSuggest,
|
|
2094
|
+
masteringAudioProfile,
|
|
960
2095
|
masteringChain,
|
|
961
2096
|
masteringChainStereo,
|
|
962
2097
|
masteringChainStereoWithProgress,
|
|
@@ -971,16 +2106,30 @@ export {
|
|
|
971
2106
|
masteringProcessorNames,
|
|
972
2107
|
masteringStereoAnalysisNames,
|
|
973
2108
|
masteringStereoAnalyze,
|
|
2109
|
+
masteringStreamingPreview,
|
|
974
2110
|
melSpectrogram,
|
|
2111
|
+
melToAudio,
|
|
975
2112
|
melToHz,
|
|
2113
|
+
melToStft,
|
|
976
2114
|
mfcc,
|
|
2115
|
+
mfccToAudio,
|
|
2116
|
+
mfccToMel,
|
|
977
2117
|
midiToHz,
|
|
2118
|
+
mixStereo,
|
|
2119
|
+
mixerScenePresetJson,
|
|
2120
|
+
mixingScenePresetJson,
|
|
2121
|
+
mixingScenePresetNames,
|
|
2122
|
+
momentaryLufs,
|
|
2123
|
+
nnlsChroma,
|
|
978
2124
|
normalize,
|
|
2125
|
+
noteStretch,
|
|
979
2126
|
noteToHz,
|
|
2127
|
+
onsetEnvelope,
|
|
980
2128
|
padCenter,
|
|
981
2129
|
pcen,
|
|
982
2130
|
peakPick,
|
|
983
2131
|
percussive,
|
|
2132
|
+
pitchCorrectToMidi,
|
|
984
2133
|
pitchPyin,
|
|
985
2134
|
pitchShift,
|
|
986
2135
|
pitchYin,
|
|
@@ -990,6 +2139,7 @@ export {
|
|
|
990
2139
|
resample,
|
|
991
2140
|
rmsEnergy,
|
|
992
2141
|
samplesToFrames,
|
|
2142
|
+
shortTermLufs,
|
|
993
2143
|
spectralBandwidth,
|
|
994
2144
|
spectralCentroid,
|
|
995
2145
|
spectralFlatness,
|
|
@@ -998,6 +2148,7 @@ export {
|
|
|
998
2148
|
stft,
|
|
999
2149
|
stftDb,
|
|
1000
2150
|
tempogram,
|
|
2151
|
+
tempogramRatio,
|
|
1001
2152
|
timeStretch,
|
|
1002
2153
|
timeToFrames,
|
|
1003
2154
|
tonnetz,
|
|
@@ -1005,6 +2156,8 @@ export {
|
|
|
1005
2156
|
trimSilence,
|
|
1006
2157
|
vectorNormalize,
|
|
1007
2158
|
version,
|
|
2159
|
+
voiceChange,
|
|
2160
|
+
vqt,
|
|
1008
2161
|
zeroCrossingRate
|
|
1009
2162
|
};
|
|
1010
2163
|
//# sourceMappingURL=index.js.map
|