@grame/faustwasm 0.8.2 → 0.9.0

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 (61) hide show
  1. package/assets/standalone/create-node.js +15 -8
  2. package/assets/standalone/faustwasm/index.d.ts +40 -0
  3. package/assets/standalone/faustwasm/index.js +109 -30
  4. package/assets/standalone/faustwasm/index.js.map +2 -2
  5. package/assets/standalone/index-pwa.js +1 -1
  6. package/assets/standalone/service-worker.js +58 -5
  7. package/dist/cjs/index.d.ts +40 -0
  8. package/dist/cjs/index.js +109 -30
  9. package/dist/cjs/index.js.map +2 -2
  10. package/dist/cjs-bundle/index.d.ts +40 -0
  11. package/dist/cjs-bundle/index.js +109 -30
  12. package/dist/cjs-bundle/index.js.map +2 -2
  13. package/dist/esm/index.d.ts +40 -0
  14. package/dist/esm/index.js +109 -30
  15. package/dist/esm/index.js.map +2 -2
  16. package/dist/esm-bundle/index.d.ts +40 -0
  17. package/dist/esm-bundle/index.js +109 -30
  18. package/dist/esm-bundle/index.js.map +2 -2
  19. package/package.json +1 -1
  20. package/src/FaustAudioWorkletNode.ts +10 -0
  21. package/src/FaustAudioWorkletProcessor.ts +16 -0
  22. package/src/FaustOfflineProcessor.ts +2 -0
  23. package/src/FaustScriptProcessorNode.ts +2 -0
  24. package/src/FaustWebAudioDsp.ts +88 -0
  25. package/src/copyWebStandaloneAssets.js +14 -0
  26. package/test/faustlive-wasm/faustwasm/index.d.ts +40 -0
  27. package/test/faustlive-wasm/faustwasm/index.js +109 -30
  28. package/test/faustlive-wasm/faustwasm/index.js.map +2 -2
  29. package/test/midi/create-node.js +177 -0
  30. package/test/midi/dsp-meta.json +133 -0
  31. package/test/midi/dsp-module.wasm +0 -0
  32. package/test/midi/faust-ui/index.css +442 -0
  33. package/test/midi/faust-ui/index.css.map +1 -0
  34. package/test/midi/faust-ui/index.d.ts +1 -0
  35. package/test/midi/faust-ui/index.js +3729 -0
  36. package/test/midi/faust-ui/index.js.map +1 -0
  37. package/test/midi/faustwasm/index.d.ts +1680 -0
  38. package/test/midi/faustwasm/index.js +4884 -0
  39. package/test/midi/faustwasm/index.js.map +7 -0
  40. package/test/midi/icon.png +0 -0
  41. package/test/midi/index.html +76 -0
  42. package/test/midi/index.js +183 -0
  43. package/test/midi/manifest.json +17 -0
  44. package/test/midi/service-worker.js +165 -0
  45. package/test/midi.dsp +8 -1
  46. package/test/organ1/create-node.js +177 -0
  47. package/test/organ1/dsp-meta.json +126 -0
  48. package/test/organ1/dsp-module.wasm +0 -0
  49. package/test/organ1/faust-ui/index.css +442 -0
  50. package/test/organ1/faust-ui/index.css.map +1 -0
  51. package/test/organ1/faust-ui/index.d.ts +1 -0
  52. package/test/organ1/faust-ui/index.js +3729 -0
  53. package/test/organ1/faust-ui/index.js.map +1 -0
  54. package/test/organ1/faustwasm/index.d.ts +1656 -0
  55. package/test/organ1/faustwasm/index.js +4783 -0
  56. package/test/organ1/faustwasm/index.js.map +7 -0
  57. package/test/organ1/icon.png +0 -0
  58. package/test/organ1/index.html +76 -0
  59. package/test/organ1/index.js +203 -0
  60. package/test/organ1/manifest.json +17 -0
  61. package/test/organ1/service-worker.js +181 -0
@@ -0,0 +1,4884 @@
1
+ var __accessCheck = (obj, member, msg) => {
2
+ if (!member.has(obj))
3
+ throw TypeError("Cannot " + msg);
4
+ };
5
+ var __privateGet = (obj, member, getter) => {
6
+ __accessCheck(obj, member, "read from private field");
7
+ return getter ? getter.call(obj) : member.get(obj);
8
+ };
9
+ var __privateAdd = (obj, member, value) => {
10
+ if (member.has(obj))
11
+ throw TypeError("Cannot add the same private member more than once");
12
+ member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
13
+ };
14
+ var __privateSet = (obj, member, value, setter) => {
15
+ __accessCheck(obj, member, "write to private field");
16
+ setter ? setter.call(obj, value) : member.set(obj, value);
17
+ return value;
18
+ };
19
+
20
+ // src/instantiateFaustModuleFromFile.ts
21
+ var instantiateFaustModuleFromFile = async (jsFile, dataFile = jsFile.replace(/c?js$/, "data"), wasmFile = jsFile.replace(/c?js$/, "wasm")) => {
22
+ var _a, _b;
23
+ let FaustModule;
24
+ let dataBinary;
25
+ let wasmBinary;
26
+ const jsCodeHead = /var (.+) = \(/;
27
+ if (typeof window === "object") {
28
+ let jsCode = await (await fetch(jsFile)).text();
29
+ jsCode = `${jsCode}
30
+ export default ${(_a = jsCode.match(jsCodeHead)) == null ? void 0 : _a[1]};
31
+ `;
32
+ const jsFileMod = URL.createObjectURL(new Blob([jsCode], { type: "text/javascript" }));
33
+ FaustModule = (await import(
34
+ /* webpackIgnore: true */
35
+ jsFileMod
36
+ )).default;
37
+ dataBinary = await (await fetch(dataFile)).arrayBuffer();
38
+ wasmBinary = new Uint8Array(await (await fetch(wasmFile)).arrayBuffer());
39
+ } else {
40
+ const { promises: fs } = await import("fs");
41
+ const { pathToFileURL } = await import("url");
42
+ let jsCode = await fs.readFile(jsFile, { encoding: "utf-8" });
43
+ jsCode = `
44
+ import process from "process";
45
+ import * as path from "path";
46
+ import { createRequire } from "module";
47
+ import { fileURLToPath } from "url";
48
+
49
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
50
+ const __filename = fileURLToPath(import.meta.url);
51
+ const require = createRequire(import.meta.url);
52
+
53
+ ${jsCode}
54
+
55
+ export default ${(_b = jsCode.match(jsCodeHead)) == null ? void 0 : _b[1]};
56
+ `;
57
+ const jsFileMod = jsFile.replace(/c?js$/, "mjs");
58
+ await fs.writeFile(jsFileMod, jsCode);
59
+ FaustModule = (await import(
60
+ /* webpackIgnore: true */
61
+ pathToFileURL(jsFileMod).href
62
+ )).default;
63
+ await fs.unlink(jsFileMod);
64
+ dataBinary = (await fs.readFile(dataFile)).buffer;
65
+ wasmBinary = (await fs.readFile(wasmFile)).buffer;
66
+ }
67
+ const faustModule = await FaustModule({
68
+ wasmBinary,
69
+ getPreloadedPackage: (remotePackageName, remotePackageSize) => {
70
+ if (remotePackageName === "libfaust-wasm.data")
71
+ return dataBinary;
72
+ return new ArrayBuffer(0);
73
+ }
74
+ });
75
+ return faustModule;
76
+ };
77
+ var instantiateFaustModuleFromFile_default = instantiateFaustModuleFromFile;
78
+
79
+ // src/FaustAudioWorkletProcessor.ts
80
+ var getFaustAudioWorkletProcessor = (dependencies, faustData, register = true) => {
81
+ const { registerProcessor, AudioWorkletProcessor, sampleRate } = globalThis;
82
+ const {
83
+ FaustBaseWebAudioDsp: FaustBaseWebAudioDsp2,
84
+ FaustWasmInstantiator: FaustWasmInstantiator2,
85
+ FaustAudioWorkletProcessorCommunicator: FaustAudioWorkletProcessorCommunicator2
86
+ } = dependencies;
87
+ const {
88
+ processorName,
89
+ dspName,
90
+ dspMeta,
91
+ effectMeta,
92
+ poly
93
+ } = faustData;
94
+ const analysePolyParameters = (item) => {
95
+ const polyKeywords = ["/gate", "/freq", "/gain", "/key", "/vel", "/velocity"];
96
+ const isPolyReserved = "address" in item && !!polyKeywords.find((k) => item.address.endsWith(k));
97
+ if (poly && isPolyReserved)
98
+ return null;
99
+ if (item.type === "vslider" || item.type === "hslider" || item.type === "nentry") {
100
+ return { name: item.address, defaultValue: item.init || 0, minValue: item.min || 0, maxValue: item.max || 0 };
101
+ } else if (item.type === "button" || item.type === "checkbox") {
102
+ return { name: item.address, defaultValue: item.init || 0, minValue: 0, maxValue: 1 };
103
+ }
104
+ return null;
105
+ };
106
+ class FaustAudioWorkletProcessor extends AudioWorkletProcessor {
107
+ constructor(options) {
108
+ super(options);
109
+ this.paramValuesCache = {};
110
+ this.fCommunicator = new FaustAudioWorkletProcessorCommunicator2(this.port);
111
+ const { parameterDescriptors } = this.constructor;
112
+ parameterDescriptors.forEach((pd) => {
113
+ this.paramValuesCache[pd.name] = pd.defaultValue || 0;
114
+ });
115
+ const { moduleId, instanceId } = options.processorOptions;
116
+ if (!moduleId || !instanceId)
117
+ return;
118
+ this.wamInfo = { moduleId, instanceId };
119
+ }
120
+ static get parameterDescriptors() {
121
+ const params = [];
122
+ const callback = (item) => {
123
+ const param = analysePolyParameters(item);
124
+ if (param)
125
+ params.push(param);
126
+ };
127
+ FaustBaseWebAudioDsp2.parseUI(dspMeta.ui, callback);
128
+ if (effectMeta)
129
+ FaustBaseWebAudioDsp2.parseUI(effectMeta.ui, callback);
130
+ return params;
131
+ }
132
+ setupWamEventHandler() {
133
+ var _a;
134
+ if (!this.wamInfo)
135
+ return;
136
+ const { moduleId, instanceId } = this.wamInfo;
137
+ const { webAudioModules } = globalThis;
138
+ const ModuleScope = webAudioModules.getModuleScope(moduleId);
139
+ const paramMgrProcessor = (_a = ModuleScope == null ? void 0 : ModuleScope.paramMgrProcessors) == null ? void 0 : _a[instanceId];
140
+ if (!paramMgrProcessor)
141
+ return;
142
+ if (paramMgrProcessor.handleEvent)
143
+ return;
144
+ paramMgrProcessor.handleEvent = (event) => {
145
+ if (event.type === "wam-midi")
146
+ this.midiMessage(event.data.bytes);
147
+ };
148
+ }
149
+ process(inputs, outputs, parameters) {
150
+ for (const path in parameters) {
151
+ const [paramValue] = parameters[path];
152
+ if (paramValue !== this.paramValuesCache[path]) {
153
+ this.fDSPCode.setParamValue(path, paramValue);
154
+ this.paramValuesCache[path] = paramValue;
155
+ }
156
+ }
157
+ if (this.fCommunicator.getNewAccDataAvailable()) {
158
+ const acc = this.fCommunicator.getAcc();
159
+ if (acc) {
160
+ this.fCommunicator.setNewAccDataAvailable(false);
161
+ const { invert, ...data } = acc;
162
+ this.propagateAcc(data, invert);
163
+ }
164
+ }
165
+ if (this.fCommunicator.getNewGyrDataAvailable()) {
166
+ const gyr = this.fCommunicator.getGyr();
167
+ if (gyr) {
168
+ this.fCommunicator.setNewGyrDataAvailable(false);
169
+ this.propagateGyr(gyr);
170
+ }
171
+ }
172
+ return this.fDSPCode.compute(inputs[0], outputs[0]);
173
+ }
174
+ handleMessageAux(e) {
175
+ const msg = e.data;
176
+ switch (msg.type) {
177
+ case "midi": {
178
+ this.midiMessage(msg.data);
179
+ break;
180
+ }
181
+ case "ctrlChange": {
182
+ this.ctrlChange(msg.data[0], msg.data[1], msg.data[2]);
183
+ break;
184
+ }
185
+ case "pitchWheel": {
186
+ this.pitchWheel(msg.data[0], msg.data[1]);
187
+ break;
188
+ }
189
+ case "keyOn": {
190
+ this.keyOn(msg.data[0], msg.data[1], msg.data[2]);
191
+ break;
192
+ }
193
+ case "keyOff": {
194
+ this.keyOff(msg.data[0], msg.data[1], msg.data[2]);
195
+ break;
196
+ }
197
+ case "param": {
198
+ this.setParamValue(msg.data.path, msg.data.value);
199
+ break;
200
+ }
201
+ case "setPlotHandler": {
202
+ if (msg.data) {
203
+ this.fDSPCode.setPlotHandler((output, index, events) => this.port.postMessage({ type: "plot", value: output, index, events }));
204
+ } else {
205
+ this.fDSPCode.setPlotHandler(null);
206
+ }
207
+ break;
208
+ }
209
+ case "setupWamEventHandler": {
210
+ this.setupWamEventHandler();
211
+ break;
212
+ }
213
+ case "start": {
214
+ this.fDSPCode.start();
215
+ break;
216
+ }
217
+ case "stop": {
218
+ this.fDSPCode.stop();
219
+ break;
220
+ }
221
+ case "destroy": {
222
+ this.port.close();
223
+ this.fDSPCode.destroy();
224
+ break;
225
+ }
226
+ default:
227
+ break;
228
+ }
229
+ }
230
+ setParamValue(path, value) {
231
+ this.fDSPCode.setParamValue(path, value);
232
+ this.paramValuesCache[path] = value;
233
+ }
234
+ midiMessage(data) {
235
+ this.fDSPCode.midiMessage(data);
236
+ }
237
+ ctrlChange(channel, ctrl, value) {
238
+ this.fDSPCode.ctrlChange(channel, ctrl, value);
239
+ }
240
+ pitchWheel(channel, wheel) {
241
+ this.fDSPCode.pitchWheel(channel, wheel);
242
+ }
243
+ keyOn(channel, pitch, velocity) {
244
+ this.fDSPCode.keyOn(channel, pitch, velocity);
245
+ }
246
+ keyOff(channel, pitch, velocity) {
247
+ this.fDSPCode.keyOff(channel, pitch, velocity);
248
+ }
249
+ propagateAcc(accelerationIncludingGravity, invert = false) {
250
+ this.fDSPCode.propagateAcc(accelerationIncludingGravity, invert);
251
+ }
252
+ propagateGyr(event) {
253
+ this.fDSPCode.propagateGyr(event);
254
+ }
255
+ }
256
+ class FaustMonoAudioWorkletProcessor extends FaustAudioWorkletProcessor {
257
+ constructor(options) {
258
+ super(options);
259
+ this.handleMessageAux = (e) => {
260
+ super.handleMessageAux(e);
261
+ };
262
+ const { FaustMonoWebAudioDsp: FaustMonoWebAudioDsp2 } = dependencies;
263
+ const { factory, sampleSize } = options.processorOptions;
264
+ const instance = FaustWasmInstantiator2.createSyncMonoDSPInstance(factory);
265
+ this.fDSPCode = new FaustMonoWebAudioDsp2(instance, sampleRate, sampleSize, 128, factory.soundfiles);
266
+ this.port.addEventListener("message", this.handleMessageAux);
267
+ this.port.start();
268
+ this.fDSPCode.setOutputParamHandler((path, value) => this.port.postMessage({ path, value, type: "param" }));
269
+ this.fDSPCode.start();
270
+ }
271
+ }
272
+ class FaustPolyAudioWorkletProcessor extends FaustAudioWorkletProcessor {
273
+ constructor(options) {
274
+ super(options);
275
+ this.handleMessageAux = (e) => {
276
+ const msg = e.data;
277
+ switch (msg.type) {
278
+ case "keyOn":
279
+ this.keyOn(msg.data[0], msg.data[1], msg.data[2]);
280
+ break;
281
+ case "keyOff":
282
+ this.keyOff(msg.data[0], msg.data[1], msg.data[2]);
283
+ break;
284
+ default:
285
+ super.handleMessageAux(e);
286
+ break;
287
+ }
288
+ };
289
+ const { FaustPolyWebAudioDsp: FaustPolyWebAudioDsp3 } = dependencies;
290
+ const { voiceFactory, mixerModule, voices, effectFactory, sampleSize } = options.processorOptions;
291
+ const instance = FaustWasmInstantiator2.createSyncPolyDSPInstance(voiceFactory, mixerModule, voices, effectFactory);
292
+ const soundfiles = { ...effectFactory == null ? void 0 : effectFactory.soundfiles, ...voiceFactory.soundfiles };
293
+ this.fDSPCode = new FaustPolyWebAudioDsp3(instance, sampleRate, sampleSize, 128, soundfiles);
294
+ this.port.addEventListener("message", this.handleMessageAux);
295
+ this.port.start();
296
+ this.fDSPCode.setOutputParamHandler((path, value) => this.port.postMessage({ path, value, type: "param" }));
297
+ this.fDSPCode.start();
298
+ }
299
+ midiMessage(data) {
300
+ const cmd = data[0] >> 4;
301
+ const channel = data[0] & 15;
302
+ const data1 = data[1];
303
+ const data2 = data[2];
304
+ if (cmd === 8 || cmd === 9 && data2 === 0)
305
+ this.keyOff(channel, data1, data2);
306
+ else if (cmd === 9)
307
+ this.keyOn(channel, data1, data2);
308
+ else
309
+ super.midiMessage(data);
310
+ }
311
+ // Public API
312
+ keyOn(channel, pitch, velocity) {
313
+ this.fDSPCode.keyOn(channel, pitch, velocity);
314
+ }
315
+ keyOff(channel, pitch, velocity) {
316
+ this.fDSPCode.keyOff(channel, pitch, velocity);
317
+ }
318
+ allNotesOff(hard) {
319
+ this.fDSPCode.allNotesOff(hard);
320
+ }
321
+ }
322
+ const Processor = poly ? FaustPolyAudioWorkletProcessor : FaustMonoAudioWorkletProcessor;
323
+ if (register) {
324
+ try {
325
+ registerProcessor(processorName || dspName || (poly ? "mydsp_poly" : "mydsp"), Processor);
326
+ } catch (error) {
327
+ console.warn(error);
328
+ }
329
+ }
330
+ return poly ? FaustPolyAudioWorkletProcessor : FaustMonoAudioWorkletProcessor;
331
+ };
332
+ var FaustAudioWorkletProcessor_default = getFaustAudioWorkletProcessor;
333
+
334
+ // src/FaustFFTAudioWorkletProcessor.ts
335
+ var getFaustFFTAudioWorkletProcessor = (dependencies, faustData, register = true) => {
336
+ const { registerProcessor, AudioWorkletProcessor, sampleRate } = globalThis;
337
+ const {
338
+ FaustBaseWebAudioDsp: FaustBaseWebAudioDsp2,
339
+ FaustWasmInstantiator: FaustWasmInstantiator2,
340
+ FaustMonoWebAudioDsp: FaustMonoWebAudioDsp2,
341
+ FaustAudioWorkletProcessorCommunicator: FaustAudioWorkletProcessorCommunicator2,
342
+ FFTUtils
343
+ } = dependencies;
344
+ const {
345
+ processorName,
346
+ dspName,
347
+ dspMeta,
348
+ fftOptions
349
+ } = faustData;
350
+ const {
351
+ windowFunctions,
352
+ getFFT,
353
+ fftToSignal,
354
+ signalToFFT,
355
+ signalToNoFFT
356
+ } = FFTUtils;
357
+ const ceil = (x, to) => Math.abs(to) < 1 ? Math.ceil(x * (1 / to)) / (1 / to) : Math.ceil(x / to) * to;
358
+ const mod = (x, y) => (x % y + y) % y;
359
+ const apply = (array, windowFunction) => {
360
+ for (let i = 0; i < array.length; i++) {
361
+ array[i] *= windowFunction(i, array.length);
362
+ }
363
+ };
364
+ const fftParamKeywords = ["/fftSize", "/fftHopSize", "/fftOverlap", "/windowFunction", "/noIFFT"];
365
+ const setTypedArray = (to, from, offsetTo = 0, offsetFrom = 0) => {
366
+ const toLength = to.length;
367
+ const fromLength = from.length;
368
+ const spillLength = Math.min(toLength, fromLength);
369
+ let spilled = 0;
370
+ let $to = mod(offsetTo, toLength) || 0;
371
+ let $from = mod(offsetFrom, fromLength) || 0;
372
+ while (spilled < spillLength) {
373
+ const $spillLength = Math.min(spillLength - spilled, toLength - $to, fromLength - $from);
374
+ const $fromEnd = $from + $spillLength;
375
+ if ($from === 0 && $fromEnd === fromLength)
376
+ to.set(from, $to);
377
+ else
378
+ to.set(from.subarray($from, $fromEnd), $to);
379
+ $to = ($to + $spillLength) % toLength;
380
+ $from = $fromEnd % fromLength;
381
+ spilled += $spillLength;
382
+ }
383
+ return $to;
384
+ };
385
+ const analyseParameters = (item) => {
386
+ const isFFTReserved = "address" in item && !!fftParamKeywords.find((k) => item.address.endsWith(k));
387
+ if (isFFTReserved)
388
+ return null;
389
+ if (item.type === "vslider" || item.type === "hslider" || item.type === "nentry") {
390
+ return { name: item.address, defaultValue: item.init || 0, minValue: item.min || 0, maxValue: item.max || 0 };
391
+ } else if (item.type === "button" || item.type === "checkbox") {
392
+ return { name: item.address, defaultValue: item.init || 0, minValue: 0, maxValue: 1 };
393
+ }
394
+ return null;
395
+ };
396
+ class FaustFFTAudioWorkletProcessor extends AudioWorkletProcessor {
397
+ constructor(options) {
398
+ super(options);
399
+ this.paramValuesCache = {};
400
+ this.destroyed = false;
401
+ /** Pointer of next start sample to write of the FFT input window */
402
+ this.$inputWrite = 0;
403
+ /** Pointer of next start sample to read of the FFT input window */
404
+ this.$inputRead = 0;
405
+ /** Pointer of next start sample to write of the FFT output window */
406
+ this.$outputWrite = 0;
407
+ /** Pointer of next start sample to read of the FFT output window */
408
+ this.$outputRead = 0;
409
+ /** Not perform in IFFT when reconstruct the audio signal */
410
+ this.noIFFT = false;
411
+ /** audio data from input, array of channels */
412
+ this.fftInput = [];
413
+ /** audio data for output, array of channels */
414
+ this.fftOutput = [];
415
+ /** FFT Overlaps, 1 means no overlap */
416
+ this.fftOverlap = 0;
417
+ this.fftHopSize = 0;
418
+ this.fftSize = 0;
419
+ this.fftBufferSize = 0;
420
+ this.fPlotHandler = null;
421
+ this.fCachedEvents = [];
422
+ this.fBufferNum = 0;
423
+ this.soundfiles = {};
424
+ this.windowFunction = null;
425
+ this.handleMessageAux = (e) => {
426
+ var _a, _b, _c;
427
+ const msg = e.data;
428
+ switch (msg.type) {
429
+ case "midi":
430
+ this.midiMessage(msg.data);
431
+ break;
432
+ case "ctrlChange":
433
+ this.ctrlChange(msg.data[0], msg.data[1], msg.data[2]);
434
+ break;
435
+ case "pitchWheel":
436
+ this.pitchWheel(msg.data[0], msg.data[1]);
437
+ break;
438
+ case "param":
439
+ this.setParamValue(msg.data.path, msg.data.value);
440
+ break;
441
+ case "setPlotHandler": {
442
+ if (msg.data) {
443
+ this.fPlotHandler = (output, index, events) => {
444
+ if (events)
445
+ this.fCachedEvents.push(...events);
446
+ };
447
+ } else {
448
+ this.fPlotHandler = null;
449
+ }
450
+ (_a = this.fDSPCode) == null ? void 0 : _a.setPlotHandler(this.fPlotHandler);
451
+ break;
452
+ }
453
+ case "setupWamEventHandler": {
454
+ this.setupWamEventHandler();
455
+ break;
456
+ }
457
+ case "start": {
458
+ (_b = this.fDSPCode) == null ? void 0 : _b.start();
459
+ break;
460
+ }
461
+ case "stop": {
462
+ (_c = this.fDSPCode) == null ? void 0 : _c.stop();
463
+ break;
464
+ }
465
+ case "destroy": {
466
+ this.port.close();
467
+ this.destroy();
468
+ break;
469
+ }
470
+ default:
471
+ break;
472
+ }
473
+ };
474
+ this.port.addEventListener("message", this.handleMessageAux);
475
+ this.port.start();
476
+ this.communicator = new FaustAudioWorkletProcessorCommunicator2(this.port);
477
+ const { parameterDescriptors } = this.constructor;
478
+ parameterDescriptors.forEach((pd) => {
479
+ this.paramValuesCache[pd.name] = pd.defaultValue || 0;
480
+ });
481
+ const { factory, sampleSize } = options.processorOptions;
482
+ this.dspInstance = FaustWasmInstantiator2.createSyncMonoDSPInstance(factory);
483
+ this.sampleSize = sampleSize;
484
+ this.soundfiles = factory.soundfiles;
485
+ this.initFFT();
486
+ const { moduleId, instanceId } = options.processorOptions;
487
+ if (!moduleId || !instanceId)
488
+ return;
489
+ this.wamInfo = { moduleId, instanceId };
490
+ }
491
+ get fftProcessorBufferSize() {
492
+ return this.fftSize / 2 + 1;
493
+ }
494
+ async initFFT() {
495
+ this.FFT = await getFFT();
496
+ await this.createFFTProcessor();
497
+ return true;
498
+ }
499
+ static get parameterDescriptors() {
500
+ const params = [];
501
+ const callback = (item) => {
502
+ const param = analyseParameters(item);
503
+ if (param)
504
+ params.push(param);
505
+ };
506
+ FaustBaseWebAudioDsp2.parseUI(dspMeta.ui, callback);
507
+ return [
508
+ ...params,
509
+ {
510
+ defaultValue: (fftOptions == null ? void 0 : fftOptions.fftSize) || 1024,
511
+ maxValue: 2 ** 32,
512
+ minValue: 2,
513
+ name: "fftSize"
514
+ },
515
+ {
516
+ defaultValue: (fftOptions == null ? void 0 : fftOptions.fftOverlap) || 2,
517
+ maxValue: 32,
518
+ minValue: 1,
519
+ name: "fftOverlap"
520
+ },
521
+ {
522
+ defaultValue: typeof (fftOptions == null ? void 0 : fftOptions.defaultWindowFunction) === "number" ? fftOptions.defaultWindowFunction + 1 : 0,
523
+ maxValue: (windowFunctions == null ? void 0 : windowFunctions.length) || 0,
524
+ minValue: 0,
525
+ name: "windowFunction"
526
+ },
527
+ {
528
+ defaultValue: +!!(fftOptions == null ? void 0 : fftOptions.noIFFT) || 0,
529
+ maxValue: 1,
530
+ minValue: 0,
531
+ name: "noIFFT"
532
+ }
533
+ ];
534
+ }
535
+ setupWamEventHandler() {
536
+ var _a;
537
+ if (!this.wamInfo)
538
+ return;
539
+ const { moduleId, instanceId } = this.wamInfo;
540
+ const { webAudioModules } = globalThis;
541
+ const ModuleScope = webAudioModules.getModuleScope(moduleId);
542
+ const paramMgrProcessor = (_a = ModuleScope == null ? void 0 : ModuleScope.paramMgrProcessors) == null ? void 0 : _a[instanceId];
543
+ if (!paramMgrProcessor)
544
+ return;
545
+ if (paramMgrProcessor.handleEvent)
546
+ return;
547
+ paramMgrProcessor.handleEvent = (event) => {
548
+ if (event.type === "wam-midi")
549
+ this.midiMessage(event.data.bytes);
550
+ };
551
+ }
552
+ processFFT() {
553
+ let samplesForFFT = mod(this.$inputWrite - this.$inputRead, this.fftBufferSize) || this.fftBufferSize;
554
+ while (samplesForFFT >= this.fftSize) {
555
+ let fftProcessorOutputs = [];
556
+ this.fDSPCode.compute((inputs) => {
557
+ for (let i = 0; i < Math.min(this.fftInput.length, Math.ceil(inputs.length / 3)); i++) {
558
+ const ffted = this.rfft.forward((fftBuffer) => {
559
+ setTypedArray(fftBuffer, this.fftInput[i], 0, this.$inputRead);
560
+ for (let j = 0; j < fftBuffer.length; j++) {
561
+ fftBuffer[j] *= this.window[j];
562
+ }
563
+ });
564
+ fftToSignal(ffted, inputs[i * 3], inputs[i * 3 + 1], inputs[i * 3 + 2]);
565
+ }
566
+ for (let i = this.fftInput.length * 3; i < inputs.length; i++) {
567
+ if (i % 3 === 2)
568
+ inputs[i].forEach((v, j) => inputs[i][j] = j);
569
+ else
570
+ inputs[i].fill(0);
571
+ }
572
+ }, (outputs) => {
573
+ fftProcessorOutputs = outputs;
574
+ });
575
+ this.$inputRead += this.fftHopSize;
576
+ this.$inputRead %= this.fftBufferSize;
577
+ samplesForFFT -= this.fftHopSize;
578
+ for (let i = 0; i < this.fftOutput.length; i++) {
579
+ let iffted;
580
+ if (this.noIFFT) {
581
+ iffted = this.noIFFTBuffer;
582
+ signalToNoFFT(fftProcessorOutputs[i * 2] || this.fftProcessorZeros, fftProcessorOutputs[i * 2 + 1] || this.fftProcessorZeros, iffted);
583
+ } else {
584
+ iffted = this.rfft.inverse((ifftBuffer) => {
585
+ signalToFFT(fftProcessorOutputs[i * 2] || this.fftProcessorZeros, fftProcessorOutputs[i * 2 + 1] || this.fftProcessorZeros, ifftBuffer);
586
+ });
587
+ }
588
+ for (let j = 0; j < iffted.length; j++) {
589
+ iffted[j] *= this.window[j];
590
+ }
591
+ let $;
592
+ for (let j = 0; j < iffted.length - this.fftHopSize; j++) {
593
+ $ = mod(this.$outputWrite + j, this.fftBufferSize);
594
+ this.fftOutput[i][$] += iffted[j];
595
+ if (i === 0)
596
+ this.windowSumSquare[$] += this.noIFFT ? this.window[j] : this.window[j] ** 2;
597
+ }
598
+ for (let j = iffted.length - this.fftHopSize; j < iffted.length; j++) {
599
+ $ = mod(this.$outputWrite + j, this.fftBufferSize);
600
+ this.fftOutput[i][$] = iffted[j];
601
+ if (i === 0)
602
+ this.windowSumSquare[$] = this.noIFFT ? this.window[j] : this.window[j] ** 2;
603
+ }
604
+ }
605
+ this.$outputWrite += this.fftHopSize;
606
+ this.$outputWrite %= this.fftBufferSize;
607
+ }
608
+ }
609
+ process(inputs, outputs, parameters) {
610
+ if (this.destroyed)
611
+ return false;
612
+ if (!this.FFT)
613
+ return true;
614
+ const input = inputs[0];
615
+ const output = outputs[0];
616
+ const inputChannels = (input == null ? void 0 : input.length) || 0;
617
+ const outputChannels = (output == null ? void 0 : output.length) || 0;
618
+ const bufferSize = (input == null ? void 0 : input.length) ? Math.max(...input.map((c) => c.length)) || 128 : 128;
619
+ this.noIFFT = !!parameters.noIFFT[0];
620
+ this.resetFFT(~~parameters.fftSize[0], ~~parameters.fftOverlap[0], ~~parameters.windowFunction[0], inputChannels, outputChannels, bufferSize);
621
+ if (!this.fDSPCode)
622
+ return true;
623
+ for (const path in parameters) {
624
+ if (!!fftParamKeywords.find((k) => `/${path}`.endsWith(k)))
625
+ continue;
626
+ const [paramValue] = parameters[path];
627
+ if (paramValue !== this.paramValuesCache[path]) {
628
+ this.fDSPCode.setParamValue(path, paramValue);
629
+ this.paramValuesCache[path] = paramValue;
630
+ }
631
+ }
632
+ if (this.communicator.getNewAccDataAvailable()) {
633
+ const acc = this.communicator.getAcc();
634
+ if (acc) {
635
+ this.communicator.setNewAccDataAvailable(false);
636
+ const { invert, ...data } = acc;
637
+ this.propagateAcc(data, invert);
638
+ }
639
+ }
640
+ if (this.communicator.getNewGyrDataAvailable()) {
641
+ const gyr = this.communicator.getGyr();
642
+ if (gyr) {
643
+ this.communicator.setNewGyrDataAvailable(false);
644
+ this.propagateGyr(gyr);
645
+ }
646
+ }
647
+ if (input == null ? void 0 : input.length) {
648
+ let $inputWrite = 0;
649
+ for (let i = 0; i < input.length; i++) {
650
+ const inputWindow = this.fftInput[i];
651
+ const channel = input[i].length ? input[i] : new Float32Array(bufferSize);
652
+ $inputWrite = setTypedArray(inputWindow, channel, this.$inputWrite);
653
+ }
654
+ this.$inputWrite = $inputWrite;
655
+ } else {
656
+ this.$inputWrite += bufferSize;
657
+ this.$inputWrite %= this.fftBufferSize;
658
+ }
659
+ this.processFFT();
660
+ for (let i = 0; i < output.length; i++) {
661
+ setTypedArray(output[i], this.fftOutput[i], 0, this.$outputRead);
662
+ let div = 0;
663
+ for (let j = 0; j < bufferSize; j++) {
664
+ div = this.windowSumSquare[mod(this.$outputRead + j, this.fftBufferSize)];
665
+ output[i][j] /= div < 1e-8 ? 1 : div;
666
+ }
667
+ }
668
+ this.$outputRead += bufferSize;
669
+ this.$outputRead %= this.fftBufferSize;
670
+ if (this.fPlotHandler) {
671
+ this.port.postMessage({ type: "plot", value: output, index: this.fBufferNum++, events: this.fCachedEvents });
672
+ this.fCachedEvents = [];
673
+ }
674
+ return true;
675
+ }
676
+ setParamValue(path, value) {
677
+ var _a;
678
+ (_a = this.fDSPCode) == null ? void 0 : _a.setParamValue(path, value);
679
+ this.paramValuesCache[path] = value;
680
+ }
681
+ midiMessage(data) {
682
+ var _a;
683
+ (_a = this.fDSPCode) == null ? void 0 : _a.midiMessage(data);
684
+ }
685
+ ctrlChange(channel, ctrl, value) {
686
+ var _a;
687
+ (_a = this.fDSPCode) == null ? void 0 : _a.ctrlChange(channel, ctrl, value);
688
+ }
689
+ pitchWheel(channel, wheel) {
690
+ var _a;
691
+ (_a = this.fDSPCode) == null ? void 0 : _a.pitchWheel(channel, wheel);
692
+ }
693
+ propagateAcc(accelerationIncludingGravity, invert = false) {
694
+ this.fDSPCode.propagateAcc(accelerationIncludingGravity, invert);
695
+ }
696
+ propagateGyr(event) {
697
+ this.fDSPCode.propagateGyr(event);
698
+ }
699
+ resetFFT(sizeIn, overlapIn, windowFunctionIn, inputChannels, outputChannels, bufferSize) {
700
+ var _a, _b;
701
+ const fftSize = ~~ceil(Math.max(2, sizeIn || 1024), 2);
702
+ const fftOverlap = ~~Math.min(fftSize, Math.max(1, overlapIn));
703
+ const fftHopSize = ~~Math.max(1, fftSize / fftOverlap);
704
+ const latency = fftSize - Math.min(fftHopSize, bufferSize);
705
+ let windowFunction = null;
706
+ if (windowFunctionIn !== 0) {
707
+ windowFunction = typeof windowFunctions === "object" ? windowFunctions[~~windowFunctionIn - 1] || null : null;
708
+ }
709
+ const fftSizeChanged = fftSize !== this.fftSize;
710
+ const fftOverlapChanged = fftOverlap !== this.fftOverlap;
711
+ if (fftSizeChanged || fftOverlapChanged) {
712
+ this.fftSize = fftSize;
713
+ this.fftOverlap = fftOverlap;
714
+ this.fftHopSize = fftHopSize;
715
+ this.$inputWrite = 0;
716
+ this.$inputRead = 0;
717
+ this.$outputWrite = 0;
718
+ this.$outputRead = -latency;
719
+ this.fftBufferSize = Math.max(fftSize * 2 - this.fftHopSize, bufferSize * 2);
720
+ if (!fftSizeChanged && this.fftHopSizeParam)
721
+ (_a = this.fDSPCode) == null ? void 0 : _a.setParamValue(this.fftHopSizeParam, this.fftHopSize);
722
+ }
723
+ if (fftSizeChanged) {
724
+ (_b = this.rfft) == null ? void 0 : _b.dispose();
725
+ this.rfft = new this.FFT(fftSize);
726
+ this.noIFFTBuffer = new Float32Array(this.fftSize);
727
+ this.createFFTProcessor();
728
+ }
729
+ if (fftSizeChanged || fftOverlapChanged || windowFunction !== this.windowFunction) {
730
+ this.windowFunction = windowFunction;
731
+ this.window = new Float32Array(fftSize);
732
+ this.window.fill(1);
733
+ if (windowFunction)
734
+ apply(this.window, windowFunction);
735
+ this.windowSumSquare = new Float32Array(this.fftBufferSize);
736
+ }
737
+ if (this.fftInput.length > inputChannels) {
738
+ this.fftInput.splice(inputChannels);
739
+ }
740
+ if (this.fftOutput.length > outputChannels) {
741
+ this.fftOutput.splice(outputChannels);
742
+ }
743
+ if (fftSizeChanged || fftOverlapChanged) {
744
+ for (let i = 0; i < inputChannels; i++) {
745
+ this.fftInput[i] = new Float32Array(this.fftBufferSize);
746
+ }
747
+ for (let i = 0; i < outputChannels; i++) {
748
+ this.fftOutput[i] = new Float32Array(this.fftBufferSize);
749
+ }
750
+ } else {
751
+ if (this.fftInput.length < inputChannels) {
752
+ for (let i = this.fftInput.length; i < inputChannels; i++) {
753
+ this.fftInput[i] = new Float32Array(this.fftBufferSize);
754
+ }
755
+ }
756
+ if (this.fftOutput.length < outputChannels) {
757
+ for (let i = this.fftOutput.length; i < outputChannels; i++) {
758
+ this.fftOutput[i] = new Float32Array(this.fftBufferSize);
759
+ }
760
+ }
761
+ }
762
+ }
763
+ async createFFTProcessor() {
764
+ var _a, _b;
765
+ (_a = this.fDSPCode) == null ? void 0 : _a.stop();
766
+ (_b = this.fDSPCode) == null ? void 0 : _b.destroy();
767
+ this.fDSPCode = new FaustMonoWebAudioDsp2(this.dspInstance, sampleRate, this.sampleSize, this.fftProcessorBufferSize, this.soundfiles);
768
+ this.fDSPCode.setOutputParamHandler((path, value) => this.port.postMessage({ path, value, type: "param" }));
769
+ this.fDSPCode.setPlotHandler(this.fPlotHandler);
770
+ const params = this.fDSPCode.getParams();
771
+ this.fDSPCode.start();
772
+ for (const path in this.paramValuesCache) {
773
+ if (!!fftParamKeywords.find((k) => `/${path}`.endsWith(k)))
774
+ continue;
775
+ this.fDSPCode.setParamValue(path, this.paramValuesCache[path]);
776
+ }
777
+ const fftSizeParam = params.find((s) => s.endsWith("/fftSize"));
778
+ if (fftSizeParam)
779
+ this.fDSPCode.setParamValue(fftSizeParam, this.fftSize);
780
+ this.fftHopSizeParam = params.find((s) => s.endsWith("/fftHopSize"));
781
+ if (this.fftHopSizeParam)
782
+ this.fDSPCode.setParamValue(this.fftHopSizeParam, this.fftHopSize);
783
+ this.fftProcessorZeros = new Float32Array(this.fftProcessorBufferSize);
784
+ }
785
+ destroy() {
786
+ var _a, _b, _c;
787
+ (_a = this.fDSPCode) == null ? void 0 : _a.stop();
788
+ (_b = this.fDSPCode) == null ? void 0 : _b.destroy();
789
+ (_c = this.rfft) == null ? void 0 : _c.dispose();
790
+ this.destroyed = true;
791
+ }
792
+ }
793
+ const Processor = FaustFFTAudioWorkletProcessor;
794
+ if (register) {
795
+ try {
796
+ registerProcessor(processorName || dspName || "myfftdsp", Processor);
797
+ } catch (error) {
798
+ console.warn(error);
799
+ }
800
+ }
801
+ return FaustFFTAudioWorkletProcessor;
802
+ };
803
+ var FaustFFTAudioWorkletProcessor_default = getFaustFFTAudioWorkletProcessor;
804
+
805
+ // node_modules/tslib/tslib.es6.mjs
806
+ function __awaiter(thisArg, _arguments, P, generator) {
807
+ function adopt(value) {
808
+ return value instanceof P ? value : new P(function(resolve) {
809
+ resolve(value);
810
+ });
811
+ }
812
+ return new (P || (P = Promise))(function(resolve, reject) {
813
+ function fulfilled(value) {
814
+ try {
815
+ step(generator.next(value));
816
+ } catch (e) {
817
+ reject(e);
818
+ }
819
+ }
820
+ function rejected(value) {
821
+ try {
822
+ step(generator["throw"](value));
823
+ } catch (e) {
824
+ reject(e);
825
+ }
826
+ }
827
+ function step(result) {
828
+ result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected);
829
+ }
830
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
831
+ });
832
+ }
833
+ function __generator(thisArg, body) {
834
+ var _ = { label: 0, sent: function() {
835
+ if (t[0] & 1)
836
+ throw t[1];
837
+ return t[1];
838
+ }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
839
+ return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() {
840
+ return this;
841
+ }), g;
842
+ function verb(n) {
843
+ return function(v) {
844
+ return step([n, v]);
845
+ };
846
+ }
847
+ function step(op) {
848
+ if (f)
849
+ throw new TypeError("Generator is already executing.");
850
+ while (g && (g = 0, op[0] && (_ = 0)), _)
851
+ try {
852
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done)
853
+ return t;
854
+ if (y = 0, t)
855
+ op = [op[0] & 2, t.value];
856
+ switch (op[0]) {
857
+ case 0:
858
+ case 1:
859
+ t = op;
860
+ break;
861
+ case 4:
862
+ _.label++;
863
+ return { value: op[1], done: false };
864
+ case 5:
865
+ _.label++;
866
+ y = op[1];
867
+ op = [0];
868
+ continue;
869
+ case 7:
870
+ op = _.ops.pop();
871
+ _.trys.pop();
872
+ continue;
873
+ default:
874
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
875
+ _ = 0;
876
+ continue;
877
+ }
878
+ if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) {
879
+ _.label = op[1];
880
+ break;
881
+ }
882
+ if (op[0] === 6 && _.label < t[1]) {
883
+ _.label = t[1];
884
+ t = op;
885
+ break;
886
+ }
887
+ if (t && _.label < t[2]) {
888
+ _.label = t[2];
889
+ _.ops.push(op);
890
+ break;
891
+ }
892
+ if (t[2])
893
+ _.ops.pop();
894
+ _.trys.pop();
895
+ continue;
896
+ }
897
+ op = body.call(thisArg, _);
898
+ } catch (e) {
899
+ op = [6, e];
900
+ y = 0;
901
+ } finally {
902
+ f = t = 0;
903
+ }
904
+ if (op[0] & 5)
905
+ throw op[1];
906
+ return { value: op[0] ? op[1] : void 0, done: true };
907
+ }
908
+ }
909
+
910
+ // node_modules/@aws-crypto/sha256-js/build/module/constants.js
911
+ var BLOCK_SIZE = 64;
912
+ var DIGEST_LENGTH = 32;
913
+ var KEY = new Uint32Array([
914
+ 1116352408,
915
+ 1899447441,
916
+ 3049323471,
917
+ 3921009573,
918
+ 961987163,
919
+ 1508970993,
920
+ 2453635748,
921
+ 2870763221,
922
+ 3624381080,
923
+ 310598401,
924
+ 607225278,
925
+ 1426881987,
926
+ 1925078388,
927
+ 2162078206,
928
+ 2614888103,
929
+ 3248222580,
930
+ 3835390401,
931
+ 4022224774,
932
+ 264347078,
933
+ 604807628,
934
+ 770255983,
935
+ 1249150122,
936
+ 1555081692,
937
+ 1996064986,
938
+ 2554220882,
939
+ 2821834349,
940
+ 2952996808,
941
+ 3210313671,
942
+ 3336571891,
943
+ 3584528711,
944
+ 113926993,
945
+ 338241895,
946
+ 666307205,
947
+ 773529912,
948
+ 1294757372,
949
+ 1396182291,
950
+ 1695183700,
951
+ 1986661051,
952
+ 2177026350,
953
+ 2456956037,
954
+ 2730485921,
955
+ 2820302411,
956
+ 3259730800,
957
+ 3345764771,
958
+ 3516065817,
959
+ 3600352804,
960
+ 4094571909,
961
+ 275423344,
962
+ 430227734,
963
+ 506948616,
964
+ 659060556,
965
+ 883997877,
966
+ 958139571,
967
+ 1322822218,
968
+ 1537002063,
969
+ 1747873779,
970
+ 1955562222,
971
+ 2024104815,
972
+ 2227730452,
973
+ 2361852424,
974
+ 2428436474,
975
+ 2756734187,
976
+ 3204031479,
977
+ 3329325298
978
+ ]);
979
+ var INIT = [
980
+ 1779033703,
981
+ 3144134277,
982
+ 1013904242,
983
+ 2773480762,
984
+ 1359893119,
985
+ 2600822924,
986
+ 528734635,
987
+ 1541459225
988
+ ];
989
+ var MAX_HASHABLE_LENGTH = Math.pow(2, 53) - 1;
990
+
991
+ // node_modules/@aws-crypto/sha256-js/build/module/RawSha256.js
992
+ var RawSha256 = (
993
+ /** @class */
994
+ function() {
995
+ function RawSha2562() {
996
+ this.state = Int32Array.from(INIT);
997
+ this.temp = new Int32Array(64);
998
+ this.buffer = new Uint8Array(64);
999
+ this.bufferLength = 0;
1000
+ this.bytesHashed = 0;
1001
+ this.finished = false;
1002
+ }
1003
+ RawSha2562.prototype.update = function(data) {
1004
+ if (this.finished) {
1005
+ throw new Error("Attempted to update an already finished hash.");
1006
+ }
1007
+ var position = 0;
1008
+ var byteLength = data.byteLength;
1009
+ this.bytesHashed += byteLength;
1010
+ if (this.bytesHashed * 8 > MAX_HASHABLE_LENGTH) {
1011
+ throw new Error("Cannot hash more than 2^53 - 1 bits");
1012
+ }
1013
+ while (byteLength > 0) {
1014
+ this.buffer[this.bufferLength++] = data[position++];
1015
+ byteLength--;
1016
+ if (this.bufferLength === BLOCK_SIZE) {
1017
+ this.hashBuffer();
1018
+ this.bufferLength = 0;
1019
+ }
1020
+ }
1021
+ };
1022
+ RawSha2562.prototype.digest = function() {
1023
+ if (!this.finished) {
1024
+ var bitsHashed = this.bytesHashed * 8;
1025
+ var bufferView = new DataView(this.buffer.buffer, this.buffer.byteOffset, this.buffer.byteLength);
1026
+ var undecoratedLength = this.bufferLength;
1027
+ bufferView.setUint8(this.bufferLength++, 128);
1028
+ if (undecoratedLength % BLOCK_SIZE >= BLOCK_SIZE - 8) {
1029
+ for (var i = this.bufferLength; i < BLOCK_SIZE; i++) {
1030
+ bufferView.setUint8(i, 0);
1031
+ }
1032
+ this.hashBuffer();
1033
+ this.bufferLength = 0;
1034
+ }
1035
+ for (var i = this.bufferLength; i < BLOCK_SIZE - 8; i++) {
1036
+ bufferView.setUint8(i, 0);
1037
+ }
1038
+ bufferView.setUint32(BLOCK_SIZE - 8, Math.floor(bitsHashed / 4294967296), true);
1039
+ bufferView.setUint32(BLOCK_SIZE - 4, bitsHashed);
1040
+ this.hashBuffer();
1041
+ this.finished = true;
1042
+ }
1043
+ var out = new Uint8Array(DIGEST_LENGTH);
1044
+ for (var i = 0; i < 8; i++) {
1045
+ out[i * 4] = this.state[i] >>> 24 & 255;
1046
+ out[i * 4 + 1] = this.state[i] >>> 16 & 255;
1047
+ out[i * 4 + 2] = this.state[i] >>> 8 & 255;
1048
+ out[i * 4 + 3] = this.state[i] >>> 0 & 255;
1049
+ }
1050
+ return out;
1051
+ };
1052
+ RawSha2562.prototype.hashBuffer = function() {
1053
+ var _a = this, buffer = _a.buffer, state = _a.state;
1054
+ var state0 = state[0], state1 = state[1], state2 = state[2], state3 = state[3], state4 = state[4], state5 = state[5], state6 = state[6], state7 = state[7];
1055
+ for (var i = 0; i < BLOCK_SIZE; i++) {
1056
+ if (i < 16) {
1057
+ this.temp[i] = (buffer[i * 4] & 255) << 24 | (buffer[i * 4 + 1] & 255) << 16 | (buffer[i * 4 + 2] & 255) << 8 | buffer[i * 4 + 3] & 255;
1058
+ } else {
1059
+ var u = this.temp[i - 2];
1060
+ var t1_1 = (u >>> 17 | u << 15) ^ (u >>> 19 | u << 13) ^ u >>> 10;
1061
+ u = this.temp[i - 15];
1062
+ var t2_1 = (u >>> 7 | u << 25) ^ (u >>> 18 | u << 14) ^ u >>> 3;
1063
+ this.temp[i] = (t1_1 + this.temp[i - 7] | 0) + (t2_1 + this.temp[i - 16] | 0);
1064
+ }
1065
+ var t1 = (((state4 >>> 6 | state4 << 26) ^ (state4 >>> 11 | state4 << 21) ^ (state4 >>> 25 | state4 << 7)) + (state4 & state5 ^ ~state4 & state6) | 0) + (state7 + (KEY[i] + this.temp[i] | 0) | 0) | 0;
1066
+ var t2 = ((state0 >>> 2 | state0 << 30) ^ (state0 >>> 13 | state0 << 19) ^ (state0 >>> 22 | state0 << 10)) + (state0 & state1 ^ state0 & state2 ^ state1 & state2) | 0;
1067
+ state7 = state6;
1068
+ state6 = state5;
1069
+ state5 = state4;
1070
+ state4 = state3 + t1 | 0;
1071
+ state3 = state2;
1072
+ state2 = state1;
1073
+ state1 = state0;
1074
+ state0 = t1 + t2 | 0;
1075
+ }
1076
+ state[0] += state0;
1077
+ state[1] += state1;
1078
+ state[2] += state2;
1079
+ state[3] += state3;
1080
+ state[4] += state4;
1081
+ state[5] += state5;
1082
+ state[6] += state6;
1083
+ state[7] += state7;
1084
+ };
1085
+ return RawSha2562;
1086
+ }()
1087
+ );
1088
+
1089
+ // node_modules/@smithy/util-utf8/dist-es/fromUtf8.browser.js
1090
+ var fromUtf8 = (input) => new TextEncoder().encode(input);
1091
+
1092
+ // node_modules/@aws-crypto/util/build/module/convertToBuffer.js
1093
+ var fromUtf82 = typeof Buffer !== "undefined" && Buffer.from ? function(input) {
1094
+ return Buffer.from(input, "utf8");
1095
+ } : fromUtf8;
1096
+ function convertToBuffer(data) {
1097
+ if (data instanceof Uint8Array)
1098
+ return data;
1099
+ if (typeof data === "string") {
1100
+ return fromUtf82(data);
1101
+ }
1102
+ if (ArrayBuffer.isView(data)) {
1103
+ return new Uint8Array(data.buffer, data.byteOffset, data.byteLength / Uint8Array.BYTES_PER_ELEMENT);
1104
+ }
1105
+ return new Uint8Array(data);
1106
+ }
1107
+
1108
+ // node_modules/@aws-crypto/util/build/module/isEmptyData.js
1109
+ function isEmptyData(data) {
1110
+ if (typeof data === "string") {
1111
+ return data.length === 0;
1112
+ }
1113
+ return data.byteLength === 0;
1114
+ }
1115
+
1116
+ // node_modules/@aws-crypto/sha256-js/build/module/jsSha256.js
1117
+ var Sha256 = (
1118
+ /** @class */
1119
+ function() {
1120
+ function Sha2562(secret) {
1121
+ this.secret = secret;
1122
+ this.hash = new RawSha256();
1123
+ this.reset();
1124
+ }
1125
+ Sha2562.prototype.update = function(toHash) {
1126
+ if (isEmptyData(toHash) || this.error) {
1127
+ return;
1128
+ }
1129
+ try {
1130
+ this.hash.update(convertToBuffer(toHash));
1131
+ } catch (e) {
1132
+ this.error = e;
1133
+ }
1134
+ };
1135
+ Sha2562.prototype.digestSync = function() {
1136
+ if (this.error) {
1137
+ throw this.error;
1138
+ }
1139
+ if (this.outer) {
1140
+ if (!this.outer.finished) {
1141
+ this.outer.update(this.hash.digest());
1142
+ }
1143
+ return this.outer.digest();
1144
+ }
1145
+ return this.hash.digest();
1146
+ };
1147
+ Sha2562.prototype.digest = function() {
1148
+ return __awaiter(this, void 0, void 0, function() {
1149
+ return __generator(this, function(_a) {
1150
+ return [2, this.digestSync()];
1151
+ });
1152
+ });
1153
+ };
1154
+ Sha2562.prototype.reset = function() {
1155
+ this.hash = new RawSha256();
1156
+ if (this.secret) {
1157
+ this.outer = new RawSha256();
1158
+ var inner = bufferFromSecret(this.secret);
1159
+ var outer = new Uint8Array(BLOCK_SIZE);
1160
+ outer.set(inner);
1161
+ for (var i = 0; i < BLOCK_SIZE; i++) {
1162
+ inner[i] ^= 54;
1163
+ outer[i] ^= 92;
1164
+ }
1165
+ this.hash.update(inner);
1166
+ this.outer.update(outer);
1167
+ for (var i = 0; i < inner.byteLength; i++) {
1168
+ inner[i] = 0;
1169
+ }
1170
+ }
1171
+ };
1172
+ return Sha2562;
1173
+ }()
1174
+ );
1175
+ function bufferFromSecret(secret) {
1176
+ var input = convertToBuffer(secret);
1177
+ if (input.byteLength > BLOCK_SIZE) {
1178
+ var bufferHash = new RawSha256();
1179
+ bufferHash.update(input);
1180
+ input = bufferHash.digest();
1181
+ }
1182
+ var buffer = new Uint8Array(BLOCK_SIZE);
1183
+ buffer.set(input);
1184
+ return buffer;
1185
+ }
1186
+
1187
+ // src/FaustCompiler.ts
1188
+ var ab2str = (buf) => String.fromCharCode.apply(null, buf);
1189
+ var str2ab = (str) => {
1190
+ const buf = new ArrayBuffer(str.length);
1191
+ const bufView = new Uint8Array(buf);
1192
+ for (let i = 0, strLen = str.length; i < strLen; i++) {
1193
+ bufView[i] = str.charCodeAt(i);
1194
+ }
1195
+ return bufView;
1196
+ };
1197
+ var sha256 = async (str) => {
1198
+ const sha2562 = new Sha256();
1199
+ sha2562.update(str);
1200
+ const hashArray = Array.from(await sha2562.digest());
1201
+ const hashHex = hashArray.map((b) => b.toString(16).padStart(2, "0")).join("");
1202
+ return hashHex;
1203
+ };
1204
+ var _FaustCompiler = class _FaustCompiler {
1205
+ /**
1206
+ * Get a stringified DSP factories table
1207
+ */
1208
+ static serializeDSPFactories() {
1209
+ const table = {};
1210
+ this.gFactories.forEach((factory, shaKey) => {
1211
+ const { code, json, poly } = factory;
1212
+ table[shaKey] = { code: btoa(ab2str(code)), json: JSON.parse(json), poly };
1213
+ });
1214
+ return table;
1215
+ }
1216
+ /**
1217
+ * Get a stringified DSP factories table as string
1218
+ */
1219
+ static stringifyDSPFactories() {
1220
+ return JSON.stringify(this.serializeDSPFactories());
1221
+ }
1222
+ /**
1223
+ * Import a DSP factories table
1224
+ */
1225
+ static deserializeDSPFactories(table) {
1226
+ const awaited = [];
1227
+ for (const shaKey in table) {
1228
+ const factory = table[shaKey];
1229
+ const { code, json, poly } = factory;
1230
+ const ab = str2ab(atob(code));
1231
+ awaited.push(WebAssembly.compile(ab).then((module) => this.gFactories.set(shaKey, { shaKey, cfactory: 0, code: ab, module, json: JSON.stringify(json), poly, soundfiles: {} })));
1232
+ }
1233
+ return Promise.all(awaited);
1234
+ }
1235
+ /**
1236
+ * Import a stringified DSP factories table
1237
+ */
1238
+ static importDSPFactories(tableStr) {
1239
+ const table = JSON.parse(tableStr);
1240
+ return this.deserializeDSPFactories(table);
1241
+ }
1242
+ constructor(libFaust) {
1243
+ this.fLibFaust = libFaust;
1244
+ this.fErrorMessage = "";
1245
+ }
1246
+ intVec2intArray(vec) {
1247
+ const size = vec.size();
1248
+ const ui8Code = new Uint8Array(size);
1249
+ for (let i = 0; i < size; i++) {
1250
+ ui8Code[i] = vec.get(i);
1251
+ }
1252
+ return ui8Code;
1253
+ }
1254
+ async createDSPFactory(name, code, args, poly) {
1255
+ if (_FaustCompiler.gFactories.size > 10) {
1256
+ _FaustCompiler.gFactories.clear();
1257
+ }
1258
+ let shaKey = await sha256(name + code + args + (poly ? "poly" : "mono"));
1259
+ if (_FaustCompiler.gFactories.has(shaKey)) {
1260
+ return _FaustCompiler.gFactories.get(shaKey) || null;
1261
+ } else {
1262
+ try {
1263
+ const faustDspWasm = this.fLibFaust.createDSPFactory(name, code, args, !poly);
1264
+ const ui8Code = this.intVec2intArray(faustDspWasm.data);
1265
+ faustDspWasm.data.delete();
1266
+ const module = await WebAssembly.compile(ui8Code);
1267
+ const factory = { shaKey, cfactory: faustDspWasm.cfactory, code: ui8Code, module, json: faustDspWasm.json, poly, soundfiles: {} };
1268
+ this.deleteDSPFactory(factory);
1269
+ _FaustCompiler.gFactories.set(shaKey, factory);
1270
+ return factory;
1271
+ } catch (e) {
1272
+ this.fErrorMessage = this.fLibFaust.getErrorAfterException();
1273
+ this.fLibFaust.cleanupAfterException();
1274
+ throw this.fErrorMessage ? new Error(this.fErrorMessage) : e;
1275
+ }
1276
+ }
1277
+ }
1278
+ version() {
1279
+ return this.fLibFaust.version();
1280
+ }
1281
+ getErrorMessage() {
1282
+ return this.fErrorMessage;
1283
+ }
1284
+ async createMonoDSPFactory(name, code, args) {
1285
+ return this.createDSPFactory(name, code, args, false);
1286
+ }
1287
+ async createPolyDSPFactory(name, code, args) {
1288
+ return this.createDSPFactory(name, code, args, true);
1289
+ }
1290
+ deleteDSPFactory(factory) {
1291
+ this.fLibFaust.deleteDSPFactory(factory.cfactory);
1292
+ factory.cfactory = 0;
1293
+ }
1294
+ expandDSP(code, args) {
1295
+ try {
1296
+ return this.fLibFaust.expandDSP("FaustDSP", code, args);
1297
+ } catch (e) {
1298
+ this.fErrorMessage = this.fLibFaust.getErrorAfterException();
1299
+ this.fLibFaust.cleanupAfterException();
1300
+ throw this.fErrorMessage ? new Error(this.fErrorMessage) : e;
1301
+ }
1302
+ }
1303
+ generateAuxFiles(name, code, args) {
1304
+ try {
1305
+ return this.fLibFaust.generateAuxFiles(name, code, args);
1306
+ } catch (e) {
1307
+ this.fErrorMessage = this.fLibFaust.getErrorAfterException();
1308
+ this.fLibFaust.cleanupAfterException();
1309
+ throw this.fErrorMessage ? new Error(this.fErrorMessage) : e;
1310
+ }
1311
+ }
1312
+ deleteAllDSPFactories() {
1313
+ this.fLibFaust.deleteAllDSPFactories();
1314
+ }
1315
+ fs() {
1316
+ return this.fLibFaust.fs();
1317
+ }
1318
+ async getAsyncInternalMixerModule(isDouble = false) {
1319
+ const bufferKey = isDouble ? "mixer64Buffer" : "mixer32Buffer";
1320
+ const moduleKey = isDouble ? "mixer64Module" : "mixer32Module";
1321
+ if (this[moduleKey])
1322
+ return { mixerBuffer: this[bufferKey], mixerModule: this[moduleKey] };
1323
+ const path = isDouble ? "/usr/rsrc/mixer64.wasm" : "/usr/rsrc/mixer32.wasm";
1324
+ const mixerBuffer = this.fs().readFile(path, { encoding: "binary" });
1325
+ this[bufferKey] = mixerBuffer;
1326
+ const mixerModule = await WebAssembly.compile(mixerBuffer);
1327
+ this[moduleKey] = mixerModule;
1328
+ return { mixerBuffer, mixerModule };
1329
+ }
1330
+ getSyncInternalMixerModule(isDouble = false) {
1331
+ const bufferKey = isDouble ? "mixer64Buffer" : "mixer32Buffer";
1332
+ const moduleKey = isDouble ? "mixer64Module" : "mixer32Module";
1333
+ if (this[moduleKey])
1334
+ return { mixerBuffer: this[bufferKey], mixerModule: this[moduleKey] };
1335
+ const path = isDouble ? "/usr/rsrc/mixer64.wasm" : "/usr/rsrc/mixer32.wasm";
1336
+ const mixerBuffer = this.fs().readFile(path, { encoding: "binary" });
1337
+ this[bufferKey] = mixerBuffer;
1338
+ const mixerModule = new WebAssembly.Module(mixerBuffer);
1339
+ this[moduleKey] = mixerModule;
1340
+ return { mixerBuffer, mixerModule };
1341
+ }
1342
+ };
1343
+ _FaustCompiler.gFactories = /* @__PURE__ */ new Map();
1344
+ var FaustCompiler = _FaustCompiler;
1345
+ var FaustCompiler_default = FaustCompiler;
1346
+
1347
+ // src/FaustDspInstance.ts
1348
+ var FaustDspInstance = class {
1349
+ constructor(exports) {
1350
+ this.fExports = exports;
1351
+ }
1352
+ compute($dsp, count, $input, $output) {
1353
+ this.fExports.compute($dsp, count, $input, $output);
1354
+ }
1355
+ getNumInputs($dsp) {
1356
+ return this.fExports.getNumInputs($dsp);
1357
+ }
1358
+ getNumOutputs($dsp) {
1359
+ return this.fExports.getNumOutputs($dsp);
1360
+ }
1361
+ getParamValue($dsp, index) {
1362
+ return this.fExports.getParamValue($dsp, index);
1363
+ }
1364
+ getSampleRate($dsp) {
1365
+ return this.fExports.getSampleRate($dsp);
1366
+ }
1367
+ init($dsp, sampleRate) {
1368
+ this.fExports.init($dsp, sampleRate);
1369
+ }
1370
+ instanceClear($dsp) {
1371
+ this.fExports.instanceClear($dsp);
1372
+ }
1373
+ instanceConstants($dsp, sampleRate) {
1374
+ this.fExports.instanceConstants($dsp, sampleRate);
1375
+ }
1376
+ instanceInit($dsp, sampleRate) {
1377
+ this.fExports.instanceInit($dsp, sampleRate);
1378
+ }
1379
+ instanceResetUserInterface($dsp) {
1380
+ this.fExports.instanceResetUserInterface($dsp);
1381
+ }
1382
+ setParamValue($dsp, index, value) {
1383
+ this.fExports.setParamValue($dsp, index, value);
1384
+ }
1385
+ };
1386
+
1387
+ // src/FaustWasmInstantiator.ts
1388
+ var FaustWasmInstantiator = class {
1389
+ static createWasmImport(memory) {
1390
+ return {
1391
+ env: {
1392
+ memory: memory || new WebAssembly.Memory({ initial: 100 }),
1393
+ memoryBase: 0,
1394
+ tableBase: 0,
1395
+ // Integer version
1396
+ _abs: Math.abs,
1397
+ // Float version
1398
+ _acosf: Math.acos,
1399
+ _asinf: Math.asin,
1400
+ _atanf: Math.atan,
1401
+ _atan2f: Math.atan2,
1402
+ _ceilf: Math.ceil,
1403
+ _cosf: Math.cos,
1404
+ _expf: Math.exp,
1405
+ _floorf: Math.floor,
1406
+ _fmodf: (x, y) => x % y,
1407
+ _logf: Math.log,
1408
+ _log10f: Math.log10,
1409
+ _max_f: Math.max,
1410
+ _min_f: Math.min,
1411
+ _remainderf: (x, y) => x - Math.round(x / y) * y,
1412
+ _powf: Math.pow,
1413
+ _roundf: Math.round,
1414
+ _sinf: Math.sin,
1415
+ _sqrtf: Math.sqrt,
1416
+ _tanf: Math.tan,
1417
+ _acoshf: Math.acosh,
1418
+ _asinhf: Math.asinh,
1419
+ _atanhf: Math.atanh,
1420
+ _coshf: Math.cosh,
1421
+ _sinhf: Math.sinh,
1422
+ _tanhf: Math.tanh,
1423
+ _isnanf: Number.isNaN,
1424
+ _isinff: (x) => !isFinite(x),
1425
+ _copysignf: (x, y) => Math.sign(x) === Math.sign(y) ? x : -x,
1426
+ // Double version
1427
+ _acos: Math.acos,
1428
+ _asin: Math.asin,
1429
+ _atan: Math.atan,
1430
+ _atan2: Math.atan2,
1431
+ _ceil: Math.ceil,
1432
+ _cos: Math.cos,
1433
+ _exp: Math.exp,
1434
+ _floor: Math.floor,
1435
+ _fmod: (x, y) => x % y,
1436
+ _log: Math.log,
1437
+ _log10: Math.log10,
1438
+ _max_: Math.max,
1439
+ _min_: Math.min,
1440
+ _remainder: (x, y) => x - Math.round(x / y) * y,
1441
+ _pow: Math.pow,
1442
+ _round: Math.round,
1443
+ _sin: Math.sin,
1444
+ _sqrt: Math.sqrt,
1445
+ _tan: Math.tan,
1446
+ _acosh: Math.acosh,
1447
+ _asinh: Math.asinh,
1448
+ _atanh: Math.atanh,
1449
+ _cosh: Math.cosh,
1450
+ _sinh: Math.sinh,
1451
+ _tanh: Math.tanh,
1452
+ _isnan: Number.isNaN,
1453
+ _isinf: (x) => !isFinite(x),
1454
+ _copysign: (x, y) => Math.sign(x) === Math.sign(y) ? x : -x,
1455
+ table: new WebAssembly.Table({ initial: 0, element: "anyfunc" })
1456
+ }
1457
+ };
1458
+ }
1459
+ static createWasmMemoryPoly(voicesIn, sampleSize, dspMeta, effectMeta, bufferSize) {
1460
+ const voices = Math.max(4, voicesIn);
1461
+ const ptrSize = sampleSize;
1462
+ const pow2limit = (x) => {
1463
+ let n = 65536;
1464
+ while (n < x) {
1465
+ n *= 2;
1466
+ }
1467
+ return n;
1468
+ };
1469
+ const effectSize = effectMeta ? effectMeta.size : 0;
1470
+ let memorySize = pow2limit(
1471
+ effectSize + dspMeta.size * voices + (dspMeta.inputs + dspMeta.outputs * 2) * (ptrSize + bufferSize * sampleSize)
1472
+ ) / 65536;
1473
+ memorySize = Math.max(2, memorySize);
1474
+ return new WebAssembly.Memory({ initial: memorySize });
1475
+ }
1476
+ static createWasmMemoryMono(sampleSize, dspMeta, bufferSize) {
1477
+ const ptrSize = sampleSize;
1478
+ const memorySize = (dspMeta.size + (dspMeta.inputs + dspMeta.outputs) * (ptrSize + bufferSize * sampleSize)) / 65536;
1479
+ return new WebAssembly.Memory({ initial: memorySize * 2 });
1480
+ }
1481
+ static createMonoDSPInstanceAux(instance, json, mem = null) {
1482
+ const functions = instance.exports;
1483
+ const api = new FaustDspInstance(functions);
1484
+ const memory = mem ? mem : instance.exports.memory;
1485
+ return { memory, api, json };
1486
+ }
1487
+ static createMemoryMono(monoFactory) {
1488
+ const monoMeta = JSON.parse(monoFactory.json);
1489
+ const sampleSize = monoMeta.compile_options.match("-double") ? 8 : 4;
1490
+ return this.createWasmMemoryMono(sampleSize, monoMeta, 8192);
1491
+ }
1492
+ static createMemoryPoly(voices, voiceFactory, effectFactory) {
1493
+ const voiceMeta = JSON.parse(voiceFactory.json);
1494
+ const effectMeta = effectFactory && effectFactory.json ? JSON.parse(effectFactory.json) : null;
1495
+ const sampleSize = voiceMeta.compile_options.match("-double") ? 8 : 4;
1496
+ return this.createWasmMemoryPoly(voices, sampleSize, voiceMeta, effectMeta, 8192);
1497
+ }
1498
+ static createMixerAux(mixerModule, memory) {
1499
+ const mixerImport = {
1500
+ imports: { print: console.log },
1501
+ memory: { memory }
1502
+ };
1503
+ const mixerInstance = new WebAssembly.Instance(mixerModule, mixerImport);
1504
+ const mixerFunctions = mixerInstance.exports;
1505
+ return mixerFunctions;
1506
+ }
1507
+ // Public API
1508
+ static async loadDSPFactory(wasmPath, jsonPath) {
1509
+ const wasmFile = await fetch(wasmPath);
1510
+ if (!wasmFile.ok) {
1511
+ throw new Error(`=> exception raised while running loadDSPFactory, file not found: ${wasmPath}`);
1512
+ }
1513
+ try {
1514
+ const wasmBuffer = await wasmFile.arrayBuffer();
1515
+ const module = await WebAssembly.compile(wasmBuffer);
1516
+ const jsonFile = await fetch(jsonPath);
1517
+ const json = await jsonFile.text();
1518
+ const meta = JSON.parse(json);
1519
+ const cOptions = meta.compile_options;
1520
+ const poly = cOptions.indexOf("wasm-e") !== -1;
1521
+ return { cfactory: 0, code: new Uint8Array(wasmBuffer), module, json, poly };
1522
+ } catch (e) {
1523
+ throw e;
1524
+ }
1525
+ }
1526
+ static async loadDSPMixer(mixerPath, fs) {
1527
+ try {
1528
+ let mixerBuffer = null;
1529
+ if (fs) {
1530
+ mixerBuffer = fs.readFile(mixerPath, { encoding: "binary" });
1531
+ } else {
1532
+ const mixerFile = await fetch(mixerPath);
1533
+ mixerBuffer = await mixerFile.arrayBuffer();
1534
+ }
1535
+ return WebAssembly.compile(mixerBuffer);
1536
+ } catch (e) {
1537
+ throw e;
1538
+ }
1539
+ }
1540
+ static async createAsyncMonoDSPInstance(factory) {
1541
+ const pattern = /"type":\s*"soundfile"/;
1542
+ const isDetected = pattern.test(factory.json);
1543
+ if (isDetected) {
1544
+ const memory = this.createMemoryMono(factory);
1545
+ const instance = await WebAssembly.instantiate(factory.module, this.createWasmImport(memory));
1546
+ return this.createMonoDSPInstanceAux(instance, factory.json, memory);
1547
+ } else {
1548
+ const instance = await WebAssembly.instantiate(factory.module, this.createWasmImport());
1549
+ return this.createMonoDSPInstanceAux(instance, factory.json);
1550
+ }
1551
+ }
1552
+ static createSyncMonoDSPInstance(factory) {
1553
+ const pattern = /"type":\s*"soundfile"/;
1554
+ const isDetected = pattern.test(factory.json);
1555
+ if (isDetected) {
1556
+ const memory = this.createMemoryMono(factory);
1557
+ const instance = new WebAssembly.Instance(factory.module, this.createWasmImport(memory));
1558
+ return this.createMonoDSPInstanceAux(instance, factory.json, memory);
1559
+ } else {
1560
+ const instance = new WebAssembly.Instance(factory.module, this.createWasmImport());
1561
+ return this.createMonoDSPInstanceAux(instance, factory.json);
1562
+ }
1563
+ }
1564
+ static async createAsyncPolyDSPInstance(voiceFactory, mixerModule, voices, effectFactory) {
1565
+ const memory = this.createMemoryPoly(voices, voiceFactory, effectFactory);
1566
+ const voiceInstance = await WebAssembly.instantiate(voiceFactory.module, this.createWasmImport(memory));
1567
+ const voiceFunctions = voiceInstance.exports;
1568
+ const voiceAPI = new FaustDspInstance(voiceFunctions);
1569
+ const mixerAPI = this.createMixerAux(mixerModule, memory);
1570
+ if (effectFactory) {
1571
+ const effectInstance = await WebAssembly.instantiate(effectFactory.module, this.createWasmImport(memory));
1572
+ const effectFunctions = effectInstance.exports;
1573
+ const effectAPI = new FaustDspInstance(effectFunctions);
1574
+ return {
1575
+ memory,
1576
+ voices,
1577
+ voiceAPI,
1578
+ effectAPI,
1579
+ mixerAPI,
1580
+ voiceJSON: voiceFactory.json,
1581
+ effectJSON: effectFactory.json
1582
+ };
1583
+ } else {
1584
+ return {
1585
+ memory,
1586
+ voices,
1587
+ voiceAPI,
1588
+ mixerAPI,
1589
+ voiceJSON: voiceFactory.json
1590
+ };
1591
+ }
1592
+ }
1593
+ static createSyncPolyDSPInstance(voiceFactory, mixerModule, voices, effectFactory) {
1594
+ const memory = this.createMemoryPoly(voices, voiceFactory, effectFactory);
1595
+ const voiceInstance = new WebAssembly.Instance(voiceFactory.module, this.createWasmImport(memory));
1596
+ const voiceFunctions = voiceInstance.exports;
1597
+ const voiceAPI = new FaustDspInstance(voiceFunctions);
1598
+ const mixerAPI = this.createMixerAux(mixerModule, memory);
1599
+ if (effectFactory) {
1600
+ const effectInstance = new WebAssembly.Instance(effectFactory.module, this.createWasmImport(memory));
1601
+ const effectFunctions = effectInstance.exports;
1602
+ const effectAPI = new FaustDspInstance(effectFunctions);
1603
+ return {
1604
+ memory,
1605
+ voices,
1606
+ voiceAPI,
1607
+ effectAPI,
1608
+ mixerAPI,
1609
+ voiceJSON: voiceFactory.json,
1610
+ effectJSON: effectFactory.json
1611
+ };
1612
+ } else {
1613
+ return {
1614
+ memory,
1615
+ voices,
1616
+ voiceAPI,
1617
+ mixerAPI,
1618
+ voiceJSON: voiceFactory.json
1619
+ };
1620
+ }
1621
+ }
1622
+ };
1623
+ var FaustWasmInstantiator_default = FaustWasmInstantiator;
1624
+
1625
+ // src/FaustSensors.ts
1626
+ var FaustSensors = class _FaustSensors {
1627
+ /**
1628
+ * Function to convert a number to an axis type
1629
+ *
1630
+ * @param value number
1631
+ * @returns axis type
1632
+ */
1633
+ static convertToAxis(value) {
1634
+ switch (value) {
1635
+ case 0:
1636
+ return 0 /* x */;
1637
+ case 1:
1638
+ return 1 /* y */;
1639
+ case 2:
1640
+ return 2 /* z */;
1641
+ default:
1642
+ console.error("Error: Axis not found value: " + value);
1643
+ return 0 /* x */;
1644
+ }
1645
+ }
1646
+ /**
1647
+ * Function to convert a number to a curve type
1648
+ *
1649
+ * @param value number
1650
+ * @returns curve type
1651
+ */
1652
+ static convertToCurve(value) {
1653
+ switch (value) {
1654
+ case 0:
1655
+ return 0 /* Up */;
1656
+ case 1:
1657
+ return 1 /* Down */;
1658
+ case 2:
1659
+ return 2 /* UpDown */;
1660
+ case 3:
1661
+ return 3 /* DownUp */;
1662
+ default:
1663
+ console.error("Error: Curve not found value: " + value);
1664
+ return 0 /* Up */;
1665
+ }
1666
+ }
1667
+ static get Range() {
1668
+ if (!this._Range) {
1669
+ this._Range = class {
1670
+ constructor(x, y) {
1671
+ this.fLo = Math.min(x, y);
1672
+ this.fHi = Math.max(x, y);
1673
+ }
1674
+ clip(x) {
1675
+ if (x < this.fLo)
1676
+ return this.fLo;
1677
+ if (x > this.fHi)
1678
+ return this.fHi;
1679
+ return x;
1680
+ }
1681
+ };
1682
+ }
1683
+ return this._Range;
1684
+ }
1685
+ /**
1686
+ * Interpolator class
1687
+ */
1688
+ static get Interpolator() {
1689
+ if (!this._Interpolator) {
1690
+ this._Interpolator = class {
1691
+ constructor(lo, hi, v1, v2) {
1692
+ this.fRange = new _FaustSensors.Range(lo, hi);
1693
+ if (hi !== lo) {
1694
+ this.fCoef = (v2 - v1) / (hi - lo);
1695
+ this.fOffset = v1 - lo * this.fCoef;
1696
+ } else {
1697
+ this.fCoef = 0;
1698
+ this.fOffset = (v1 + v2) / 2;
1699
+ }
1700
+ }
1701
+ returnMappedValue(v) {
1702
+ var x = this.fRange.clip(v);
1703
+ return this.fOffset + x * this.fCoef;
1704
+ }
1705
+ getLowHigh(amin, amax) {
1706
+ return { amin: this.fRange.fLo, amax: this.fRange.fHi };
1707
+ }
1708
+ };
1709
+ }
1710
+ return this._Interpolator;
1711
+ }
1712
+ /**
1713
+ * Interpolator3pt class, combine two interpolators
1714
+ */
1715
+ static get Interpolator3pt() {
1716
+ if (!this._Interpolator3pt) {
1717
+ this._Interpolator3pt = class {
1718
+ constructor(lo, mid, hi, v1, vMid, v2) {
1719
+ this.fSegment1 = new _FaustSensors.Interpolator(lo, mid, v1, vMid);
1720
+ this.fSegment2 = new _FaustSensors.Interpolator(mid, hi, vMid, v2);
1721
+ this.fMid = mid;
1722
+ }
1723
+ returnMappedValue(x) {
1724
+ return x < this.fMid ? this.fSegment1.returnMappedValue(x) : this.fSegment2.returnMappedValue(x);
1725
+ }
1726
+ getMappingValues(amin, amid, amax) {
1727
+ var lowHighSegment1 = this.fSegment1.getLowHigh(amin, amid);
1728
+ var lowHighSegment2 = this.fSegment2.getLowHigh(amid, amax);
1729
+ return { amin: lowHighSegment1.amin, amid: lowHighSegment2.amin, amax: lowHighSegment2.amax };
1730
+ }
1731
+ };
1732
+ }
1733
+ return this._Interpolator3pt;
1734
+ }
1735
+ /**
1736
+ * UpConverter class, convert accelerometer value to Faust value
1737
+ */
1738
+ static get UpConverter() {
1739
+ if (!this._UpConverter) {
1740
+ this._UpConverter = class {
1741
+ constructor(amin, amid, amax, fmin, fmid, fmax) {
1742
+ this.fActive = true;
1743
+ this.fA2F = new _FaustSensors.Interpolator3pt(amin, amid, amax, fmin, fmid, fmax);
1744
+ this.fF2A = new _FaustSensors.Interpolator3pt(fmin, fmid, fmax, amin, amid, amax);
1745
+ }
1746
+ uiToFaust(x) {
1747
+ return this.fA2F.returnMappedValue(x);
1748
+ }
1749
+ faustToUi(x) {
1750
+ return this.fF2A.returnMappedValue(x);
1751
+ }
1752
+ setMappingValues(amin, amid, amax, min, init, max) {
1753
+ this.fA2F = new _FaustSensors.Interpolator3pt(amin, amid, amax, min, init, max);
1754
+ this.fF2A = new _FaustSensors.Interpolator3pt(min, init, max, amin, amid, amax);
1755
+ }
1756
+ getMappingValues(amin, amid, amax) {
1757
+ return this.fA2F.getMappingValues(amin, amid, amax);
1758
+ }
1759
+ setActive(onOff) {
1760
+ this.fActive = onOff;
1761
+ }
1762
+ getActive() {
1763
+ return this.fActive;
1764
+ }
1765
+ };
1766
+ }
1767
+ return this._UpConverter;
1768
+ }
1769
+ /**
1770
+ * DownConverter class, convert accelerometer value to Faust value
1771
+ */
1772
+ static get DownConverter() {
1773
+ if (!this._DownConverter) {
1774
+ this._DownConverter = class {
1775
+ constructor(amin, amid, amax, fmin, fmid, fmax) {
1776
+ this.fActive = true;
1777
+ this.fA2F = new _FaustSensors.Interpolator3pt(amin, amid, amax, fmax, fmid, fmin);
1778
+ this.fF2A = new _FaustSensors.Interpolator3pt(fmin, fmid, fmax, amax, amid, amin);
1779
+ }
1780
+ uiToFaust(x) {
1781
+ return this.fA2F.returnMappedValue(x);
1782
+ }
1783
+ faustToUi(x) {
1784
+ return this.fF2A.returnMappedValue(x);
1785
+ }
1786
+ setMappingValues(amin, amid, amax, min, init, max) {
1787
+ this.fA2F = new _FaustSensors.Interpolator3pt(amin, amid, amax, max, init, min);
1788
+ this.fF2A = new _FaustSensors.Interpolator3pt(min, init, max, amax, amid, amin);
1789
+ }
1790
+ getMappingValues(amin, amid, amax) {
1791
+ return this.fA2F.getMappingValues(amin, amid, amax);
1792
+ }
1793
+ setActive(onOff) {
1794
+ this.fActive = onOff;
1795
+ }
1796
+ getActive() {
1797
+ return this.fActive;
1798
+ }
1799
+ };
1800
+ }
1801
+ return this._DownConverter;
1802
+ }
1803
+ /**
1804
+ * UpDownConverter class, convert accelerometer value to Faust value
1805
+ */
1806
+ static get UpDownConverter() {
1807
+ if (!this._UpDownConverter) {
1808
+ this._UpDownConverter = class {
1809
+ constructor(amin, amid, amax, fmin, fmid, fmax) {
1810
+ this.fActive = true;
1811
+ this.fA2F = new _FaustSensors.Interpolator3pt(amin, amid, amax, fmin, fmax, fmin);
1812
+ this.fF2A = new _FaustSensors.Interpolator(fmin, fmax, amin, amax);
1813
+ }
1814
+ uiToFaust(x) {
1815
+ return this.fA2F.returnMappedValue(x);
1816
+ }
1817
+ faustToUi(x) {
1818
+ return this.fF2A.returnMappedValue(x);
1819
+ }
1820
+ setMappingValues(amin, amid, amax, min, init, max) {
1821
+ this.fA2F = new _FaustSensors.Interpolator3pt(amin, amid, amax, min, max, min);
1822
+ this.fF2A = new _FaustSensors.Interpolator(min, max, amin, amax);
1823
+ }
1824
+ getMappingValues(amin, amid, amax) {
1825
+ return this.fA2F.getMappingValues(amin, amid, amax);
1826
+ }
1827
+ setActive(onOff) {
1828
+ this.fActive = onOff;
1829
+ }
1830
+ getActive() {
1831
+ return this.fActive;
1832
+ }
1833
+ };
1834
+ }
1835
+ return this._UpDownConverter;
1836
+ }
1837
+ static get DownUpConverter() {
1838
+ if (!this._DownUpConverter) {
1839
+ this._DownUpConverter = class {
1840
+ constructor(amin, amid, amax, fmin, fmid, fmax) {
1841
+ this.fActive = true;
1842
+ this.fA2F = new _FaustSensors.Interpolator3pt(amin, amid, amax, fmax, fmin, fmax);
1843
+ this.fF2A = new _FaustSensors.Interpolator(fmin, fmax, amin, amax);
1844
+ }
1845
+ uiToFaust(x) {
1846
+ return this.fA2F.returnMappedValue(x);
1847
+ }
1848
+ faustToUi(x) {
1849
+ return this.fF2A.returnMappedValue(x);
1850
+ }
1851
+ setMappingValues(amin, amid, amax, min, init, max) {
1852
+ this.fA2F = new _FaustSensors.Interpolator3pt(amin, amid, amax, max, min, max);
1853
+ this.fF2A = new _FaustSensors.Interpolator(min, max, amin, amax);
1854
+ }
1855
+ getMappingValues(amin, amid, amax) {
1856
+ return this.fA2F.getMappingValues(amin, amid, amax);
1857
+ }
1858
+ setActive(onOff) {
1859
+ this.fActive = onOff;
1860
+ }
1861
+ getActive() {
1862
+ return this.fActive;
1863
+ }
1864
+ };
1865
+ }
1866
+ return this._DownUpConverter;
1867
+ }
1868
+ /**
1869
+ * Public function to build the accelerometer handler
1870
+ *
1871
+ * @returns `UpdatableValueConverter` built for the given curve
1872
+ */
1873
+ static buildHandler(curve, amin, amid, amax, min, init, max) {
1874
+ switch (curve) {
1875
+ case 0 /* Up */:
1876
+ return new _FaustSensors.UpConverter(amin, amid, amax, min, init, max);
1877
+ case 1 /* Down */:
1878
+ return new _FaustSensors.DownConverter(amin, amid, amax, min, init, max);
1879
+ case 2 /* UpDown */:
1880
+ return new _FaustSensors.UpDownConverter(amin, amid, amax, min, init, max);
1881
+ case 3 /* DownUp */:
1882
+ return new _FaustSensors.DownUpConverter(amin, amid, amax, min, init, max);
1883
+ default:
1884
+ return new _FaustSensors.UpConverter(amin, amid, amax, min, init, max);
1885
+ }
1886
+ }
1887
+ };
1888
+
1889
+ // src/FaustWebAudioDsp.ts
1890
+ var WasmAllocator = class {
1891
+ constructor(memory, offset) {
1892
+ this.memory = memory;
1893
+ this.allocatedBytes = offset;
1894
+ }
1895
+ /**
1896
+ * Allocates a block of memory of the specified size, returning the pointer to the
1897
+ * beginning of the block. The block is allocated at the current offset and the
1898
+ * offset is incremented by the size of the block.
1899
+ *
1900
+ * @param sizeInBytes The size of the block to allocate in bytes.
1901
+ * @returns The offset (pointer) to the beginning of the allocated block.
1902
+ */
1903
+ alloc(sizeInBytes) {
1904
+ const currentOffset = this.allocatedBytes;
1905
+ const newOffset = currentOffset + sizeInBytes;
1906
+ const totalMemoryBytes = this.memory.buffer.byteLength;
1907
+ if (newOffset > totalMemoryBytes) {
1908
+ const neededPages = Math.ceil((newOffset - totalMemoryBytes) / 65536);
1909
+ console.log(`GROW: ${neededPages} pages`);
1910
+ this.memory.grow(neededPages);
1911
+ }
1912
+ this.allocatedBytes = newOffset;
1913
+ return currentOffset;
1914
+ }
1915
+ /**
1916
+ * Returns the underlying buffer object.
1917
+ *
1918
+ * @returns The buffer object.
1919
+ */
1920
+ getBuffer() {
1921
+ return this.memory.buffer;
1922
+ }
1923
+ /**
1924
+ * Returns the Int32 view of the underlying buffer object.
1925
+ *
1926
+ * @returns The view of the memory buffer as Int32Array.
1927
+ */
1928
+ getInt32Array() {
1929
+ return new Int32Array(this.memory.buffer);
1930
+ }
1931
+ /**
1932
+ * Returns the Int64 view of the underlying buffer object.
1933
+ *
1934
+ * @returns The view of the memory buffer as BigInt64Array.
1935
+ */
1936
+ getInt64Array() {
1937
+ return new BigInt64Array(this.memory.buffer);
1938
+ }
1939
+ /**
1940
+ * Returns the Float32 view of the underlying buffer object.
1941
+ *
1942
+ * @returns The view of the memory buffer as Float32Array.
1943
+ */
1944
+ getFloat32Array() {
1945
+ return new Float32Array(this.memory.buffer);
1946
+ }
1947
+ /**
1948
+ * Returns the Float64 view of the underlying buffer object..
1949
+ *
1950
+ * @returns The view of the memory buffer as Float64Array.
1951
+ */
1952
+ getFloat64Array() {
1953
+ return new Float64Array(this.memory.buffer);
1954
+ }
1955
+ };
1956
+ var Soundfile = class _Soundfile {
1957
+ /** Maximum number of soundfile parts. */
1958
+ static get MAX_SOUNDFILE_PARTS() {
1959
+ return 256;
1960
+ }
1961
+ /** Maximum number of channels. */
1962
+ static get MAX_CHAN() {
1963
+ return 64;
1964
+ }
1965
+ /** Maximum buffer size in frames. */
1966
+ static get BUFFER_SIZE() {
1967
+ return 1024;
1968
+ }
1969
+ /** Default sample rate. */
1970
+ static get SAMPLE_RATE() {
1971
+ return 44100;
1972
+ }
1973
+ constructor(allocator, sampleSize, curChan, length, maxChan, totalParts) {
1974
+ this.fSampleSize = sampleSize;
1975
+ this.fIntSize = this.fSampleSize;
1976
+ this.fPtrSize = 4;
1977
+ this.fAllocator = allocator;
1978
+ console.log(`Soundfile constructor: curChan: ${curChan}, length: ${length}, maxChan: ${maxChan}, totalParts: ${totalParts}`);
1979
+ this.fPtr = allocator.alloc(4 * this.fPtrSize);
1980
+ this.fLength = allocator.alloc(_Soundfile.MAX_SOUNDFILE_PARTS * this.fIntSize);
1981
+ this.fSR = allocator.alloc(_Soundfile.MAX_SOUNDFILE_PARTS * this.fIntSize);
1982
+ this.fOffset = allocator.alloc(_Soundfile.MAX_SOUNDFILE_PARTS * this.fIntSize);
1983
+ this.fBuffers = this.allocBuffers(curChan, length, maxChan);
1984
+ const HEAP32 = this.fAllocator.getInt32Array();
1985
+ HEAP32[this.fPtr >> 2] = this.fBuffers;
1986
+ HEAP32[this.fPtr + this.fPtrSize >> 2] = this.fLength;
1987
+ HEAP32[this.fPtr + 2 * this.fPtrSize >> 2] = this.fSR;
1988
+ HEAP32[this.fPtr + 3 * this.fPtrSize >> 2] = this.fOffset;
1989
+ for (let chan = 0; chan < curChan; chan++) {
1990
+ const buffer = HEAP32[(this.fBuffers >> 2) + chan];
1991
+ console.log(`allocBuffers AFTER: ${chan} - ${buffer}`);
1992
+ }
1993
+ }
1994
+ allocBuffers(curChan, length, maxChan) {
1995
+ const buffers = this.fAllocator.alloc(maxChan * this.fPtrSize);
1996
+ console.log(`allocBuffers buffers: ${buffers}`);
1997
+ for (let chan = 0; chan < curChan; chan++) {
1998
+ const buffer = this.fAllocator.alloc(length * this.fSampleSize);
1999
+ const HEAP32 = this.fAllocator.getInt32Array();
2000
+ HEAP32[(buffers >> 2) + chan] = buffer;
2001
+ }
2002
+ return buffers;
2003
+ }
2004
+ shareBuffers(curChan, maxChan) {
2005
+ const HEAP32 = this.fAllocator.getInt32Array();
2006
+ for (let chan = curChan; chan < maxChan; chan++) {
2007
+ HEAP32[(this.fBuffers >> 2) + chan] = HEAP32[(this.fBuffers >> 2) + chan % curChan];
2008
+ }
2009
+ }
2010
+ copyToOut(part, maxChannels, offset, audioData) {
2011
+ if (this.fIntSize === 4) {
2012
+ const HEAP32 = this.fAllocator.getInt32Array();
2013
+ HEAP32[(this.fLength >> Math.log2(this.fIntSize)) + part] = audioData.audioBuffer[0].length;
2014
+ HEAP32[(this.fSR >> Math.log2(this.fIntSize)) + part] = audioData.sampleRate;
2015
+ HEAP32[(this.fOffset >> Math.log2(this.fIntSize)) + part] = offset;
2016
+ } else {
2017
+ const HEAP64 = this.fAllocator.getInt64Array();
2018
+ HEAP64[(this.fLength >> Math.log2(this.fIntSize)) + part] = BigInt(audioData.audioBuffer[0].length);
2019
+ HEAP64[(this.fSR >> Math.log2(this.fIntSize)) + part] = BigInt(audioData.sampleRate);
2020
+ HEAP64[(this.fOffset >> Math.log2(this.fIntSize)) + part] = BigInt(offset);
2021
+ }
2022
+ console.log(`copyToOut: part: ${part}, maxChannels: ${maxChannels}, offset: ${offset}, buffer: ${audioData}`);
2023
+ if (this.fSampleSize === 8) {
2024
+ this.copyToOutReal64(maxChannels, offset, audioData);
2025
+ } else {
2026
+ this.copyToOutReal32(maxChannels, offset, audioData);
2027
+ }
2028
+ }
2029
+ copyToOutReal32(maxChannels, offset, audioData) {
2030
+ const HEAP32 = this.fAllocator.getInt32Array();
2031
+ const HEAPF = this.fAllocator.getFloat32Array();
2032
+ for (let chan = 0; chan < audioData.audioBuffer.length; chan++) {
2033
+ const input = audioData.audioBuffer[chan];
2034
+ const output = HEAP32[(this.fBuffers >> 2) + chan];
2035
+ const begin = output + offset * this.fSampleSize >> Math.log2(this.fSampleSize);
2036
+ const end = output + (offset + input.length) * this.fSampleSize >> Math.log2(this.fSampleSize);
2037
+ console.log(`copyToOutReal32 begin: ${begin}, end: ${end}, delta: ${end - begin}`);
2038
+ const outputReal = HEAPF.subarray(
2039
+ output + offset * this.fSampleSize >> Math.log2(this.fSampleSize),
2040
+ output + (offset + input.length) * this.fSampleSize >> Math.log2(this.fSampleSize)
2041
+ );
2042
+ for (let sample = 0; sample < input.length; sample++) {
2043
+ outputReal[sample] = input[sample];
2044
+ }
2045
+ }
2046
+ }
2047
+ copyToOutReal64(maxChannels, offset, audioData) {
2048
+ const HEAP32 = this.fAllocator.getInt32Array();
2049
+ const HEAPF = this.fAllocator.getFloat64Array();
2050
+ for (let chan = 0; chan < audioData.audioBuffer.length; chan++) {
2051
+ const input = audioData.audioBuffer[chan];
2052
+ const output = HEAP32[(this.fBuffers >> 2) + chan];
2053
+ const begin = output + offset * this.fSampleSize >> Math.log2(this.fSampleSize);
2054
+ const end = output + (offset + input.length) * this.fSampleSize >> Math.log2(this.fSampleSize);
2055
+ console.log(`copyToOutReal64 begin: ${begin}, end: ${end}, delta: ${end - begin}`);
2056
+ const outputReal = HEAPF.subarray(
2057
+ output + offset * this.fSampleSize >> Math.log2(this.fSampleSize),
2058
+ output + (offset + input.length) * this.fSampleSize >> Math.log2(this.fSampleSize)
2059
+ );
2060
+ for (let sample = 0; sample < input.length; sample++) {
2061
+ outputReal[sample] = input[sample];
2062
+ }
2063
+ }
2064
+ }
2065
+ emptyFile(part, offset) {
2066
+ if (this.fIntSize === 4) {
2067
+ const HEAP32 = this.fAllocator.getInt32Array();
2068
+ HEAP32[(this.fLength >> Math.log2(this.fIntSize)) + part] = _Soundfile.BUFFER_SIZE;
2069
+ HEAP32[(this.fSR >> Math.log2(this.fIntSize)) + part] = _Soundfile.SAMPLE_RATE;
2070
+ HEAP32[(this.fOffset >> Math.log2(this.fIntSize)) + part] = offset;
2071
+ } else {
2072
+ const HEAP64 = this.fAllocator.getInt64Array();
2073
+ HEAP64[(this.fLength >> Math.log2(this.fIntSize)) + part] = BigInt(_Soundfile.BUFFER_SIZE);
2074
+ HEAP64[(this.fSR >> Math.log2(this.fIntSize)) + part] = BigInt(_Soundfile.SAMPLE_RATE);
2075
+ HEAP64[(this.fOffset >> Math.log2(this.fIntSize)) + part] = BigInt(offset);
2076
+ }
2077
+ return offset + _Soundfile.BUFFER_SIZE;
2078
+ }
2079
+ displayMemory(where = "", mem = false) {
2080
+ console.log("Soundfile memory: " + where);
2081
+ console.log(`fPtr: ${this.fPtr}`);
2082
+ console.log(`fBuffers: ${this.fBuffers}`);
2083
+ console.log(`fLength: ${this.fLength}`);
2084
+ console.log(`fSR: ${this.fSR}`);
2085
+ console.log(`fOffset: ${this.fOffset}`);
2086
+ const HEAP32 = this.fAllocator.getInt32Array();
2087
+ if (mem)
2088
+ console.log(`HEAP32: ${HEAP32}`);
2089
+ console.log(`HEAP32[this.fPtr >> 2]: ${HEAP32[this.fPtr >> 2]}`);
2090
+ console.log(`HEAP32[(this.fPtr + ptrSize) >> 2]: ${HEAP32[this.fPtr + this.fPtrSize >> 2]}`);
2091
+ console.log(`HEAP32[(this.fPtr + 2 * ptrSize) >> 2]: ${HEAP32[this.fPtr + 2 * this.fPtrSize >> 2]}`);
2092
+ console.log(`HEAP32[(this.fPtr + 3 * ptrSize) >> 2]: ${HEAP32[this.fPtr + 3 * this.fPtrSize >> 2]}`);
2093
+ }
2094
+ // Return the pointer to the soundfile structure in wasm memory
2095
+ getPtr() {
2096
+ return this.fPtr;
2097
+ }
2098
+ getHEAP32() {
2099
+ return this.fAllocator.getInt32Array();
2100
+ }
2101
+ getHEAPFloat32() {
2102
+ return this.fAllocator.getFloat32Array();
2103
+ }
2104
+ getHEAPFloat64() {
2105
+ return this.fAllocator.getFloat64Array();
2106
+ }
2107
+ };
2108
+ var FaustBaseWebAudioDsp = class _FaustBaseWebAudioDsp {
2109
+ constructor(sampleSize, bufferSize, soundfiles) {
2110
+ this.fOutputHandler = null;
2111
+ this.fComputeHandler = null;
2112
+ // To handle MIDI events plot
2113
+ this.fPlotHandler = null;
2114
+ this.fCachedEvents = [];
2115
+ this.fBufferNum = 0;
2116
+ this.fInChannels = [];
2117
+ this.fOutChannels = [];
2118
+ this.fOutputsTimer = 5;
2119
+ // UI items path
2120
+ this.fInputsItems = [];
2121
+ this.fOutputsItems = [];
2122
+ this.fDescriptor = [];
2123
+ // Soundfile handling
2124
+ this.fSoundfiles = [];
2125
+ this.fSoundfileBuffers = {};
2126
+ // MIDI handling
2127
+ this.fPitchwheelLabel = [];
2128
+ this.fCtrlLabel = new Array(128).fill(null).map(() => []);
2129
+ // array of MIDI key handlers; array index is the MIDI note number
2130
+ this.fMidiKeyLabel = new Array(128).fill(null).map(() => []);
2131
+ this.fMidiKeyOnLabel = new Array(128).fill(null).map(() => []);
2132
+ this.fMidiKeyOffLabel = new Array(128).fill(null).map(() => []);
2133
+ this.fPathTable = {};
2134
+ this.fUICallback = (item) => {
2135
+ if (item.type === "hbargraph" || item.type === "vbargraph") {
2136
+ this.fOutputsItems.push(item.address);
2137
+ this.fPathTable[item.address] = item.index;
2138
+ } else if (item.type === "vslider" || item.type === "hslider" || item.type === "button" || item.type === "checkbox" || item.type === "nentry") {
2139
+ this.fInputsItems.push(item.address);
2140
+ this.fPathTable[item.address] = item.index;
2141
+ this.fDescriptor.push(item);
2142
+ if (!item.meta)
2143
+ return;
2144
+ item.meta.forEach((meta) => {
2145
+ var _a, _b, _c, _d, _e, _f;
2146
+ const { midi, acc, gyr } = meta;
2147
+ if (midi) {
2148
+ const strMidi = midi.trim();
2149
+ if (strMidi === "pitchwheel") {
2150
+ const matched = strMidi.match(/^pitchwheel\s(\d+)/);
2151
+ if (matched) {
2152
+ this.fPitchwheelLabel.push({ path: item.address, chan: parseInt(matched[1]), min: item.min, max: item.max });
2153
+ } else {
2154
+ this.fPitchwheelLabel.push({ path: item.address, chan: 0, min: item.min, max: item.max });
2155
+ }
2156
+ } else {
2157
+ const matched2 = strMidi.match(/^ctrl\s(\d+)\s(\d+)/);
2158
+ const matched1 = strMidi.match(/^ctrl\s(\d+)/);
2159
+ const matchedKey = strMidi.match(/^key\s+(\d+)(?:\s+(\d+))?$/);
2160
+ const matchedKeyOn = strMidi.match(/^keyon\s+(\d+)(?:\s+(\d+))?$/);
2161
+ const matchedKeyOff = strMidi.match(/^keyoff\s+(\d+)(?:\s+(\d+))?$/);
2162
+ if (matched2) {
2163
+ this.fCtrlLabel[parseInt(matched2[1])].push({ path: item.address, chan: parseInt(matched2[2]), min: item.min, max: item.max });
2164
+ } else if (matched1) {
2165
+ this.fCtrlLabel[parseInt(matched1[1])].push({ path: item.address, chan: 0, min: item.min, max: item.max });
2166
+ } else if (matchedKey) {
2167
+ const note = parseInt(matchedKey[1]);
2168
+ const channel = matchedKey[2] ? parseInt(matchedKey[2]) : 0;
2169
+ this.fMidiKeyLabel[note].push({ path: item.address, chan: channel, min: (_a = item.min) != null ? _a : 0, max: (_b = item.max) != null ? _b : 1 });
2170
+ } else if (matchedKeyOn) {
2171
+ const note = parseInt(matchedKeyOn[1]);
2172
+ const channel = matchedKeyOn[2] ? parseInt(matchedKeyOn[2]) : 0;
2173
+ this.fMidiKeyOnLabel[note].push({ path: item.address, chan: channel, min: (_c = item.min) != null ? _c : 0, max: (_d = item.max) != null ? _d : 1 });
2174
+ } else if (matchedKeyOff) {
2175
+ const note = parseInt(matchedKeyOff[1]);
2176
+ const channel = matchedKeyOff[2] ? parseInt(matchedKeyOff[2]) : 0;
2177
+ this.fMidiKeyOffLabel[note].push({ path: item.address, chan: channel, min: (_e = item.min) != null ? _e : 0, max: (_f = item.max) != null ? _f : 1 });
2178
+ }
2179
+ }
2180
+ }
2181
+ if (acc) {
2182
+ const numAcc = acc.trim().split(" ").map(Number);
2183
+ this.setupAccHandler(item.address, FaustSensors.convertToAxis(numAcc[0]), FaustSensors.convertToCurve(numAcc[1]), numAcc[2], numAcc[3], numAcc[4], item.min, item.init, item.max);
2184
+ }
2185
+ if (gyr) {
2186
+ const numAcc = gyr.trim().split(" ").map(Number);
2187
+ this.setupGyrHandler(item.address, FaustSensors.convertToAxis(numAcc[0]), FaustSensors.convertToCurve(numAcc[1]), numAcc[2], numAcc[3], numAcc[4], item.min, item.init, item.max);
2188
+ }
2189
+ });
2190
+ } else if (item.type === "soundfile") {
2191
+ this.fSoundfiles.push({ name: item.label, url: item.url, index: item.index, basePtr: -1 });
2192
+ }
2193
+ };
2194
+ // Audio callback
2195
+ this.fProcessing = false;
2196
+ this.fDestroyed = false;
2197
+ this.fFirstCall = true;
2198
+ this.fBufferSize = bufferSize;
2199
+ this.fPtrSize = sampleSize;
2200
+ this.fSampleSize = sampleSize;
2201
+ this.fSoundfileBuffers = soundfiles;
2202
+ this.fAcc = { x: [], y: [], z: [] };
2203
+ this.fGyr = { x: [], y: [], z: [] };
2204
+ }
2205
+ // Tools
2206
+ static remap(v, mn0, mx0, mn1, mx1) {
2207
+ return (v - mn0) / (mx0 - mn0) * (mx1 - mn1) + mn1;
2208
+ }
2209
+ // JSON parsing functions
2210
+ static parseUI(ui, callback) {
2211
+ ui.forEach((group) => this.parseGroup(group, callback));
2212
+ }
2213
+ static parseGroup(group, callback) {
2214
+ if (group.items) {
2215
+ this.parseItems(group.items, callback);
2216
+ }
2217
+ }
2218
+ static parseItems(items, callback) {
2219
+ items.forEach((item) => this.parseItem(item, callback));
2220
+ }
2221
+ static parseItem(item, callback) {
2222
+ if (item.type === "vgroup" || item.type === "hgroup" || item.type === "tgroup") {
2223
+ this.parseItems(item.items, callback);
2224
+ } else {
2225
+ callback(item);
2226
+ }
2227
+ }
2228
+ /** Split the soundfile names and return an array of names */
2229
+ static splitSoundfileNames(input) {
2230
+ let trimmed = input.replace(/^\{|\}$/g, "");
2231
+ return trimmed.split(";").map((str) => str.length <= 2 ? "" : str.substring(1, str.length - 1));
2232
+ }
2233
+ get hasAccInput() {
2234
+ return this.fAcc.x.length + this.fAcc.y.length + this.fAcc.z.length > 0;
2235
+ }
2236
+ propagateAcc(accelerationIncludingGravity, invert = false) {
2237
+ const { x, y, z } = accelerationIncludingGravity;
2238
+ if (invert) {
2239
+ if (x !== null)
2240
+ this.fAcc.x.forEach((handler) => handler(-x));
2241
+ if (y !== null)
2242
+ this.fAcc.y.forEach((handler) => handler(-y));
2243
+ if (z !== null)
2244
+ this.fAcc.z.forEach((handler) => handler(-z));
2245
+ } else {
2246
+ if (x !== null)
2247
+ this.fAcc.x.forEach((handler) => handler(x));
2248
+ if (y !== null)
2249
+ this.fAcc.y.forEach((handler) => handler(y));
2250
+ if (z !== null)
2251
+ this.fAcc.z.forEach((handler) => handler(z));
2252
+ }
2253
+ }
2254
+ get hasGyrInput() {
2255
+ return this.fGyr.x.length + this.fGyr.y.length + this.fGyr.z.length > 0;
2256
+ }
2257
+ propagateGyr(event) {
2258
+ const { alpha, beta, gamma } = event;
2259
+ if (alpha !== null)
2260
+ this.fGyr.x.forEach((handler) => handler(alpha));
2261
+ if (beta !== null)
2262
+ this.fGyr.y.forEach((handler) => handler(beta));
2263
+ if (gamma !== null)
2264
+ this.fGyr.z.forEach((handler) => handler(gamma));
2265
+ }
2266
+ /** Build the accelerometer handler */
2267
+ setupAccHandler(path, axis, curve, amin, amid, amax, min, init, max) {
2268
+ const handler = FaustSensors.buildHandler(curve, amin, amid, amax, min, init, max);
2269
+ switch (axis) {
2270
+ case 0 /* x */:
2271
+ this.fAcc.x.push((val) => this.setParamValue(path, handler.uiToFaust(val)));
2272
+ break;
2273
+ case 1 /* y */:
2274
+ this.fAcc.y.push((val) => this.setParamValue(path, handler.uiToFaust(val)));
2275
+ break;
2276
+ case 2 /* z */:
2277
+ this.fAcc.z.push((val) => this.setParamValue(path, handler.uiToFaust(val)));
2278
+ break;
2279
+ }
2280
+ }
2281
+ /** Build the gyroscope handler */
2282
+ setupGyrHandler(path, axis, curve, amin, amid, amax, min, init, max) {
2283
+ const handler = FaustSensors.buildHandler(curve, amin, amid, amax, min, init, max);
2284
+ switch (axis) {
2285
+ case 0 /* x */:
2286
+ this.fGyr.x.push((val) => this.setParamValue(path, handler.uiToFaust(val)));
2287
+ break;
2288
+ case 1 /* y */:
2289
+ this.fGyr.y.push((val) => this.setParamValue(path, handler.uiToFaust(val)));
2290
+ break;
2291
+ case 2 /* z */:
2292
+ this.fGyr.z.push((val) => this.setParamValue(path, handler.uiToFaust(val)));
2293
+ break;
2294
+ }
2295
+ }
2296
+ static extractUrlsFromMeta(dspMeta) {
2297
+ const soundfilesEntry = dspMeta.meta.find((entry) => entry.soundfiles !== void 0);
2298
+ if (soundfilesEntry) {
2299
+ return soundfilesEntry.soundfiles.split(";").filter((url) => url !== "");
2300
+ } else {
2301
+ return [];
2302
+ }
2303
+ }
2304
+ /**
2305
+ * Load a soundfile possibly containing several parts in the DSP struct.
2306
+ * Soundfile pointers are located at 'index' offset, to be read in the JSON file.
2307
+ * The DSP struct is located at baseDSP in the wasm memory,
2308
+ * either a monophonic DSP, or a voice in a polyphonic context.
2309
+ *
2310
+ * @param allocator : the wasm memory allocator
2311
+ * @param baseDSP : the base DSP in the wasm memory
2312
+ * @param name : the name of the soundfile
2313
+ * @param url : the url of the soundfile
2314
+ */
2315
+ loadSoundfile(allocator, baseDSP, name, url) {
2316
+ console.log(`Soundfile ${name} paths: ${url}`);
2317
+ const soundfileIds = _FaustBaseWebAudioDsp.splitSoundfileNames(url);
2318
+ const item = this.fSoundfiles.find((item2) => item2.url === url);
2319
+ if (!item)
2320
+ throw new Error(`Soundfile with ${url} cannot be found !}`);
2321
+ if (item.basePtr !== -1) {
2322
+ const HEAP32 = allocator.getInt32Array();
2323
+ console.log(`Soundfile CACHE ${url}} : ${name} loaded at ${item.basePtr} in wasm memory with index ${item.index}`);
2324
+ HEAP32[baseDSP + item.index >> 2] = item.basePtr;
2325
+ } else {
2326
+ const soundfile = this.createSoundfile(allocator, soundfileIds, this.fSoundfileBuffers);
2327
+ if (soundfile) {
2328
+ const HEAP32 = soundfile.getHEAP32();
2329
+ item.basePtr = soundfile.getPtr();
2330
+ console.log(`Soundfile ${name} loaded at ${item.basePtr} in wasm memory with index ${item.index}`);
2331
+ HEAP32[baseDSP + item.index >> 2] = item.basePtr;
2332
+ } else {
2333
+ console.log(`Soundfile ${name} for ${url} cannot be created !}`);
2334
+ }
2335
+ }
2336
+ }
2337
+ createSoundfile(allocator, soundfileIdList, soundfiles, maxChan = Soundfile.MAX_CHAN) {
2338
+ let curChan = 1;
2339
+ let totalLength = 0;
2340
+ for (const soundfileId of soundfileIdList) {
2341
+ let chan = 0;
2342
+ let len = 0;
2343
+ const audioData = soundfiles[soundfileId];
2344
+ if (audioData) {
2345
+ chan = audioData.audioBuffer.length;
2346
+ len = audioData.audioBuffer[0].length;
2347
+ } else {
2348
+ len = Soundfile.BUFFER_SIZE;
2349
+ chan = 1;
2350
+ }
2351
+ curChan = Math.max(curChan, chan);
2352
+ totalLength += len;
2353
+ }
2354
+ totalLength += (Soundfile.MAX_SOUNDFILE_PARTS - soundfileIdList.length) * Soundfile.BUFFER_SIZE;
2355
+ const soundfile = new Soundfile(allocator, this.fSampleSize, curChan, totalLength, maxChan, soundfileIdList.length);
2356
+ let offset = 0;
2357
+ for (let part = 0; part < soundfileIdList.length; part++) {
2358
+ const soundfileId = soundfileIdList[part];
2359
+ const audioData = soundfiles[soundfileId];
2360
+ if (audioData) {
2361
+ soundfile.copyToOut(part, maxChan, offset, audioData);
2362
+ offset += audioData.audioBuffer[0].length;
2363
+ } else {
2364
+ offset = soundfile.emptyFile(part, offset);
2365
+ }
2366
+ }
2367
+ for (let part = soundfileIdList.length; part < Soundfile.MAX_SOUNDFILE_PARTS; part++) {
2368
+ offset = soundfile.emptyFile(part, offset);
2369
+ }
2370
+ soundfile.shareBuffers(curChan, maxChan);
2371
+ return soundfile;
2372
+ }
2373
+ /**
2374
+ * Init soundfiles memory.
2375
+ *
2376
+ * @param allocator : the wasm memory allocator
2377
+ * @param sfReader : the soundfile reader
2378
+ * @param baseDSP : the DSP struct (either a monophonic DSP of polyphonic voice) base DSP in the wasm memory
2379
+ */
2380
+ initSoundfileMemory(allocator, baseDSP) {
2381
+ for (const { name, url } of this.fSoundfiles) {
2382
+ this.loadSoundfile(allocator, baseDSP, name, url);
2383
+ }
2384
+ ;
2385
+ }
2386
+ updateOutputs() {
2387
+ if (this.fOutputsItems.length > 0 && this.fOutputHandler && this.fOutputsTimer-- === 0) {
2388
+ this.fOutputsTimer = 5;
2389
+ this.fOutputsItems.forEach((item) => {
2390
+ var _a;
2391
+ return (_a = this.fOutputHandler) == null ? void 0 : _a.call(this, item, this.getParamValue(item));
2392
+ });
2393
+ }
2394
+ }
2395
+ // Public API
2396
+ metadata(handler) {
2397
+ if (this.fJSONDsp.meta) {
2398
+ this.fJSONDsp.meta.forEach((meta) => handler(Object.keys(meta)[0], meta[Object.keys(meta)[0]]));
2399
+ }
2400
+ }
2401
+ compute(input, output) {
2402
+ return false;
2403
+ }
2404
+ setOutputParamHandler(handler) {
2405
+ this.fOutputHandler = handler;
2406
+ }
2407
+ getOutputParamHandler() {
2408
+ return this.fOutputHandler;
2409
+ }
2410
+ setComputeHandler(handler) {
2411
+ this.fComputeHandler = handler;
2412
+ }
2413
+ getComputeHandler() {
2414
+ return this.fComputeHandler;
2415
+ }
2416
+ setPlotHandler(handler) {
2417
+ this.fPlotHandler = handler;
2418
+ }
2419
+ getPlotHandler() {
2420
+ return this.fPlotHandler;
2421
+ }
2422
+ getNumInputs() {
2423
+ return -1;
2424
+ }
2425
+ getNumOutputs() {
2426
+ return -1;
2427
+ }
2428
+ midiMessage(data) {
2429
+ if (this.fPlotHandler)
2430
+ this.fCachedEvents.push({ data, type: "midi" });
2431
+ const cmd = data[0] >> 4;
2432
+ const channel = data[0] & 15;
2433
+ const data1 = data[1];
2434
+ const data2 = data[2];
2435
+ if (cmd === 11)
2436
+ return this.ctrlChange(channel, data1, data2);
2437
+ if (cmd === 14)
2438
+ return this.pitchWheel(channel, data2 * 128 + data1);
2439
+ if (cmd === 9) {
2440
+ if (data2 > 0)
2441
+ return this.keyOn(channel, data1, data2);
2442
+ else
2443
+ return this.keyOff(channel, data1, data2);
2444
+ }
2445
+ if (cmd === 8) {
2446
+ return this.keyOff(channel, data1, data2);
2447
+ }
2448
+ }
2449
+ ctrlChange(channel, ctrl, value) {
2450
+ if (this.fPlotHandler)
2451
+ this.fCachedEvents.push({ type: "ctrlChange", data: [channel, ctrl, value] });
2452
+ if (this.fCtrlLabel[ctrl].length) {
2453
+ this.fCtrlLabel[ctrl].forEach((ctrl2) => {
2454
+ const { path, chan } = ctrl2;
2455
+ if (chan === 0 || channel === chan - 1) {
2456
+ this.setParamValue(path, _FaustBaseWebAudioDsp.remap(value, 0, 127, ctrl2.min, ctrl2.max));
2457
+ if (this.fOutputHandler)
2458
+ this.fOutputHandler(path, this.getParamValue(path));
2459
+ }
2460
+ });
2461
+ }
2462
+ }
2463
+ keyOn(channel, pitch, velocity) {
2464
+ if (this.fPlotHandler)
2465
+ this.fCachedEvents.push({ type: "keyOn", data: [channel, pitch, velocity] });
2466
+ this.fMidiKeyOnLabel[pitch].forEach((key) => {
2467
+ const { path, chan } = key;
2468
+ if (chan === 0 || channel === chan - 1) {
2469
+ this.setParamValue(path, _FaustBaseWebAudioDsp.remap(velocity, 0, 127, key.min, key.max));
2470
+ if (this.fOutputHandler)
2471
+ this.fOutputHandler(path, this.getParamValue(path));
2472
+ }
2473
+ });
2474
+ this.fMidiKeyLabel[pitch].forEach((key) => {
2475
+ const { path, chan } = key;
2476
+ if (chan === 0 || channel === chan - 1) {
2477
+ this.setParamValue(path, _FaustBaseWebAudioDsp.remap(velocity, 0, 127, key.min, key.max));
2478
+ if (this.fOutputHandler)
2479
+ this.fOutputHandler(path, this.getParamValue(path));
2480
+ }
2481
+ });
2482
+ }
2483
+ keyOff(channel, pitch, velocity) {
2484
+ if (this.fPlotHandler)
2485
+ this.fCachedEvents.push({ type: "keyOff", data: [channel, pitch, velocity] });
2486
+ this.fMidiKeyOffLabel[pitch].forEach((key) => {
2487
+ const { path, chan } = key;
2488
+ if (chan === 0 || channel === chan - 1) {
2489
+ this.setParamValue(path, _FaustBaseWebAudioDsp.remap(velocity, 0, 127, key.min, key.max));
2490
+ if (this.fOutputHandler)
2491
+ this.fOutputHandler(path, this.getParamValue(path));
2492
+ }
2493
+ });
2494
+ this.fMidiKeyLabel[pitch].forEach((key) => {
2495
+ const { path, chan } = key;
2496
+ if (chan === 0 || channel === chan - 1) {
2497
+ this.setParamValue(path, 0);
2498
+ if (this.fOutputHandler)
2499
+ this.fOutputHandler(path, this.getParamValue(path));
2500
+ }
2501
+ });
2502
+ }
2503
+ pitchWheel(channel, wheel) {
2504
+ if (this.fPlotHandler)
2505
+ this.fCachedEvents.push({ type: "pitchWheel", data: [channel, wheel] });
2506
+ this.fPitchwheelLabel.forEach((pw) => {
2507
+ const { path, chan } = pw;
2508
+ if (chan === 0 || channel === chan - 1) {
2509
+ this.setParamValue(path, _FaustBaseWebAudioDsp.remap(wheel, 0, 16383, pw.min, pw.max));
2510
+ if (this.fOutputHandler)
2511
+ this.fOutputHandler(path, this.getParamValue(path));
2512
+ }
2513
+ });
2514
+ }
2515
+ setParamValue(path, value) {
2516
+ }
2517
+ getParamValue(path) {
2518
+ return 0;
2519
+ }
2520
+ getParams() {
2521
+ return this.fInputsItems;
2522
+ }
2523
+ getMeta() {
2524
+ return this.fJSONDsp;
2525
+ }
2526
+ getJSON() {
2527
+ return JSON.stringify(this.getMeta());
2528
+ }
2529
+ getUI() {
2530
+ return this.fJSONDsp.ui;
2531
+ }
2532
+ getDescriptors() {
2533
+ return this.fDescriptor;
2534
+ }
2535
+ hasSoundfiles() {
2536
+ return this.fSoundfiles.length > 0;
2537
+ }
2538
+ startSensors() {
2539
+ this.startSensors();
2540
+ }
2541
+ stopSensors() {
2542
+ this.stopSensors();
2543
+ }
2544
+ start() {
2545
+ this.fProcessing = true;
2546
+ }
2547
+ stop() {
2548
+ this.fProcessing = false;
2549
+ }
2550
+ destroy() {
2551
+ this.fDestroyed = true;
2552
+ this.fOutputHandler = null;
2553
+ this.fComputeHandler = null;
2554
+ this.fPlotHandler = null;
2555
+ }
2556
+ };
2557
+ var FaustMonoWebAudioDsp = class extends FaustBaseWebAudioDsp {
2558
+ constructor(instance, sampleRate, sampleSize, bufferSize, soundfiles) {
2559
+ super(sampleSize, bufferSize, soundfiles);
2560
+ this.fInstance = instance;
2561
+ console.log(`sampleSize: ${sampleSize} bufferSize: ${bufferSize}`);
2562
+ this.fJSONDsp = JSON.parse(this.fInstance.json);
2563
+ FaustBaseWebAudioDsp.parseUI(this.fJSONDsp.ui, this.fUICallback);
2564
+ this.fEndMemory = this.initMemory();
2565
+ this.fInstance.api.init(this.fDSP, sampleRate);
2566
+ if (this.fSoundfiles.length > 0) {
2567
+ const allocator = new WasmAllocator(this.fInstance.memory, this.fEndMemory);
2568
+ this.initSoundfileMemory(allocator, this.fDSP);
2569
+ }
2570
+ }
2571
+ initMemory() {
2572
+ this.fDSP = 0;
2573
+ const $audio = this.fJSONDsp.size;
2574
+ this.fAudioInputs = $audio;
2575
+ this.fAudioOutputs = this.fAudioInputs + this.getNumInputs() * this.fPtrSize;
2576
+ const $audioInputs = this.fAudioOutputs + this.getNumOutputs() * this.fPtrSize;
2577
+ const $audioOutputs = $audioInputs + this.getNumInputs() * this.fBufferSize * this.fSampleSize;
2578
+ const endMemory = $audioOutputs + this.getNumOutputs() * this.fBufferSize * this.fSampleSize;
2579
+ const HEAP = this.fInstance.memory.buffer;
2580
+ const HEAP32 = new Int32Array(HEAP);
2581
+ const HEAPF = this.fSampleSize === 4 ? new Float32Array(HEAP) : new Float64Array(HEAP);
2582
+ if (this.getNumInputs() > 0) {
2583
+ for (let chan = 0; chan < this.getNumInputs(); chan++) {
2584
+ HEAP32[(this.fAudioInputs >> 2) + chan] = $audioInputs + this.fBufferSize * this.fSampleSize * chan;
2585
+ }
2586
+ const dspInChans = HEAP32.subarray(this.fAudioInputs >> 2, this.fAudioInputs + this.getNumInputs() * this.fPtrSize >> 2);
2587
+ for (let chan = 0; chan < this.getNumInputs(); chan++) {
2588
+ this.fInChannels[chan] = HEAPF.subarray(dspInChans[chan] >> Math.log2(this.fSampleSize), dspInChans[chan] + this.fBufferSize * this.fSampleSize >> Math.log2(this.fSampleSize));
2589
+ }
2590
+ }
2591
+ if (this.getNumOutputs() > 0) {
2592
+ for (let chan = 0; chan < this.getNumOutputs(); chan++) {
2593
+ HEAP32[(this.fAudioOutputs >> 2) + chan] = $audioOutputs + this.fBufferSize * this.fSampleSize * chan;
2594
+ }
2595
+ const dspOutChans = HEAP32.subarray(this.fAudioOutputs >> 2, this.fAudioOutputs + this.getNumOutputs() * this.fPtrSize >> 2);
2596
+ for (let chan = 0; chan < this.getNumOutputs(); chan++) {
2597
+ this.fOutChannels[chan] = HEAPF.subarray(dspOutChans[chan] >> Math.log2(this.fSampleSize), dspOutChans[chan] + this.fBufferSize * this.fSampleSize >> Math.log2(this.fSampleSize));
2598
+ }
2599
+ }
2600
+ return endMemory;
2601
+ }
2602
+ toString() {
2603
+ return `============== Mono Memory layout ==============
2604
+ this.fBufferSize: ${this.fBufferSize}
2605
+ this.fJSONDsp.size: ${this.fJSONDsp.size}
2606
+ this.fAudioInputs: ${this.fAudioInputs}
2607
+ this.fAudioOutputs: ${this.fAudioOutputs}
2608
+ this.fDSP: ${this.fDSP}`;
2609
+ }
2610
+ // Public API
2611
+ compute(input, output) {
2612
+ if (this.fDestroyed)
2613
+ return false;
2614
+ if (!this.fProcessing)
2615
+ return true;
2616
+ if (this.fFirstCall) {
2617
+ this.initMemory();
2618
+ this.fFirstCall = false;
2619
+ }
2620
+ if (typeof input === "function") {
2621
+ input(this.fInChannels);
2622
+ } else {
2623
+ if (this.getNumInputs() > 0 && (!input || !input[0] || input[0].length === 0)) {
2624
+ return true;
2625
+ }
2626
+ if (this.getNumOutputs() > 0 && typeof output !== "function" && (!output || !output[0] || output[0].length === 0)) {
2627
+ return true;
2628
+ }
2629
+ if (input !== void 0) {
2630
+ for (let chan = 0; chan < Math.min(this.getNumInputs(), input.length); chan++) {
2631
+ const dspInput = this.fInChannels[chan];
2632
+ dspInput.set(input[chan]);
2633
+ }
2634
+ }
2635
+ }
2636
+ if (this.fComputeHandler)
2637
+ this.fComputeHandler(this.fBufferSize);
2638
+ this.fInstance.api.compute(this.fDSP, this.fBufferSize, this.fAudioInputs, this.fAudioOutputs);
2639
+ this.updateOutputs();
2640
+ let forPlot = this.fOutChannels;
2641
+ if (typeof output === "function") {
2642
+ output(this.fOutChannels);
2643
+ } else {
2644
+ for (let chan = 0; chan < Math.min(this.getNumOutputs(), output.length); chan++) {
2645
+ const dspOutput = this.fOutChannels[chan];
2646
+ output[chan].set(dspOutput);
2647
+ }
2648
+ forPlot = output;
2649
+ }
2650
+ if (this.fPlotHandler) {
2651
+ this.fPlotHandler(forPlot, this.fBufferNum++, this.fCachedEvents.length ? this.fCachedEvents : void 0);
2652
+ this.fCachedEvents = [];
2653
+ }
2654
+ return true;
2655
+ }
2656
+ metadata(handler) {
2657
+ super.metadata(handler);
2658
+ }
2659
+ getNumInputs() {
2660
+ return this.fInstance.api.getNumInputs(this.fDSP);
2661
+ }
2662
+ getNumOutputs() {
2663
+ return this.fInstance.api.getNumOutputs(this.fDSP);
2664
+ }
2665
+ setParamValue(path, value) {
2666
+ if (this.fPlotHandler)
2667
+ this.fCachedEvents.push({ type: "param", data: { path, value } });
2668
+ this.fInstance.api.setParamValue(this.fDSP, this.fPathTable[path], value);
2669
+ }
2670
+ getParamValue(path) {
2671
+ return this.fInstance.api.getParamValue(this.fDSP, this.fPathTable[path]);
2672
+ }
2673
+ getMeta() {
2674
+ return this.fJSONDsp;
2675
+ }
2676
+ getJSON() {
2677
+ return this.fInstance.json;
2678
+ }
2679
+ getDescriptors() {
2680
+ return this.fDescriptor;
2681
+ }
2682
+ getUI() {
2683
+ return this.fJSONDsp.ui;
2684
+ }
2685
+ };
2686
+ var FaustWebAudioDspVoice = class _FaustWebAudioDspVoice {
2687
+ constructor($dsp, api, inputItems, pathTable, sampleRate) {
2688
+ this.fFreqLabel = [];
2689
+ this.fGateLabel = [];
2690
+ this.fGainLabel = [];
2691
+ this.fKeyLabel = [];
2692
+ this.fVelLabel = [];
2693
+ // Voice DSP code
2694
+ // Accessed by PolyDSPImp class
2695
+ this.fCurNote = _FaustWebAudioDspVoice.kFreeVoice;
2696
+ this.fNextNote = -1;
2697
+ this.fNextVel = -1;
2698
+ this.fDate = 0;
2699
+ this.fLevel = 0;
2700
+ this.fRelease = 0;
2701
+ this.fDSP = $dsp;
2702
+ this.fAPI = api;
2703
+ this.fAPI.init(this.fDSP, sampleRate);
2704
+ this.extractPaths(inputItems, pathTable);
2705
+ }
2706
+ // Voice state
2707
+ static get kActiveVoice() {
2708
+ return 0;
2709
+ }
2710
+ static get kFreeVoice() {
2711
+ return -1;
2712
+ }
2713
+ static get kReleaseVoice() {
2714
+ return -2;
2715
+ }
2716
+ static get kLegatoVoice() {
2717
+ return -3;
2718
+ }
2719
+ static get kNoVoice() {
2720
+ return -4;
2721
+ }
2722
+ static get VOICE_STOP_LEVEL() {
2723
+ return 5e-4;
2724
+ }
2725
+ static midiToFreq(note) {
2726
+ return 440 * 2 ** ((note - 69) / 12);
2727
+ }
2728
+ static normalizeVelocity(velocity) {
2729
+ return velocity / 127;
2730
+ }
2731
+ extractPaths(inputItems, pathTable) {
2732
+ inputItems.forEach((item) => {
2733
+ if (item.endsWith("/gate")) {
2734
+ this.fGateLabel.push(pathTable[item]);
2735
+ } else if (item.endsWith("/freq")) {
2736
+ this.fFreqLabel.push(pathTable[item]);
2737
+ } else if (item.endsWith("/key")) {
2738
+ this.fKeyLabel.push(pathTable[item]);
2739
+ } else if (item.endsWith("/gain")) {
2740
+ this.fGainLabel.push(pathTable[item]);
2741
+ } else if (item.endsWith("/vel") && item.endsWith("/velocity")) {
2742
+ this.fVelLabel.push(pathTable[item]);
2743
+ }
2744
+ });
2745
+ }
2746
+ // Public API
2747
+ keyOn(pitch, velocity, legato = false) {
2748
+ if (legato) {
2749
+ this.fNextNote = pitch;
2750
+ this.fNextVel = velocity;
2751
+ } else {
2752
+ this.fFreqLabel.forEach((index) => this.fAPI.setParamValue(this.fDSP, index, _FaustWebAudioDspVoice.midiToFreq(pitch)));
2753
+ this.fGateLabel.forEach((index) => this.fAPI.setParamValue(this.fDSP, index, 1));
2754
+ this.fGainLabel.forEach((index) => this.fAPI.setParamValue(this.fDSP, index, _FaustWebAudioDspVoice.normalizeVelocity(velocity)));
2755
+ this.fKeyLabel.forEach((index) => this.fAPI.setParamValue(this.fDSP, index, pitch));
2756
+ this.fVelLabel.forEach((index) => this.fAPI.setParamValue(this.fDSP, index, velocity));
2757
+ this.fCurNote = pitch;
2758
+ }
2759
+ }
2760
+ keyOff(hard = false) {
2761
+ this.fGateLabel.forEach((index) => this.fAPI.setParamValue(this.fDSP, index, 0));
2762
+ if (hard) {
2763
+ this.fCurNote = _FaustWebAudioDspVoice.kFreeVoice;
2764
+ } else {
2765
+ this.fRelease = this.fAPI.getSampleRate(this.fDSP) / 2;
2766
+ this.fCurNote = _FaustWebAudioDspVoice.kReleaseVoice;
2767
+ }
2768
+ }
2769
+ computeLegato(bufferSize, $inputs, $outputZero, $outputsHalf) {
2770
+ let size = bufferSize / 2;
2771
+ this.fGateLabel.forEach((index) => this.fAPI.setParamValue(this.fDSP, index, 0));
2772
+ this.fAPI.compute(this.fDSP, size, $inputs, $outputZero);
2773
+ this.keyOn(this.fNextNote, this.fNextVel);
2774
+ this.fAPI.compute(this.fDSP, size, $inputs, $outputsHalf);
2775
+ }
2776
+ compute(bufferSize, $inputs, $outputs) {
2777
+ this.fAPI.compute(this.fDSP, bufferSize, $inputs, $outputs);
2778
+ }
2779
+ setParamValue(index, value) {
2780
+ this.fAPI.setParamValue(this.fDSP, index, value);
2781
+ }
2782
+ getParamValue(index) {
2783
+ return this.fAPI.getParamValue(this.fDSP, index);
2784
+ }
2785
+ };
2786
+ var FaustPolyWebAudioDsp = class _FaustPolyWebAudioDsp extends FaustBaseWebAudioDsp {
2787
+ constructor(instance, sampleRate, sampleSize, bufferSize, soundfiles) {
2788
+ super(sampleSize, bufferSize, soundfiles);
2789
+ this.fInstance = instance;
2790
+ console.log(`sampleSize: ${sampleSize} bufferSize: ${bufferSize}`);
2791
+ this.fJSONDsp = JSON.parse(this.fInstance.voiceJSON);
2792
+ this.fJSONEffect = this.fInstance.effectAPI && this.fInstance.effectJSON ? JSON.parse(this.fInstance.effectJSON) : null;
2793
+ FaustBaseWebAudioDsp.parseUI(this.fJSONDsp.ui, this.fUICallback);
2794
+ if (this.fJSONEffect)
2795
+ FaustBaseWebAudioDsp.parseUI(this.fJSONEffect.ui, this.fUICallback);
2796
+ this.fEndMemory = this.initMemory();
2797
+ this.fVoiceTable = [];
2798
+ for (let voice = 0; voice < this.fInstance.voices; voice++) {
2799
+ this.fVoiceTable.push(new FaustWebAudioDspVoice(
2800
+ this.fJSONDsp.size * voice,
2801
+ this.fInstance.voiceAPI,
2802
+ this.fInputsItems,
2803
+ this.fPathTable,
2804
+ sampleRate
2805
+ ));
2806
+ }
2807
+ if (this.fInstance.effectAPI)
2808
+ this.fInstance.effectAPI.init(this.fEffect, sampleRate);
2809
+ if (this.fSoundfiles.length > 0) {
2810
+ const allocator = new WasmAllocator(this.fInstance.memory, this.fEndMemory);
2811
+ for (let voice = 0; voice < this.fInstance.voices; voice++) {
2812
+ this.initSoundfileMemory(allocator, this.fJSONDsp.size * voice);
2813
+ }
2814
+ }
2815
+ }
2816
+ initMemory() {
2817
+ this.fEffect = this.fJSONDsp.size * this.fInstance.voices;
2818
+ const $audio = this.fEffect + (this.fJSONEffect ? this.fJSONEffect.size : 0);
2819
+ this.fAudioInputs = $audio;
2820
+ this.fAudioOutputs = this.fAudioInputs + this.getNumInputs() * this.fPtrSize;
2821
+ this.fAudioMixing = this.fAudioOutputs + this.getNumOutputs() * this.fPtrSize;
2822
+ this.fAudioMixingHalf = this.fAudioMixing + this.getNumOutputs() * this.fPtrSize;
2823
+ const $audioInputs = this.fAudioMixingHalf + this.getNumOutputs() * this.fPtrSize;
2824
+ const $audioOutputs = $audioInputs + this.getNumInputs() * this.fBufferSize * this.fSampleSize;
2825
+ const $audioMixing = $audioOutputs + this.getNumOutputs() * this.fBufferSize * this.fSampleSize;
2826
+ const endMemory = $audioMixing + this.getNumOutputs() * this.fBufferSize * this.fSampleSize;
2827
+ const HEAP = this.fInstance.memory.buffer;
2828
+ const HEAP32 = new Int32Array(HEAP);
2829
+ const HEAPF = this.fSampleSize === 4 ? new Float32Array(HEAP) : new Float64Array(HEAP);
2830
+ if (this.getNumInputs() > 0) {
2831
+ for (let chan = 0; chan < this.getNumInputs(); chan++) {
2832
+ HEAP32[(this.fAudioInputs >> 2) + chan] = $audioInputs + this.fBufferSize * this.fSampleSize * chan;
2833
+ }
2834
+ const dspInChans = HEAP32.subarray(this.fAudioInputs >> 2, this.fAudioInputs + this.getNumInputs() * this.fPtrSize >> 2);
2835
+ for (let chan = 0; chan < this.getNumInputs(); chan++) {
2836
+ this.fInChannels[chan] = HEAPF.subarray(dspInChans[chan] >> Math.log2(this.fSampleSize), dspInChans[chan] + this.fBufferSize * this.fSampleSize >> Math.log2(this.fSampleSize));
2837
+ }
2838
+ }
2839
+ if (this.getNumOutputs() > 0) {
2840
+ for (let chan = 0; chan < this.getNumOutputs(); chan++) {
2841
+ HEAP32[(this.fAudioOutputs >> 2) + chan] = $audioOutputs + this.fBufferSize * this.fSampleSize * chan;
2842
+ HEAP32[(this.fAudioMixing >> 2) + chan] = $audioMixing + this.fBufferSize * this.fSampleSize * chan;
2843
+ HEAP32[(this.fAudioMixingHalf >> 2) + chan] = $audioMixing + this.fBufferSize * this.fSampleSize * chan + this.fBufferSize / 2 * this.fSampleSize;
2844
+ }
2845
+ const dspOutChans = HEAP32.subarray(this.fAudioOutputs >> 2, this.fAudioOutputs + this.getNumOutputs() * this.fPtrSize >> 2);
2846
+ for (let chan = 0; chan < this.getNumOutputs(); chan++) {
2847
+ this.fOutChannels[chan] = HEAPF.subarray(dspOutChans[chan] >> Math.log2(this.fSampleSize), dspOutChans[chan] + this.fBufferSize * this.fSampleSize >> Math.log2(this.fSampleSize));
2848
+ }
2849
+ }
2850
+ return endMemory;
2851
+ }
2852
+ toString() {
2853
+ return `============== Poly Memory layout ==============
2854
+ this.fBufferSize: ${this.fBufferSize}
2855
+ this.fJSONDsp.size: ${this.fJSONDsp.size}
2856
+ this.fAudioInputs: ${this.fAudioInputs}
2857
+ this.fAudioOutputs: ${this.fAudioOutputs}
2858
+ this.fAudioMixing: ${this.fAudioMixing}
2859
+ this.fAudioMixingHalf: ${this.fAudioMixingHalf}`;
2860
+ }
2861
+ allocVoice(voice, type) {
2862
+ this.fVoiceTable[voice].fDate++;
2863
+ this.fVoiceTable[voice].fCurNote = type;
2864
+ return voice;
2865
+ }
2866
+ getPlayingVoice(pitch) {
2867
+ let voicePlaying = FaustWebAudioDspVoice.kNoVoice;
2868
+ let oldestDatePlaying = Number.MAX_VALUE;
2869
+ for (let voice = 0; voice < this.fInstance.voices; voice++) {
2870
+ if (this.fVoiceTable[voice].fCurNote === pitch) {
2871
+ if (this.fVoiceTable[voice].fDate < oldestDatePlaying) {
2872
+ oldestDatePlaying = this.fVoiceTable[voice].fDate;
2873
+ voicePlaying = voice;
2874
+ }
2875
+ }
2876
+ }
2877
+ return voicePlaying;
2878
+ }
2879
+ getFreeVoice() {
2880
+ for (let voice = 0; voice < this.fInstance.voices; voice++) {
2881
+ if (this.fVoiceTable[voice].fCurNote === FaustWebAudioDspVoice.kFreeVoice) {
2882
+ return this.allocVoice(voice, FaustWebAudioDspVoice.kActiveVoice);
2883
+ }
2884
+ }
2885
+ let voiceRelease = FaustWebAudioDspVoice.kNoVoice;
2886
+ let voicePlaying = FaustWebAudioDspVoice.kNoVoice;
2887
+ let oldestDateRelease = Number.MAX_VALUE;
2888
+ let oldestDatePlaying = Number.MAX_VALUE;
2889
+ for (let voice = 0; voice < this.fInstance.voices; voice++) {
2890
+ if (this.fVoiceTable[voice].fCurNote === FaustWebAudioDspVoice.kReleaseVoice) {
2891
+ if (this.fVoiceTable[voice].fDate < oldestDateRelease) {
2892
+ oldestDateRelease = this.fVoiceTable[voice].fDate;
2893
+ voiceRelease = voice;
2894
+ }
2895
+ } else if (this.fVoiceTable[voice].fDate < oldestDatePlaying) {
2896
+ oldestDatePlaying = this.fVoiceTable[voice].fDate;
2897
+ voicePlaying = voice;
2898
+ }
2899
+ }
2900
+ if (oldestDateRelease !== Number.MAX_VALUE) {
2901
+ console.log(`Steal release voice : voice_date = ${this.fVoiceTable[voiceRelease].fDate} voice = ${voiceRelease}`);
2902
+ return this.allocVoice(voiceRelease, FaustWebAudioDspVoice.kLegatoVoice);
2903
+ }
2904
+ if (oldestDatePlaying !== Number.MAX_VALUE) {
2905
+ console.log(`Steal playing voice : voice_date = ${this.fVoiceTable[voicePlaying].fDate} voice = ${voicePlaying}`);
2906
+ return this.allocVoice(voicePlaying, FaustWebAudioDspVoice.kLegatoVoice);
2907
+ }
2908
+ return FaustWebAudioDspVoice.kNoVoice;
2909
+ }
2910
+ // Public API
2911
+ compute(input, output) {
2912
+ if (this.fDestroyed)
2913
+ return false;
2914
+ if (this.fFirstCall) {
2915
+ this.initMemory();
2916
+ this.fFirstCall = false;
2917
+ }
2918
+ if (!this.fProcessing)
2919
+ return true;
2920
+ if (this.getNumInputs() > 0 && (!input || !input[0] || input[0].length === 0)) {
2921
+ return true;
2922
+ }
2923
+ if (this.getNumOutputs() > 0 && (!output || !output[0] || output[0].length === 0)) {
2924
+ return true;
2925
+ }
2926
+ if (input !== void 0) {
2927
+ for (let chan = 0; chan < Math.min(this.getNumInputs(), input.length); ++chan) {
2928
+ const dspInput = this.fInChannels[chan];
2929
+ dspInput.set(input[chan]);
2930
+ }
2931
+ }
2932
+ if (this.fComputeHandler)
2933
+ this.fComputeHandler(this.fBufferSize);
2934
+ this.fInstance.mixerAPI.clearOutput(this.fBufferSize, this.getNumOutputs(), this.fAudioOutputs);
2935
+ this.fVoiceTable.forEach((voice) => {
2936
+ if (voice.fCurNote === FaustWebAudioDspVoice.kLegatoVoice) {
2937
+ voice.computeLegato(this.fBufferSize, this.fAudioInputs, this.fAudioMixing, this.fAudioMixingHalf);
2938
+ this.fInstance.mixerAPI.fadeOut(this.fBufferSize / 2, this.getNumOutputs(), this.fAudioMixing);
2939
+ voice.fLevel = this.fInstance.mixerAPI.mixCheckVoice(this.fBufferSize, this.getNumOutputs(), this.fAudioMixing, this.fAudioOutputs);
2940
+ } else if (voice.fCurNote !== FaustWebAudioDspVoice.kFreeVoice) {
2941
+ voice.compute(this.fBufferSize, this.fAudioInputs, this.fAudioMixing);
2942
+ voice.fLevel = this.fInstance.mixerAPI.mixCheckVoice(this.fBufferSize, this.getNumOutputs(), this.fAudioMixing, this.fAudioOutputs);
2943
+ voice.fRelease -= this.fBufferSize;
2944
+ if (voice.fCurNote == FaustWebAudioDspVoice.kReleaseVoice && (voice.fLevel < FaustWebAudioDspVoice.VOICE_STOP_LEVEL && voice.fRelease < 0)) {
2945
+ voice.fCurNote = FaustWebAudioDspVoice.kFreeVoice;
2946
+ }
2947
+ }
2948
+ });
2949
+ if (this.fInstance.effectAPI)
2950
+ this.fInstance.effectAPI.compute(this.fEffect, this.fBufferSize, this.fAudioOutputs, this.fAudioOutputs);
2951
+ this.updateOutputs();
2952
+ if (output !== void 0) {
2953
+ for (let chan = 0; chan < Math.min(this.getNumOutputs(), output.length); chan++) {
2954
+ const dspOutput = this.fOutChannels[chan];
2955
+ output[chan].set(dspOutput);
2956
+ }
2957
+ if (this.fPlotHandler) {
2958
+ this.fPlotHandler(output, this.fBufferNum++, this.fCachedEvents.length ? this.fCachedEvents : void 0);
2959
+ this.fCachedEvents = [];
2960
+ }
2961
+ }
2962
+ return true;
2963
+ }
2964
+ getNumInputs() {
2965
+ return this.fInstance.voiceAPI.getNumInputs(0);
2966
+ }
2967
+ getNumOutputs() {
2968
+ return this.fInstance.voiceAPI.getNumOutputs(0);
2969
+ }
2970
+ static findPath(o, p) {
2971
+ if (typeof o !== "object") {
2972
+ return false;
2973
+ } else if (o.address) {
2974
+ return o.address === p;
2975
+ } else {
2976
+ for (const k in o) {
2977
+ if (_FaustPolyWebAudioDsp.findPath(o[k], p))
2978
+ return true;
2979
+ }
2980
+ return false;
2981
+ }
2982
+ }
2983
+ setParamValue(path, value) {
2984
+ if (this.fPlotHandler)
2985
+ this.fCachedEvents.push({ type: "param", data: { path, value } });
2986
+ if (this.fJSONEffect && _FaustPolyWebAudioDsp.findPath(this.fJSONEffect.ui, path) && this.fInstance.effectAPI) {
2987
+ this.fInstance.effectAPI.setParamValue(this.fEffect, this.fPathTable[path], value);
2988
+ } else {
2989
+ this.fVoiceTable.forEach((voice) => voice.setParamValue(this.fPathTable[path], value));
2990
+ }
2991
+ }
2992
+ getParamValue(path) {
2993
+ if (this.fJSONEffect && _FaustPolyWebAudioDsp.findPath(this.fJSONEffect.ui, path) && this.fInstance.effectAPI) {
2994
+ return this.fInstance.effectAPI.getParamValue(this.fEffect, this.fPathTable[path]);
2995
+ } else {
2996
+ return this.fVoiceTable[0].getParamValue(this.fPathTable[path]);
2997
+ }
2998
+ }
2999
+ getMeta() {
3000
+ const o = this.fJSONDsp;
3001
+ const e = this.fJSONEffect;
3002
+ const r = { ...o };
3003
+ if (e) {
3004
+ r.ui = [{
3005
+ type: "tgroup",
3006
+ label: "Sequencer",
3007
+ items: [
3008
+ { type: "vgroup", label: "Instrument", items: o.ui },
3009
+ { type: "vgroup", label: "Effect", items: e.ui }
3010
+ ]
3011
+ }];
3012
+ } else {
3013
+ r.ui = [{
3014
+ type: "tgroup",
3015
+ label: "Polyphonic",
3016
+ items: [
3017
+ { type: "vgroup", label: "Voices", items: o.ui }
3018
+ ]
3019
+ }];
3020
+ }
3021
+ return r;
3022
+ }
3023
+ getJSON() {
3024
+ return JSON.stringify(this.getMeta());
3025
+ }
3026
+ getUI() {
3027
+ return this.getMeta().ui;
3028
+ }
3029
+ getDescriptors() {
3030
+ return this.fDescriptor;
3031
+ }
3032
+ midiMessage(data) {
3033
+ const cmd = data[0] >> 4;
3034
+ const channel = data[0] & 15;
3035
+ const data1 = data[1];
3036
+ const data2 = data[2];
3037
+ if (cmd === 8 || cmd === 9 && data2 === 0)
3038
+ return this.keyOff(channel, data1, data2);
3039
+ else if (cmd === 9)
3040
+ return this.keyOn(channel, data1, data2);
3041
+ else
3042
+ super.midiMessage(data);
3043
+ }
3044
+ ctrlChange(channel, ctrl, value) {
3045
+ if (ctrl === 123 || ctrl === 120) {
3046
+ this.allNotesOff(true);
3047
+ } else {
3048
+ super.ctrlChange(channel, ctrl, value);
3049
+ }
3050
+ }
3051
+ keyOn(channel, pitch, velocity) {
3052
+ if (this.fPlotHandler)
3053
+ this.fCachedEvents.push({ type: "keyOn", data: [channel, pitch, velocity] });
3054
+ const voice = this.getFreeVoice();
3055
+ this.fVoiceTable[voice].keyOn(pitch, velocity, this.fVoiceTable[voice].fCurNote == FaustWebAudioDspVoice.kLegatoVoice);
3056
+ }
3057
+ keyOff(channel, pitch, velocity) {
3058
+ if (this.fPlotHandler)
3059
+ this.fCachedEvents.push({ type: "keyOff", data: [channel, pitch, velocity] });
3060
+ const voice = this.getPlayingVoice(pitch);
3061
+ if (voice !== FaustWebAudioDspVoice.kNoVoice) {
3062
+ this.fVoiceTable[voice].keyOff();
3063
+ } else {
3064
+ console.log("Playing pitch = %d not found\n", pitch);
3065
+ }
3066
+ }
3067
+ allNotesOff(hard = true) {
3068
+ this.fCachedEvents.push({ type: "ctrlChange", data: [0, 123, 0] });
3069
+ this.fVoiceTable.forEach((voice) => voice.keyOff(hard));
3070
+ }
3071
+ };
3072
+
3073
+ // src/FaustOfflineProcessor.ts
3074
+ var FaustOfflineProcessor = class {
3075
+ constructor(instance, bufferSize) {
3076
+ this.fDSPCode = instance;
3077
+ this.fBufferSize = bufferSize;
3078
+ this.fInputs = new Array(this.fDSPCode.getNumInputs()).fill(null).map(() => new Float32Array(bufferSize));
3079
+ this.fOutputs = new Array(this.fDSPCode.getNumOutputs()).fill(null).map(() => new Float32Array(bufferSize));
3080
+ }
3081
+ // Public API
3082
+ getParameterDescriptors() {
3083
+ const params = [];
3084
+ const callback = (item) => {
3085
+ let param = null;
3086
+ const polyKeywords = ["/gate", "/freq", "/gain", "/key", "/vel", "/velocity"];
3087
+ const isPolyReserved = "address" in item && !!polyKeywords.find((k) => item.address.endsWith(k));
3088
+ if (this.fDSPCode instanceof FaustMonoWebAudioDsp || !isPolyReserved) {
3089
+ if (item.type === "vslider" || item.type === "hslider" || item.type === "nentry") {
3090
+ param = { name: item.address, defaultValue: item.init || 0, minValue: item.min || 0, maxValue: item.max || 0 };
3091
+ } else if (item.type === "button" || item.type === "checkbox") {
3092
+ param = { name: item.address, defaultValue: item.init || 0, minValue: 0, maxValue: 1 };
3093
+ }
3094
+ }
3095
+ if (param)
3096
+ params.push(param);
3097
+ };
3098
+ FaustBaseWebAudioDsp.parseUI(this.fDSPCode.getUI(), callback);
3099
+ return params;
3100
+ }
3101
+ compute(input, output) {
3102
+ return this.fDSPCode.compute(input, output);
3103
+ }
3104
+ setOutputParamHandler(handler) {
3105
+ this.fDSPCode.setOutputParamHandler(handler);
3106
+ }
3107
+ getOutputParamHandler() {
3108
+ return this.fDSPCode.getOutputParamHandler();
3109
+ }
3110
+ setComputeHandler(handler) {
3111
+ this.fDSPCode.setComputeHandler(handler);
3112
+ }
3113
+ getComputeHandler() {
3114
+ return this.fDSPCode.getComputeHandler();
3115
+ }
3116
+ setPlotHandler(handler) {
3117
+ this.fDSPCode.setPlotHandler(handler);
3118
+ }
3119
+ getPlotHandler() {
3120
+ return this.fDSPCode.getPlotHandler();
3121
+ }
3122
+ getNumInputs() {
3123
+ return this.fDSPCode.getNumInputs();
3124
+ }
3125
+ getNumOutputs() {
3126
+ return this.fDSPCode.getNumOutputs();
3127
+ }
3128
+ metadata(handler) {
3129
+ }
3130
+ midiMessage(data) {
3131
+ this.fDSPCode.midiMessage(data);
3132
+ }
3133
+ ctrlChange(chan, ctrl, value) {
3134
+ this.fDSPCode.ctrlChange(chan, ctrl, value);
3135
+ }
3136
+ pitchWheel(chan, value) {
3137
+ this.fDSPCode.pitchWheel(chan, value);
3138
+ }
3139
+ setParamValue(path, value) {
3140
+ this.fDSPCode.setParamValue(path, value);
3141
+ }
3142
+ getParamValue(path) {
3143
+ return this.fDSPCode.getParamValue(path);
3144
+ }
3145
+ getParams() {
3146
+ return this.fDSPCode.getParams();
3147
+ }
3148
+ getMeta() {
3149
+ return this.fDSPCode.getMeta();
3150
+ }
3151
+ getJSON() {
3152
+ return this.fDSPCode.getJSON();
3153
+ }
3154
+ getDescriptors() {
3155
+ return this.fDSPCode.getDescriptors();
3156
+ }
3157
+ getUI() {
3158
+ return this.fDSPCode.getUI();
3159
+ }
3160
+ start() {
3161
+ this.fDSPCode.start();
3162
+ }
3163
+ stop() {
3164
+ this.fDSPCode.stop();
3165
+ }
3166
+ destroy() {
3167
+ this.fDSPCode.destroy();
3168
+ }
3169
+ get hasAccInput() {
3170
+ return this.fDSPCode.hasAccInput;
3171
+ }
3172
+ propagateAcc(accelerationIncludingGravity, invert = false) {
3173
+ this.fDSPCode.propagateAcc(accelerationIncludingGravity, invert);
3174
+ }
3175
+ get hasGyrInput() {
3176
+ return this.fDSPCode.hasGyrInput;
3177
+ }
3178
+ propagateGyr(event) {
3179
+ this.fDSPCode.propagateGyr(event);
3180
+ }
3181
+ startSensors() {
3182
+ }
3183
+ stopSensors() {
3184
+ }
3185
+ /**
3186
+ * Render frames in an array.
3187
+ *
3188
+ * @param inputs - input signal
3189
+ * @param length - the number of frames to render (default: bufferSize)
3190
+ * @param onUpdate - a callback after each buffer calculated, with an argument "current sample"
3191
+ * @return an array of Float32Array with the rendered frames
3192
+ */
3193
+ render(inputs = [], length = this.fBufferSize, onUpdate) {
3194
+ let l = 0;
3195
+ const outputs = new Array(this.fDSPCode.getNumOutputs()).fill(null).map(() => new Float32Array(length));
3196
+ this.fDSPCode.start();
3197
+ while (l < length) {
3198
+ const sliceLength = Math.min(length - l, this.fBufferSize);
3199
+ for (let i = 0; i < this.fDSPCode.getNumInputs(); i++) {
3200
+ let input;
3201
+ if (inputs[i]) {
3202
+ if (inputs[i].length <= l) {
3203
+ input = new Float32Array(sliceLength);
3204
+ } else if (inputs[i].length > l + sliceLength) {
3205
+ input = inputs[i].subarray(l, l + sliceLength);
3206
+ } else {
3207
+ input = inputs[i].subarray(l, inputs[i].length);
3208
+ }
3209
+ } else {
3210
+ input = new Float32Array(sliceLength);
3211
+ }
3212
+ this.fInputs[i] = input;
3213
+ }
3214
+ this.fDSPCode.compute(this.fInputs, this.fOutputs);
3215
+ for (let i = 0; i < this.fDSPCode.getNumOutputs(); i++) {
3216
+ const output = this.fOutputs[i];
3217
+ if (sliceLength < this.fBufferSize) {
3218
+ outputs[i].set(output.subarray(0, sliceLength), l);
3219
+ } else {
3220
+ outputs[i].set(output, l);
3221
+ }
3222
+ }
3223
+ l += this.fBufferSize;
3224
+ onUpdate == null ? void 0 : onUpdate(l);
3225
+ }
3226
+ this.fDSPCode.stop();
3227
+ return outputs;
3228
+ }
3229
+ };
3230
+ var FaustMonoOfflineProcessor = class extends FaustOfflineProcessor {
3231
+ };
3232
+ var FaustPolyOfflineProcessor = class extends FaustOfflineProcessor {
3233
+ keyOn(channel, pitch, velocity) {
3234
+ this.fDSPCode.keyOn(channel, pitch, velocity);
3235
+ }
3236
+ keyOff(channel, pitch, velocity) {
3237
+ this.fDSPCode.keyOff(channel, pitch, velocity);
3238
+ }
3239
+ allNotesOff(hard) {
3240
+ this.fDSPCode.allNotesOff(hard);
3241
+ }
3242
+ };
3243
+ var FaustOfflineProcessor_default = FaustOfflineProcessor;
3244
+
3245
+ // src/FaustSvgDiagrams.ts
3246
+ var FaustSvgDiagrams = class {
3247
+ constructor(compiler) {
3248
+ this.compiler = compiler;
3249
+ }
3250
+ from(name, code, args) {
3251
+ const fs = this.compiler.fs();
3252
+ try {
3253
+ const files2 = fs.readdir(`/${name}-svg/`);
3254
+ files2.filter((file) => file !== "." && file !== "..").forEach((file) => fs.unlink(`/${name}-svg/${file}`));
3255
+ } catch {
3256
+ }
3257
+ const success = this.compiler.generateAuxFiles(name, code, `-lang wasm -o binary -svg ${args}`);
3258
+ if (!success)
3259
+ throw new Error(this.compiler.getErrorMessage());
3260
+ const svgs = {};
3261
+ const files = fs.readdir(`/${name}-svg/`);
3262
+ files.filter((file) => file !== "." && file !== "..").forEach((file) => svgs[file] = fs.readFile(`/${name}-svg/${file}`, { encoding: "utf8" }));
3263
+ return svgs;
3264
+ }
3265
+ };
3266
+ var FaustSvgDiagrams_default = FaustSvgDiagrams;
3267
+
3268
+ // src/FaustCmajor.ts
3269
+ var FaustCmajor = class {
3270
+ constructor(compiler) {
3271
+ this.fCompiler = compiler;
3272
+ }
3273
+ compile(name, code, args) {
3274
+ const fs = this.fCompiler.fs();
3275
+ const success = this.fCompiler.generateAuxFiles(name, code, `-lang cmajor-hybrid -cn ${name} -o ${name}.cmajor`);
3276
+ return success ? fs.readFile(`${name}.cmajor`, { encoding: "utf8" }) : "";
3277
+ }
3278
+ };
3279
+ var FaustCmajor_default = FaustCmajor;
3280
+
3281
+ // src/LibFaust.ts
3282
+ var LibFaust = class {
3283
+ constructor(module) {
3284
+ this.fModule = module;
3285
+ this.fCompiler = new module.libFaustWasm();
3286
+ this.fFileSystem = this.fModule.FS;
3287
+ }
3288
+ module() {
3289
+ return this.fModule;
3290
+ }
3291
+ fs() {
3292
+ return this.fFileSystem;
3293
+ }
3294
+ version() {
3295
+ return this.fCompiler.version();
3296
+ }
3297
+ createDSPFactory(name, code, args, useInternalMemory) {
3298
+ return this.fCompiler.createDSPFactory(name, code, args, useInternalMemory);
3299
+ }
3300
+ deleteDSPFactory(cFactory) {
3301
+ return this.fCompiler.deleteDSPFactory(cFactory);
3302
+ }
3303
+ expandDSP(name, code, args) {
3304
+ return this.fCompiler.expandDSP(name, code, args);
3305
+ }
3306
+ generateAuxFiles(name, code, args) {
3307
+ return this.fCompiler.generateAuxFiles(name, code, args);
3308
+ }
3309
+ deleteAllDSPFactories() {
3310
+ return this.fCompiler.deleteAllDSPFactories();
3311
+ }
3312
+ getErrorAfterException() {
3313
+ return this.fCompiler.getErrorAfterException();
3314
+ }
3315
+ cleanupAfterException() {
3316
+ return this.fCompiler.cleanupAfterException();
3317
+ }
3318
+ getInfos(what) {
3319
+ return this.fCompiler.getInfos(what);
3320
+ }
3321
+ toString() {
3322
+ return `LibFaust module: ${this.fModule}, compiler: ${this.fCompiler}`;
3323
+ }
3324
+ };
3325
+ var LibFaust_default = LibFaust;
3326
+
3327
+ // src/WavEncoder.ts
3328
+ var WavEncoder = class {
3329
+ static encode(audioBuffer, options) {
3330
+ const numberOfChannels = audioBuffer.length;
3331
+ const length = audioBuffer[0].length;
3332
+ const { shared, float } = options;
3333
+ const bitDepth = float ? 32 : options.bitDepth | 0 || 16;
3334
+ const byteDepth = bitDepth >> 3;
3335
+ const byteLength = length * numberOfChannels * byteDepth;
3336
+ const AB = shared ? globalThis.SharedArrayBuffer || globalThis.ArrayBuffer : globalThis.ArrayBuffer;
3337
+ const ab = new AB((44 + byteLength) * Uint8Array.BYTES_PER_ELEMENT);
3338
+ const dataView = new DataView(ab);
3339
+ const writer = new Writer(dataView);
3340
+ const format = {
3341
+ formatId: float ? 3 : 1,
3342
+ float: !!float,
3343
+ numberOfChannels,
3344
+ sampleRate: options.sampleRate,
3345
+ symmetric: !!options.symmetric,
3346
+ length,
3347
+ bitDepth,
3348
+ byteDepth
3349
+ };
3350
+ this.writeHeader(writer, format);
3351
+ this.writeData(writer, audioBuffer, format);
3352
+ return ab;
3353
+ }
3354
+ static writeHeader(writer, format) {
3355
+ const { formatId, sampleRate, bitDepth, numberOfChannels, length, byteDepth } = format;
3356
+ writer.string("RIFF");
3357
+ writer.uint32(writer.dataView.byteLength - 8);
3358
+ writer.string("WAVE");
3359
+ writer.string("fmt ");
3360
+ writer.uint32(16);
3361
+ writer.uint16(formatId);
3362
+ writer.uint16(numberOfChannels);
3363
+ writer.uint32(sampleRate);
3364
+ writer.uint32(sampleRate * numberOfChannels * byteDepth);
3365
+ writer.uint16(numberOfChannels * byteDepth);
3366
+ writer.uint16(bitDepth);
3367
+ writer.string("data");
3368
+ writer.uint32(length * numberOfChannels * byteDepth);
3369
+ return writer.pos;
3370
+ }
3371
+ static writeData(writer, audioBuffer, format) {
3372
+ const { bitDepth, float, length, numberOfChannels, symmetric } = format;
3373
+ if (bitDepth === 32 && float) {
3374
+ const { dataView, pos } = writer;
3375
+ const ab = dataView.buffer;
3376
+ const f32View = new Float32Array(ab, pos);
3377
+ if (numberOfChannels === 1) {
3378
+ f32View.set(audioBuffer[0]);
3379
+ return;
3380
+ }
3381
+ for (let ch = 0; ch < numberOfChannels; ch++) {
3382
+ const channel = audioBuffer[ch];
3383
+ for (let i = 0; i < length; i++) {
3384
+ f32View[i * numberOfChannels + ch] = channel[i];
3385
+ }
3386
+ }
3387
+ return;
3388
+ }
3389
+ const encoderOption = float ? "f" : symmetric ? "s" : "";
3390
+ const methodName = "pcm" + bitDepth + encoderOption;
3391
+ if (!writer[methodName]) {
3392
+ throw new TypeError("Not supported bit depth: " + bitDepth);
3393
+ }
3394
+ const write = writer[methodName].bind(writer);
3395
+ for (let i = 0; i < length; i++) {
3396
+ for (let j = 0; j < numberOfChannels; j++) {
3397
+ write(audioBuffer[j][i]);
3398
+ }
3399
+ }
3400
+ }
3401
+ };
3402
+ var Writer = class {
3403
+ constructor(dataView) {
3404
+ this.pos = 0;
3405
+ this.dataView = dataView;
3406
+ }
3407
+ int16(value) {
3408
+ this.dataView.setInt16(this.pos, value, true);
3409
+ this.pos += 2;
3410
+ }
3411
+ uint16(value) {
3412
+ this.dataView.setUint16(this.pos, value, true);
3413
+ this.pos += 2;
3414
+ }
3415
+ uint32(value) {
3416
+ this.dataView.setUint32(this.pos, value, true);
3417
+ this.pos += 4;
3418
+ }
3419
+ string(value) {
3420
+ for (let i = 0, imax = value.length; i < imax; i++) {
3421
+ this.dataView.setUint8(this.pos++, value.charCodeAt(i));
3422
+ }
3423
+ }
3424
+ pcm8(valueIn) {
3425
+ let value = valueIn;
3426
+ value = Math.max(-1, Math.min(value, 1));
3427
+ value = (value * 0.5 + 0.5) * 255;
3428
+ value = Math.round(value) | 0;
3429
+ this.dataView.setUint8(
3430
+ this.pos,
3431
+ value
3432
+ /* , true*/
3433
+ );
3434
+ this.pos += 1;
3435
+ }
3436
+ pcm8s(valueIn) {
3437
+ let value = valueIn;
3438
+ value = Math.round(value * 128) + 128;
3439
+ value = Math.max(0, Math.min(value, 255));
3440
+ this.dataView.setUint8(
3441
+ this.pos,
3442
+ value
3443
+ /* , true*/
3444
+ );
3445
+ this.pos += 1;
3446
+ }
3447
+ pcm16(valueIn) {
3448
+ let value = valueIn;
3449
+ value = Math.max(-1, Math.min(value, 1));
3450
+ value = value < 0 ? value * 32768 : value * 32767;
3451
+ value = Math.round(value) | 0;
3452
+ this.dataView.setInt16(this.pos, value, true);
3453
+ this.pos += 2;
3454
+ }
3455
+ pcm16s(valueIn) {
3456
+ let value = valueIn;
3457
+ value = Math.round(value * 32768);
3458
+ value = Math.max(-32768, Math.min(value, 32767));
3459
+ this.dataView.setInt16(this.pos, value, true);
3460
+ this.pos += 2;
3461
+ }
3462
+ pcm24(valueIn) {
3463
+ let value = valueIn;
3464
+ value = Math.max(-1, Math.min(value, 1));
3465
+ value = value < 0 ? 16777216 + value * 8388608 : value * 8388607;
3466
+ value = Math.round(value) | 0;
3467
+ const x0 = value >> 0 & 255;
3468
+ const x1 = value >> 8 & 255;
3469
+ const x2 = value >> 16 & 255;
3470
+ this.dataView.setUint8(this.pos + 0, x0);
3471
+ this.dataView.setUint8(this.pos + 1, x1);
3472
+ this.dataView.setUint8(this.pos + 2, x2);
3473
+ this.pos += 3;
3474
+ }
3475
+ pcm24s(valueIn) {
3476
+ let value = valueIn;
3477
+ value = Math.round(value * 8388608);
3478
+ value = Math.max(-8388608, Math.min(value, 8388607));
3479
+ const x0 = value >> 0 & 255;
3480
+ const x1 = value >> 8 & 255;
3481
+ const x2 = value >> 16 & 255;
3482
+ this.dataView.setUint8(this.pos + 0, x0);
3483
+ this.dataView.setUint8(this.pos + 1, x1);
3484
+ this.dataView.setUint8(this.pos + 2, x2);
3485
+ this.pos += 3;
3486
+ }
3487
+ pcm32(valueIn) {
3488
+ let value = valueIn;
3489
+ value = Math.max(-1, Math.min(value, 1));
3490
+ value = value < 0 ? value * 2147483648 : value * 2147483647;
3491
+ value = Math.round(value) | 0;
3492
+ this.dataView.setInt32(this.pos, value, true);
3493
+ this.pos += 4;
3494
+ }
3495
+ pcm32s(valueIn) {
3496
+ let value = valueIn;
3497
+ value = Math.round(value * 2147483648);
3498
+ value = Math.max(-2147483648, Math.min(value, 2147483647));
3499
+ this.dataView.setInt32(this.pos, value, true);
3500
+ this.pos += 4;
3501
+ }
3502
+ pcm32f(value) {
3503
+ this.dataView.setFloat32(this.pos, value, true);
3504
+ this.pos += 4;
3505
+ }
3506
+ };
3507
+ var WavEncoder_default = WavEncoder;
3508
+
3509
+ // src/WavDecoder.ts
3510
+ var WavDecoder = class {
3511
+ static decode(buffer, options) {
3512
+ const dataView = new DataView(buffer);
3513
+ const reader = new Reader(dataView);
3514
+ if (reader.string(4) !== "RIFF") {
3515
+ throw new TypeError("Invalid WAV file");
3516
+ }
3517
+ reader.uint32();
3518
+ if (reader.string(4) !== "WAVE") {
3519
+ throw new TypeError("Invalid WAV file");
3520
+ }
3521
+ let format = null;
3522
+ let audioData = null;
3523
+ do {
3524
+ const chunkType = reader.string(4);
3525
+ const chunkSize = reader.uint32();
3526
+ if (chunkType === "fmt ") {
3527
+ format = this.decodeFormat(reader, chunkSize);
3528
+ } else if (chunkType === "data") {
3529
+ audioData = this.decodeData(reader, chunkSize, format, options || {});
3530
+ } else {
3531
+ reader.skip(chunkSize);
3532
+ }
3533
+ } while (audioData === null);
3534
+ return audioData;
3535
+ }
3536
+ static decodeFormat(reader, chunkSize) {
3537
+ const formats = {
3538
+ 1: "lpcm",
3539
+ 3: "lpcm"
3540
+ };
3541
+ const formatId = reader.uint16();
3542
+ if (!formats.hasOwnProperty(formatId)) {
3543
+ throw new TypeError("Unsupported format in WAV file: 0x" + formatId.toString(16));
3544
+ }
3545
+ const format = {
3546
+ formatId,
3547
+ float: formatId === 3,
3548
+ numberOfChannels: reader.uint16(),
3549
+ sampleRate: reader.uint32(),
3550
+ byteRate: reader.uint32(),
3551
+ blockSize: reader.uint16(),
3552
+ bitDepth: reader.uint16()
3553
+ };
3554
+ reader.skip(chunkSize - 16);
3555
+ return format;
3556
+ }
3557
+ static decodeData(reader, chunkSizeIn, format, options) {
3558
+ const chunkSize = Math.min(chunkSizeIn, reader.remain());
3559
+ const length = Math.floor(chunkSize / format.blockSize);
3560
+ const numberOfChannels = format.numberOfChannels;
3561
+ const sampleRate = format.sampleRate;
3562
+ const channelData = new Array(numberOfChannels);
3563
+ for (let ch = 0; ch < numberOfChannels; ch++) {
3564
+ const AB = options.shared ? globalThis.SharedArrayBuffer || globalThis.ArrayBuffer : globalThis.ArrayBuffer;
3565
+ const ab = new AB(length * Float32Array.BYTES_PER_ELEMENT);
3566
+ channelData[ch] = new Float32Array(ab);
3567
+ }
3568
+ this.readPCM(reader, channelData, length, format, options);
3569
+ return {
3570
+ numberOfChannels,
3571
+ length,
3572
+ sampleRate,
3573
+ channelData
3574
+ };
3575
+ }
3576
+ static readPCM(reader, channelData, length, format, options) {
3577
+ const bitDepth = format.bitDepth;
3578
+ const decoderOption = format.float ? "f" : options.symmetric ? "s" : "";
3579
+ const methodName = "pcm" + bitDepth + decoderOption;
3580
+ if (!reader[methodName]) {
3581
+ throw new TypeError("Not supported bit depth: " + format.bitDepth);
3582
+ }
3583
+ const read = reader[methodName].bind(reader);
3584
+ const numberOfChannels = format.numberOfChannels;
3585
+ for (let i = 0; i < length; i++) {
3586
+ for (let ch = 0; ch < numberOfChannels; ch++) {
3587
+ channelData[ch][i] = read();
3588
+ }
3589
+ }
3590
+ }
3591
+ };
3592
+ var Reader = class {
3593
+ constructor(dataView) {
3594
+ this.pos = 0;
3595
+ this.dataView = dataView;
3596
+ }
3597
+ remain() {
3598
+ return this.dataView.byteLength - this.pos;
3599
+ }
3600
+ skip(n) {
3601
+ this.pos += n;
3602
+ }
3603
+ uint8() {
3604
+ const data = this.dataView.getUint8(this.pos);
3605
+ this.pos += 1;
3606
+ return data;
3607
+ }
3608
+ int16() {
3609
+ const data = this.dataView.getInt16(this.pos, true);
3610
+ this.pos += 2;
3611
+ return data;
3612
+ }
3613
+ uint16() {
3614
+ const data = this.dataView.getUint16(this.pos, true);
3615
+ this.pos += 2;
3616
+ return data;
3617
+ }
3618
+ uint32() {
3619
+ const data = this.dataView.getUint32(this.pos, true);
3620
+ this.pos += 4;
3621
+ return data;
3622
+ }
3623
+ string(n) {
3624
+ let data = "";
3625
+ for (let i = 0; i < n; i++) {
3626
+ data += String.fromCharCode(this.uint8());
3627
+ }
3628
+ return data;
3629
+ }
3630
+ pcm8() {
3631
+ const data = this.dataView.getUint8(this.pos) - 128;
3632
+ this.pos += 1;
3633
+ return data < 0 ? data / 128 : data / 127;
3634
+ }
3635
+ pcm8s() {
3636
+ const data = this.dataView.getUint8(this.pos) - 127.5;
3637
+ this.pos += 1;
3638
+ return data / 127.5;
3639
+ }
3640
+ pcm16() {
3641
+ const data = this.dataView.getInt16(this.pos, true);
3642
+ this.pos += 2;
3643
+ return data < 0 ? data / 32768 : data / 32767;
3644
+ }
3645
+ pcm16s() {
3646
+ const data = this.dataView.getInt16(this.pos, true);
3647
+ this.pos += 2;
3648
+ return data / 32768;
3649
+ }
3650
+ pcm24() {
3651
+ const x0 = this.dataView.getUint8(this.pos + 0);
3652
+ const x1 = this.dataView.getUint8(this.pos + 1);
3653
+ const x2 = this.dataView.getUint8(this.pos + 2);
3654
+ const xx = x0 + (x1 << 8) + (x2 << 16);
3655
+ const data = xx > 8388608 ? xx - 16777216 : xx;
3656
+ this.pos += 3;
3657
+ return data < 0 ? data / 8388608 : data / 8388607;
3658
+ }
3659
+ pcm24s() {
3660
+ const x0 = this.dataView.getUint8(this.pos + 0);
3661
+ const x1 = this.dataView.getUint8(this.pos + 1);
3662
+ const x2 = this.dataView.getUint8(this.pos + 2);
3663
+ const xx = x0 + (x1 << 8) + (x2 << 16);
3664
+ const data = xx > 8388608 ? xx - 16777216 : xx;
3665
+ this.pos += 3;
3666
+ return data / 8388608;
3667
+ }
3668
+ pcm32() {
3669
+ const data = this.dataView.getInt32(this.pos, true);
3670
+ this.pos += 4;
3671
+ return data < 0 ? data / 2147483648 : data / 2147483647;
3672
+ }
3673
+ pcm32s() {
3674
+ const data = this.dataView.getInt32(this.pos, true);
3675
+ this.pos += 4;
3676
+ return data / 2147483648;
3677
+ }
3678
+ pcm32f() {
3679
+ const data = this.dataView.getFloat32(this.pos, true);
3680
+ this.pos += 4;
3681
+ return data;
3682
+ }
3683
+ pcm64f() {
3684
+ const data = this.dataView.getFloat64(this.pos, true);
3685
+ this.pos += 8;
3686
+ return data;
3687
+ }
3688
+ };
3689
+ var WavDecoder_default = WavDecoder;
3690
+
3691
+ // src/SoundfileReader.ts
3692
+ var SoundfileReader = class {
3693
+ // Set the fallback paths
3694
+ static get fallbackPaths() {
3695
+ return [location.href, this.getParentUrl(location.href), location.origin];
3696
+ }
3697
+ /**
3698
+ * Extract the parent URL from an URL.
3699
+ * @param url : the URL
3700
+ * @returns : the parent URL
3701
+ */
3702
+ static getParentUrl(url) {
3703
+ return url.substring(0, url.lastIndexOf("/") + 1);
3704
+ }
3705
+ /**
3706
+ * Convert an audio buffer to audio data.
3707
+ *
3708
+ * @param audioBuffer : the audio buffer to convert
3709
+ * @returns : the audio data
3710
+ */
3711
+ static toAudioData(audioBuffer) {
3712
+ const { sampleRate, numberOfChannels } = audioBuffer;
3713
+ return {
3714
+ sampleRate,
3715
+ audioBuffer: new Array(numberOfChannels).fill(null).map((v, i) => audioBuffer.getChannelData(i))
3716
+ };
3717
+ }
3718
+ /**
3719
+ * Extract the URLs from the metadata.
3720
+ *
3721
+ * @param dspMeta : the metadata
3722
+ * @returns : the URLs
3723
+ */
3724
+ static findSoundfilesFromMeta(dspMeta) {
3725
+ const soundfiles = {};
3726
+ const callback = (item) => {
3727
+ if (item.type === "soundfile") {
3728
+ const urls = FaustBaseWebAudioDsp.splitSoundfileNames(item.url);
3729
+ urls.forEach((url) => soundfiles[url] = null);
3730
+ }
3731
+ };
3732
+ FaustBaseWebAudioDsp.parseUI(dspMeta.ui, callback);
3733
+ return soundfiles;
3734
+ }
3735
+ /**
3736
+ * Check if the file exists.
3737
+ *
3738
+ * @param url : the url of the file to check
3739
+ * @returns : true if the file exists, otherwise false
3740
+ */
3741
+ static async checkFileExists(url) {
3742
+ try {
3743
+ console.log(`"checkFileExists" url: ${url}`);
3744
+ const response = await fetch(url);
3745
+ console.log(`"checkFileExists" response.ok: ${response.ok}`);
3746
+ return response.ok;
3747
+ } catch (error) {
3748
+ console.error("Fetch error:", error);
3749
+ return false;
3750
+ }
3751
+ }
3752
+ /**
3753
+ * Fetch the soundfile.
3754
+ *
3755
+ * @param url : the url of the soundfile
3756
+ * @param audioCtx : the audio context
3757
+ * @returns : the audio data
3758
+ */
3759
+ static async fetchSoundfile(url, audioCtx) {
3760
+ console.log(`Loading sound file from ${url}`);
3761
+ const response = await fetch(url);
3762
+ if (!response.ok)
3763
+ throw new Error(`Failed to load sound file from ${url}: ${response.statusText}`);
3764
+ const arrayBuffer = await response.arrayBuffer();
3765
+ const audioBuffer = await audioCtx.decodeAudioData(arrayBuffer);
3766
+ return this.toAudioData(audioBuffer);
3767
+ }
3768
+ /**
3769
+ * Load the soundfile.
3770
+ *
3771
+ * @param filename : the filename
3772
+ * @param metaUrls : the metadata URLs
3773
+ * @param soundfiles : the soundfiles
3774
+ * @param audioCtx : the audio context
3775
+ */
3776
+ static async loadSoundfile(filename, metaUrls, soundfiles, audioCtx) {
3777
+ if (soundfiles[filename])
3778
+ return;
3779
+ const urlsToCheck = [filename, ...[...metaUrls, ...this.fallbackPaths].map((path) => new URL(filename, path.endsWith("/") ? path : `${path}/`).href)];
3780
+ const checkResults = await Promise.all(urlsToCheck.map((url) => this.checkFileExists(url)));
3781
+ const successIndex = checkResults.findIndex((r) => !!r);
3782
+ if (successIndex === -1)
3783
+ throw new Error(`Failed to load sound file ${filename}, all check failed.`);
3784
+ soundfiles[filename] = await this.fetchSoundfile(urlsToCheck[successIndex], audioCtx);
3785
+ }
3786
+ /**
3787
+ * Load the soundfiles, public API.
3788
+ *
3789
+ * @param dspMeta : the metadata
3790
+ * @param soundfilesIn : the soundfiles
3791
+ * @param audioCtx : the audio context
3792
+ * @returns : the soundfiles
3793
+ */
3794
+ static async loadSoundfiles(dspMeta, soundfilesIn, audioCtx) {
3795
+ const metaUrls = FaustBaseWebAudioDsp.extractUrlsFromMeta(dspMeta);
3796
+ const soundfiles = this.findSoundfilesFromMeta(dspMeta);
3797
+ for (const id in soundfiles) {
3798
+ if (soundfilesIn[id]) {
3799
+ soundfiles[id] = soundfilesIn[id];
3800
+ continue;
3801
+ }
3802
+ try {
3803
+ await this.loadSoundfile(id, metaUrls, soundfiles, audioCtx);
3804
+ } catch (error) {
3805
+ console.error(error);
3806
+ }
3807
+ }
3808
+ return soundfiles;
3809
+ }
3810
+ };
3811
+ var SoundfileReader_default = SoundfileReader;
3812
+
3813
+ // src/FaustAudioWorkletCommunicator.ts
3814
+ var FaustAudioWorkletCommunicator = class {
3815
+ constructor(port) {
3816
+ this.port = port;
3817
+ this.supportSharedArrayBuffer = !!globalThis.SharedArrayBuffer;
3818
+ this.byteLength = 4 * Uint8Array.BYTES_PER_ELEMENT + 3 * Float32Array.BYTES_PER_ELEMENT + 3 * Float32Array.BYTES_PER_ELEMENT;
3819
+ }
3820
+ initializeBuffer(ab) {
3821
+ let ptr = 0;
3822
+ this.uin8Invert = new Uint8ClampedArray(ab, ptr, 1);
3823
+ ptr += Uint8ClampedArray.BYTES_PER_ELEMENT;
3824
+ this.uin8NewAccData = new Uint8ClampedArray(ab, ptr, 1);
3825
+ ptr += Uint8ClampedArray.BYTES_PER_ELEMENT;
3826
+ this.uin8NewGyrData = new Uint8ClampedArray(ab, ptr, 1);
3827
+ ptr += Uint8ClampedArray.BYTES_PER_ELEMENT;
3828
+ ptr += Uint8ClampedArray.BYTES_PER_ELEMENT;
3829
+ ;
3830
+ this.f32Acc = new Float32Array(ab, ptr, 3);
3831
+ ptr += 3 * Float32Array.BYTES_PER_ELEMENT;
3832
+ this.f32Gyr = new Float32Array(ab, ptr, 3);
3833
+ ptr += 3 * Float32Array.BYTES_PER_ELEMENT;
3834
+ }
3835
+ setNewAccDataAvailable(value) {
3836
+ if (!this.uin8NewAccData)
3837
+ return;
3838
+ this.uin8NewAccData[0] = +value;
3839
+ }
3840
+ getNewAccDataAvailable() {
3841
+ var _a;
3842
+ return !!((_a = this.uin8NewAccData) == null ? void 0 : _a[0]);
3843
+ }
3844
+ setNewGyrDataAvailable(value) {
3845
+ if (!this.uin8NewGyrData)
3846
+ return;
3847
+ this.uin8NewGyrData[0] = +value;
3848
+ }
3849
+ getNewGyrDataAvailable() {
3850
+ var _a;
3851
+ return !!((_a = this.uin8NewGyrData) == null ? void 0 : _a[0]);
3852
+ }
3853
+ setAcc({ x, y, z }, invert = false) {
3854
+ if (!this.supportSharedArrayBuffer) {
3855
+ const e = { type: "acc", data: { x, y, z }, invert };
3856
+ this.port.postMessage(e);
3857
+ }
3858
+ if (!this.uin8NewAccData)
3859
+ return;
3860
+ this.uin8Invert[0] = +invert;
3861
+ this.f32Acc[0] = x;
3862
+ this.f32Acc[1] = y;
3863
+ this.f32Acc[2] = z;
3864
+ this.uin8NewAccData[0] = 1;
3865
+ }
3866
+ getAcc() {
3867
+ if (!this.uin8NewAccData)
3868
+ return;
3869
+ const invert = !!this.uin8Invert[0];
3870
+ const [x, y, z] = this.f32Acc;
3871
+ return { x, y, z, invert };
3872
+ }
3873
+ setGyr({ alpha, beta, gamma }) {
3874
+ if (!this.supportSharedArrayBuffer) {
3875
+ const e = { type: "gyr", data: { alpha, beta, gamma } };
3876
+ this.port.postMessage(e);
3877
+ }
3878
+ if (!this.uin8NewGyrData)
3879
+ return;
3880
+ this.f32Gyr[0] = alpha;
3881
+ this.f32Gyr[1] = beta;
3882
+ this.f32Gyr[2] = gamma;
3883
+ this.uin8NewGyrData[0] = 1;
3884
+ }
3885
+ getGyr() {
3886
+ if (!this.uin8NewGyrData)
3887
+ return;
3888
+ const [alpha, beta, gamma] = this.f32Gyr;
3889
+ return { alpha, beta, gamma };
3890
+ }
3891
+ };
3892
+ var FaustAudioWorkletNodeCommunicator = class extends FaustAudioWorkletCommunicator {
3893
+ constructor(port) {
3894
+ super(port);
3895
+ if (this.supportSharedArrayBuffer) {
3896
+ const sab = new SharedArrayBuffer(this.byteLength);
3897
+ this.initializeBuffer(sab);
3898
+ this.port.postMessage({ type: "initSab", sab });
3899
+ } else {
3900
+ const ab = new ArrayBuffer(this.byteLength);
3901
+ this.initializeBuffer(ab);
3902
+ }
3903
+ }
3904
+ };
3905
+ var FaustAudioWorkletProcessorCommunicator = class extends FaustAudioWorkletCommunicator {
3906
+ constructor(port) {
3907
+ super(port);
3908
+ if (this.supportSharedArrayBuffer) {
3909
+ this.port.addEventListener("message", (event) => {
3910
+ const { data } = event;
3911
+ if (data.type === "initSab") {
3912
+ this.initializeBuffer(data.sab);
3913
+ }
3914
+ });
3915
+ } else {
3916
+ const ab = new ArrayBuffer(this.byteLength);
3917
+ this.initializeBuffer(ab);
3918
+ this.port.addEventListener("message", (event) => {
3919
+ const msg = event.data;
3920
+ switch (msg.type) {
3921
+ case "acc": {
3922
+ this.setAcc(msg.data, msg.invert);
3923
+ break;
3924
+ }
3925
+ case "gyr": {
3926
+ this.setGyr(msg.data);
3927
+ break;
3928
+ }
3929
+ default:
3930
+ break;
3931
+ }
3932
+ });
3933
+ }
3934
+ }
3935
+ };
3936
+
3937
+ // src/FaustAudioWorkletNode.ts
3938
+ var _hasAccInput, _hasGyrInput;
3939
+ var FaustAudioWorkletNode = class extends (globalThis.AudioWorkletNode || null) {
3940
+ constructor(context, name, factory, options = {}) {
3941
+ const JSONObj = JSON.parse(factory.json);
3942
+ super(context, name, {
3943
+ numberOfInputs: JSONObj.inputs > 0 ? 1 : 0,
3944
+ numberOfOutputs: JSONObj.outputs > 0 ? 1 : 0,
3945
+ channelCount: Math.max(1, JSONObj.inputs),
3946
+ outputChannelCount: [JSONObj.outputs],
3947
+ channelCountMode: "explicit",
3948
+ channelInterpretation: "speakers",
3949
+ processorOptions: options.processorOptions,
3950
+ ...options
3951
+ });
3952
+ __privateAdd(this, _hasAccInput, false);
3953
+ __privateAdd(this, _hasGyrInput, false);
3954
+ this.handleMessageAux = (e) => {
3955
+ if (e.data.type === "param" && this.fOutputHandler) {
3956
+ this.fOutputHandler(e.data.path, e.data.value);
3957
+ } else if (e.data.type === "plot" && this.fPlotHandler) {
3958
+ this.fPlotHandler(e.data.value, e.data.index, e.data.events);
3959
+ }
3960
+ };
3961
+ // Accelerometer and gyroscope handlers
3962
+ this.handleDeviceMotion = ({ accelerationIncludingGravity }) => {
3963
+ const isAndroid = /Android/i.test(navigator.userAgent);
3964
+ if (!accelerationIncludingGravity)
3965
+ return;
3966
+ const { x, y, z } = accelerationIncludingGravity;
3967
+ this.propagateAcc({ x, y, z }, isAndroid);
3968
+ };
3969
+ this.handleDeviceOrientation = ({ alpha, beta, gamma }) => {
3970
+ this.propagateGyr({ alpha, beta, gamma });
3971
+ };
3972
+ this.fJSONDsp = JSONObj;
3973
+ this.fJSON = factory.json;
3974
+ this.fOutputHandler = null;
3975
+ this.fComputeHandler = null;
3976
+ this.fPlotHandler = null;
3977
+ this.fDescriptor = [];
3978
+ this.fInputsItems = [];
3979
+ this.fUICallback = (item) => {
3980
+ if (item.type === "vslider" || item.type === "hslider" || item.type === "button" || item.type === "checkbox" || item.type === "nentry") {
3981
+ this.fInputsItems.push(item.address);
3982
+ this.fDescriptor.push(item);
3983
+ if (!item.meta)
3984
+ return;
3985
+ item.meta.forEach((meta) => {
3986
+ const { midi, acc, gyr } = meta;
3987
+ if (acc)
3988
+ __privateSet(this, _hasAccInput, true);
3989
+ if (gyr)
3990
+ __privateSet(this, _hasGyrInput, true);
3991
+ });
3992
+ }
3993
+ };
3994
+ FaustBaseWebAudioDsp.parseUI(this.fJSONDsp.ui, this.fUICallback);
3995
+ this.fCommunicator = new FaustAudioWorkletNodeCommunicator(this.port);
3996
+ this.port.addEventListener("message", this.handleMessageAux);
3997
+ this.port.start();
3998
+ }
3999
+ // Public API
4000
+ /** Setup accelerometer and gyroscope handlers */
4001
+ async startSensors() {
4002
+ if (this.hasAccInput) {
4003
+ if (window.DeviceMotionEvent) {
4004
+ window.addEventListener("devicemotion", this.handleDeviceMotion, true);
4005
+ } else {
4006
+ console.log("Cannot set the accelerometer handler.");
4007
+ }
4008
+ }
4009
+ if (this.hasGyrInput) {
4010
+ if (window.DeviceMotionEvent) {
4011
+ window.addEventListener("deviceorientation", this.handleDeviceOrientation, true);
4012
+ } else {
4013
+ console.log("Cannot set the gyroscope handler.");
4014
+ }
4015
+ }
4016
+ }
4017
+ stopSensors() {
4018
+ if (this.hasAccInput) {
4019
+ window.removeEventListener("devicemotion", this.handleDeviceMotion, true);
4020
+ }
4021
+ if (this.hasGyrInput) {
4022
+ window.removeEventListener("deviceorientation", this.handleDeviceOrientation, true);
4023
+ }
4024
+ }
4025
+ setOutputParamHandler(handler) {
4026
+ this.fOutputHandler = handler;
4027
+ }
4028
+ getOutputParamHandler() {
4029
+ return this.fOutputHandler;
4030
+ }
4031
+ setComputeHandler(handler) {
4032
+ this.fComputeHandler = handler;
4033
+ }
4034
+ getComputeHandler() {
4035
+ return this.fComputeHandler;
4036
+ }
4037
+ setPlotHandler(handler) {
4038
+ this.fPlotHandler = handler;
4039
+ if (this.fPlotHandler) {
4040
+ this.port.postMessage({ type: "setPlotHandler", data: true });
4041
+ } else {
4042
+ this.port.postMessage({ type: "setPlotHandler", data: false });
4043
+ }
4044
+ }
4045
+ getPlotHandler() {
4046
+ return this.fPlotHandler;
4047
+ }
4048
+ setupWamEventHandler() {
4049
+ this.port.postMessage({ type: "setupWamEventHandler" });
4050
+ }
4051
+ getNumInputs() {
4052
+ return this.fJSONDsp.inputs;
4053
+ }
4054
+ getNumOutputs() {
4055
+ return this.fJSONDsp.outputs;
4056
+ }
4057
+ // Implemented in subclasses
4058
+ compute(inputs, outputs) {
4059
+ return false;
4060
+ }
4061
+ metadata(handler) {
4062
+ if (this.fJSONDsp.meta) {
4063
+ this.fJSONDsp.meta.forEach((meta) => handler(Object.keys(meta)[0], meta[Object.keys(meta)[0]]));
4064
+ }
4065
+ }
4066
+ midiMessage(data) {
4067
+ const cmd = data[0] >> 4;
4068
+ const channel = data[0] & 15;
4069
+ const data1 = data[1];
4070
+ const data2 = data[2];
4071
+ if (cmd === 11)
4072
+ this.ctrlChange(channel, data1, data2);
4073
+ else if (cmd === 14)
4074
+ this.pitchWheel(channel, data2 * 128 + data1);
4075
+ if (cmd === 8 || cmd === 9 && data2 === 0)
4076
+ this.keyOff(channel, data1, data2);
4077
+ else if (cmd === 9)
4078
+ this.keyOn(channel, data1, data2);
4079
+ else
4080
+ this.port.postMessage({ type: "midi", data });
4081
+ }
4082
+ ctrlChange(channel, ctrl, value) {
4083
+ const e = { type: "ctrlChange", data: [channel, ctrl, value] };
4084
+ this.port.postMessage(e);
4085
+ }
4086
+ pitchWheel(channel, wheel) {
4087
+ const e = { type: "pitchWheel", data: [channel, wheel] };
4088
+ this.port.postMessage(e);
4089
+ }
4090
+ keyOn(channel, pitch, velocity) {
4091
+ const e = { type: "keyOn", data: [channel, pitch, velocity] };
4092
+ this.port.postMessage(e);
4093
+ }
4094
+ keyOff(channel, pitch, velocity) {
4095
+ const e = { type: "keyOff", data: [channel, pitch, velocity] };
4096
+ this.port.postMessage(e);
4097
+ }
4098
+ get hasAccInput() {
4099
+ return __privateGet(this, _hasAccInput);
4100
+ }
4101
+ propagateAcc(accelerationIncludingGravity, invert = false) {
4102
+ if (!accelerationIncludingGravity)
4103
+ return;
4104
+ const { x, y, z } = accelerationIncludingGravity;
4105
+ this.fCommunicator.setAcc({ x, y, z }, invert);
4106
+ }
4107
+ get hasGyrInput() {
4108
+ return __privateGet(this, _hasGyrInput);
4109
+ }
4110
+ propagateGyr(event) {
4111
+ if (!event)
4112
+ return;
4113
+ const { alpha, beta, gamma } = event;
4114
+ this.fCommunicator.setGyr({ alpha, beta, gamma });
4115
+ }
4116
+ setParamValue(path, value) {
4117
+ const e = { type: "param", data: { path, value } };
4118
+ this.port.postMessage(e);
4119
+ const param = this.parameters.get(path);
4120
+ if (param)
4121
+ param.setValueAtTime(value, this.context.currentTime);
4122
+ }
4123
+ getParamValue(path) {
4124
+ const param = this.parameters.get(path);
4125
+ return param ? param.value : 0;
4126
+ }
4127
+ getParams() {
4128
+ return this.fInputsItems;
4129
+ }
4130
+ getMeta() {
4131
+ return this.fJSONDsp;
4132
+ }
4133
+ getJSON() {
4134
+ return JSON.stringify(this.getMeta());
4135
+ }
4136
+ getUI() {
4137
+ return this.fJSONDsp.ui;
4138
+ }
4139
+ getDescriptors() {
4140
+ return this.fDescriptor;
4141
+ }
4142
+ start() {
4143
+ this.port.postMessage({ type: "start" });
4144
+ }
4145
+ stop() {
4146
+ this.port.postMessage({ type: "stop" });
4147
+ }
4148
+ destroy() {
4149
+ this.port.postMessage({ type: "destroy" });
4150
+ this.port.close();
4151
+ }
4152
+ };
4153
+ _hasAccInput = new WeakMap();
4154
+ _hasGyrInput = new WeakMap();
4155
+ var FaustMonoAudioWorkletNode = class extends FaustAudioWorkletNode {
4156
+ constructor(context, options) {
4157
+ super(context, options.processorOptions.name, options.processorOptions.factory, options);
4158
+ this.onprocessorerror = (e) => {
4159
+ throw e;
4160
+ };
4161
+ }
4162
+ };
4163
+ var FaustPolyAudioWorkletNode = class extends FaustAudioWorkletNode {
4164
+ constructor(context, options) {
4165
+ super(
4166
+ context,
4167
+ options.processorOptions.name,
4168
+ options.processorOptions.voiceFactory,
4169
+ options
4170
+ );
4171
+ this.onprocessorerror = (e) => {
4172
+ throw e;
4173
+ };
4174
+ this.fJSONEffect = options.processorOptions.effectFactory ? JSON.parse(options.processorOptions.effectFactory.json) : null;
4175
+ if (this.fJSONEffect) {
4176
+ FaustBaseWebAudioDsp.parseUI(this.fJSONEffect.ui, this.fUICallback);
4177
+ }
4178
+ }
4179
+ // Public API
4180
+ keyOn(channel, pitch, velocity) {
4181
+ const e = { type: "keyOn", data: [channel, pitch, velocity] };
4182
+ this.port.postMessage(e);
4183
+ }
4184
+ keyOff(channel, pitch, velocity) {
4185
+ const e = { type: "keyOff", data: [channel, pitch, velocity] };
4186
+ this.port.postMessage(e);
4187
+ }
4188
+ allNotesOff(hard) {
4189
+ const e = { type: "ctrlChange", data: [0, 123, 0] };
4190
+ this.port.postMessage(e);
4191
+ }
4192
+ getMeta() {
4193
+ const o = this.fJSONDsp;
4194
+ const e = this.fJSONEffect;
4195
+ const r = { ...o };
4196
+ if (e) {
4197
+ r.ui = [{
4198
+ type: "tgroup",
4199
+ label: "Sequencer",
4200
+ items: [
4201
+ { type: "vgroup", label: "Instrument", items: o.ui },
4202
+ { type: "vgroup", label: "Effect", items: e.ui }
4203
+ ]
4204
+ }];
4205
+ } else {
4206
+ r.ui = [{
4207
+ type: "tgroup",
4208
+ label: "Polyphonic",
4209
+ items: [
4210
+ { type: "vgroup", label: "Voices", items: o.ui }
4211
+ ]
4212
+ }];
4213
+ }
4214
+ return r;
4215
+ }
4216
+ getJSON() {
4217
+ return JSON.stringify(this.getMeta());
4218
+ }
4219
+ getUI() {
4220
+ return this.getMeta().ui;
4221
+ }
4222
+ };
4223
+
4224
+ // src/FaustScriptProcessorNode.ts
4225
+ var FaustScriptProcessorNode = class extends (globalThis.ScriptProcessorNode || null) {
4226
+ constructor() {
4227
+ super(...arguments);
4228
+ this.handleDeviceMotion = void 0;
4229
+ this.handleDeviceOrientation = void 0;
4230
+ }
4231
+ init(instance) {
4232
+ this.fDSPCode = instance;
4233
+ this.fInputs = new Array(this.fDSPCode.getNumInputs());
4234
+ this.fOutputs = new Array(this.fDSPCode.getNumOutputs());
4235
+ this.handleDeviceMotion = ({ accelerationIncludingGravity }) => {
4236
+ const isAndroid = /Android/i.test(navigator.userAgent);
4237
+ if (!accelerationIncludingGravity)
4238
+ return;
4239
+ const { x, y, z } = accelerationIncludingGravity;
4240
+ this.propagateAcc({ x, y, z }, isAndroid);
4241
+ };
4242
+ this.handleDeviceOrientation = ({ alpha, beta, gamma }) => {
4243
+ this.propagateGyr({ alpha, beta, gamma });
4244
+ };
4245
+ this.onaudioprocess = (e) => {
4246
+ for (let chan = 0; chan < this.fDSPCode.getNumInputs(); chan++) {
4247
+ this.fInputs[chan] = e.inputBuffer.getChannelData(chan);
4248
+ }
4249
+ for (let chan = 0; chan < this.fDSPCode.getNumOutputs(); chan++) {
4250
+ this.fOutputs[chan] = e.outputBuffer.getChannelData(chan);
4251
+ }
4252
+ return this.fDSPCode.compute(this.fInputs, this.fOutputs);
4253
+ };
4254
+ this.start();
4255
+ }
4256
+ // Public API
4257
+ /** Start accelerometer and gyroscope handlers */
4258
+ async startSensors() {
4259
+ if (this.hasAccInput) {
4260
+ if (window.DeviceMotionEvent) {
4261
+ window.addEventListener("devicemotion", this.handleDeviceMotion, true);
4262
+ } else {
4263
+ console.log("Cannot set the accelerometer handler.");
4264
+ }
4265
+ }
4266
+ if (this.hasGyrInput) {
4267
+ if (window.DeviceMotionEvent) {
4268
+ window.addEventListener("deviceorientation", this.handleDeviceOrientation, true);
4269
+ } else {
4270
+ console.log("Cannot set the gyroscope handler.");
4271
+ }
4272
+ }
4273
+ }
4274
+ /** Stop accelerometer and gyroscope handlers */
4275
+ stopSensors() {
4276
+ if (this.hasAccInput) {
4277
+ window.removeEventListener("devicemotion", this.handleDeviceMotion, true);
4278
+ }
4279
+ if (this.hasGyrInput) {
4280
+ window.removeEventListener("deviceorientation", this.handleDeviceOrientation, true);
4281
+ }
4282
+ }
4283
+ compute(input, output) {
4284
+ return this.fDSPCode.compute(input, output);
4285
+ }
4286
+ setOutputParamHandler(handler) {
4287
+ this.fDSPCode.setOutputParamHandler(handler);
4288
+ }
4289
+ getOutputParamHandler() {
4290
+ return this.fDSPCode.getOutputParamHandler();
4291
+ }
4292
+ setComputeHandler(handler) {
4293
+ this.fDSPCode.setComputeHandler(handler);
4294
+ }
4295
+ getComputeHandler() {
4296
+ return this.fDSPCode.getComputeHandler();
4297
+ }
4298
+ setPlotHandler(handler) {
4299
+ this.fDSPCode.setPlotHandler(handler);
4300
+ }
4301
+ getPlotHandler() {
4302
+ return this.fDSPCode.getPlotHandler();
4303
+ }
4304
+ getNumInputs() {
4305
+ return this.fDSPCode.getNumInputs();
4306
+ }
4307
+ getNumOutputs() {
4308
+ return this.fDSPCode.getNumOutputs();
4309
+ }
4310
+ metadata(handler) {
4311
+ }
4312
+ midiMessage(data) {
4313
+ this.fDSPCode.midiMessage(data);
4314
+ }
4315
+ ctrlChange(chan, ctrl, value) {
4316
+ this.fDSPCode.ctrlChange(chan, ctrl, value);
4317
+ }
4318
+ pitchWheel(chan, value) {
4319
+ this.fDSPCode.pitchWheel(chan, value);
4320
+ }
4321
+ keyOn(channel, pitch, velocity) {
4322
+ this.fDSPCode.keyOn(channel, pitch, velocity);
4323
+ }
4324
+ keyOff(channel, pitch, velocity) {
4325
+ this.fDSPCode.keyOff(channel, pitch, velocity);
4326
+ }
4327
+ setParamValue(path, value) {
4328
+ this.fDSPCode.setParamValue(path, value);
4329
+ }
4330
+ getParamValue(path) {
4331
+ return this.fDSPCode.getParamValue(path);
4332
+ }
4333
+ getParams() {
4334
+ return this.fDSPCode.getParams();
4335
+ }
4336
+ getMeta() {
4337
+ return this.fDSPCode.getMeta();
4338
+ }
4339
+ getJSON() {
4340
+ return this.fDSPCode.getJSON();
4341
+ }
4342
+ getDescriptors() {
4343
+ return this.fDSPCode.getDescriptors();
4344
+ }
4345
+ getUI() {
4346
+ return this.fDSPCode.getUI();
4347
+ }
4348
+ start() {
4349
+ this.fDSPCode.start();
4350
+ }
4351
+ stop() {
4352
+ this.fDSPCode.stop();
4353
+ }
4354
+ destroy() {
4355
+ this.fDSPCode.destroy();
4356
+ }
4357
+ get hasAccInput() {
4358
+ return this.fDSPCode.hasAccInput;
4359
+ }
4360
+ propagateAcc(accelerationIncludingGravity, invert = false) {
4361
+ this.fDSPCode.propagateAcc(accelerationIncludingGravity, invert);
4362
+ }
4363
+ get hasGyrInput() {
4364
+ return this.fDSPCode.hasGyrInput;
4365
+ }
4366
+ propagateGyr(event) {
4367
+ this.fDSPCode.propagateGyr(event);
4368
+ }
4369
+ };
4370
+ var FaustMonoScriptProcessorNode = class extends FaustScriptProcessorNode {
4371
+ };
4372
+ var FaustPolyScriptProcessorNode = class extends FaustScriptProcessorNode {
4373
+ keyOn(channel, pitch, velocity) {
4374
+ this.fDSPCode.keyOn(channel, pitch, velocity);
4375
+ }
4376
+ keyOff(channel, pitch, velocity) {
4377
+ this.fDSPCode.keyOff(channel, pitch, velocity);
4378
+ }
4379
+ allNotesOff(hard) {
4380
+ this.fDSPCode.allNotesOff(hard);
4381
+ }
4382
+ };
4383
+
4384
+ // src/FaustDspGenerator.ts
4385
+ var _FaustMonoDspGenerator = class _FaustMonoDspGenerator {
4386
+ constructor() {
4387
+ this.factory = null;
4388
+ }
4389
+ async compile(compiler, name, code, args) {
4390
+ this.factory = await compiler.createMonoDSPFactory(name, code, args);
4391
+ if (this.factory) {
4392
+ this.name = name;
4393
+ return this;
4394
+ } else {
4395
+ return null;
4396
+ }
4397
+ }
4398
+ addSoundfiles(soundfileMap) {
4399
+ if (!this.factory)
4400
+ throw new Error("Code is not compiled, please define the factory or call `await this.compile()` first.");
4401
+ for (const id in soundfileMap) {
4402
+ this.factory.soundfiles[id] = soundfileMap[id];
4403
+ }
4404
+ }
4405
+ getSoundfileList() {
4406
+ if (!this.factory)
4407
+ throw new Error("Code is not compiled, please define the factory or call `await this.compile()` first.");
4408
+ const meta = JSON.parse(this.factory.json);
4409
+ const map = SoundfileReader_default.findSoundfilesFromMeta(meta);
4410
+ return Object.keys(map);
4411
+ }
4412
+ async createNode(context, name = this.name, factory = this.factory, sp = false, bufferSize = 1024, processorName = (factory == null ? void 0 : factory.shaKey) || name, processorOptions = {}) {
4413
+ var _a, _b;
4414
+ if (!factory)
4415
+ throw new Error("Code is not compiled, please define the factory or call `await this.compile()` first.");
4416
+ const meta = JSON.parse(factory.json);
4417
+ const sampleSize = meta.compile_options.match("-double") ? 8 : 4;
4418
+ factory.soundfiles = await SoundfileReader_default.loadSoundfiles(meta, factory.soundfiles || {}, context);
4419
+ if (sp) {
4420
+ const instance = await FaustWasmInstantiator_default.createAsyncMonoDSPInstance(factory);
4421
+ const monoDsp = new FaustMonoWebAudioDsp(instance, context.sampleRate, sampleSize, bufferSize, factory.soundfiles);
4422
+ const sp2 = context.createScriptProcessor(bufferSize, monoDsp.getNumInputs(), monoDsp.getNumOutputs());
4423
+ Object.setPrototypeOf(sp2, FaustMonoScriptProcessorNode.prototype);
4424
+ sp2.init(monoDsp);
4425
+ return sp2;
4426
+ } else {
4427
+ if (!_FaustMonoDspGenerator.gWorkletProcessors.has(context))
4428
+ _FaustMonoDspGenerator.gWorkletProcessors.set(context, /* @__PURE__ */ new Set());
4429
+ if (!((_a = _FaustMonoDspGenerator.gWorkletProcessors.get(context)) == null ? void 0 : _a.has(processorName))) {
4430
+ try {
4431
+ const processorCode = `
4432
+ // DSP name and JSON string for DSP are generated
4433
+ const faustData = ${JSON.stringify({
4434
+ processorName,
4435
+ dspName: name,
4436
+ dspMeta: meta,
4437
+ poly: false
4438
+ })};
4439
+ // Implementation needed classes of functions
4440
+ var ${FaustDspInstance.name} = ${FaustDspInstance.toString()}
4441
+ var FaustDspInstance = ${FaustDspInstance.name};
4442
+ var ${FaustBaseWebAudioDsp.name} = ${FaustBaseWebAudioDsp.toString()}
4443
+ var FaustBaseWebAudioDsp = ${FaustBaseWebAudioDsp.name};
4444
+ var ${FaustMonoWebAudioDsp.name} = ${FaustMonoWebAudioDsp.toString()}
4445
+ var FaustMonoWebAudioDsp = ${FaustMonoWebAudioDsp.name};
4446
+ var ${FaustWasmInstantiator_default.name} = ${FaustWasmInstantiator_default.toString()}
4447
+ var FaustWasmInstantiator = ${FaustWasmInstantiator_default.name};
4448
+ var ${Soundfile.name} = ${Soundfile.toString()}
4449
+ var Soundfile = ${Soundfile.name};
4450
+ var ${WasmAllocator.name} = ${WasmAllocator.toString()}
4451
+ var WasmAllocator = ${WasmAllocator.name};
4452
+ var ${FaustSensors.name} = ${FaustSensors.toString()}
4453
+ var FaustSensors = ${FaustSensors.name};
4454
+ var ${FaustAudioWorkletCommunicator.name} = ${FaustAudioWorkletCommunicator.toString()}
4455
+ var FaustAudioWorkletCommunicator = ${FaustAudioWorkletCommunicator.name};
4456
+ var ${FaustAudioWorkletProcessorCommunicator.name} = ${FaustAudioWorkletProcessorCommunicator.toString()}
4457
+ var FaustAudioWorkletProcessorCommunicator = ${FaustAudioWorkletProcessorCommunicator.name};
4458
+ // Put them in dependencies
4459
+ const dependencies = {
4460
+ FaustBaseWebAudioDsp,
4461
+ FaustMonoWebAudioDsp,
4462
+ FaustWasmInstantiator,
4463
+ FaustAudioWorkletProcessorCommunicator
4464
+ };
4465
+ // Generate the actual AudioWorkletProcessor code
4466
+ (${FaustAudioWorkletProcessor_default.toString()})(dependencies, faustData);
4467
+ `;
4468
+ const url = URL.createObjectURL(new Blob([processorCode], { type: "text/javascript" }));
4469
+ await context.audioWorklet.addModule(url);
4470
+ (_b = _FaustMonoDspGenerator.gWorkletProcessors.get(context)) == null ? void 0 : _b.add(processorName);
4471
+ } catch (e) {
4472
+ throw e;
4473
+ }
4474
+ }
4475
+ const node = new FaustMonoAudioWorkletNode(context, { processorOptions: { name: processorName, factory, sampleSize, ...processorOptions } });
4476
+ return node;
4477
+ }
4478
+ }
4479
+ async createFFTNode(context, fftUtils, name = this.name, factory = this.factory, fftOptions = {}, processorName = (factory == null ? void 0 : factory.shaKey) ? `${factory.shaKey}_fft` : name, processorOptions = {}) {
4480
+ var _a, _b;
4481
+ if (!factory)
4482
+ throw new Error("Code is not compiled, please define the factory or call `await this.compile()` first.");
4483
+ const meta = JSON.parse(factory.json);
4484
+ const sampleSize = meta.compile_options.match("-double") ? 8 : 4;
4485
+ factory.soundfiles = await SoundfileReader_default.loadSoundfiles(meta, factory.soundfiles || {}, context);
4486
+ if (!_FaustMonoDspGenerator.gWorkletProcessors.has(context))
4487
+ _FaustMonoDspGenerator.gWorkletProcessors.set(context, /* @__PURE__ */ new Set());
4488
+ if (!((_a = _FaustMonoDspGenerator.gWorkletProcessors.get(context)) == null ? void 0 : _a.has(processorName))) {
4489
+ try {
4490
+ const processorCode = `
4491
+ // DSP name and JSON string for DSP are generated
4492
+ const faustData = ${JSON.stringify({
4493
+ processorName,
4494
+ dspName: name,
4495
+ dspMeta: meta,
4496
+ fftOptions
4497
+ })};
4498
+ // Implementation needed classes of functions
4499
+ var ${FaustDspInstance.name} = ${FaustDspInstance.toString()}
4500
+ var FaustDspInstance = ${FaustDspInstance.name};
4501
+ var ${FaustBaseWebAudioDsp.name} = ${FaustBaseWebAudioDsp.toString()}
4502
+ var FaustBaseWebAudioDsp = ${FaustBaseWebAudioDsp.name};
4503
+ var ${FaustMonoWebAudioDsp.name} = ${FaustMonoWebAudioDsp.toString()}
4504
+ var FaustMonoWebAudioDsp = ${FaustMonoWebAudioDsp.name};
4505
+ var ${FaustWasmInstantiator_default.name} = ${FaustWasmInstantiator_default.toString()}
4506
+ var FaustWasmInstantiator = ${FaustWasmInstantiator_default.name};
4507
+ var ${Soundfile.name} = ${Soundfile.toString()}
4508
+ var Soundfile = ${Soundfile.name};
4509
+ var ${WasmAllocator.name} = ${WasmAllocator.toString()}
4510
+ var WasmAllocator = ${WasmAllocator.name};
4511
+ var ${FaustSensors.name} = ${FaustSensors.toString()}
4512
+ var FaustSensors = ${FaustSensors.name};
4513
+ var ${FaustAudioWorkletCommunicator.name} = ${FaustAudioWorkletCommunicator.toString()}
4514
+ var FaustAudioWorkletCommunicator = ${FaustAudioWorkletCommunicator.name};
4515
+ var ${FaustAudioWorkletProcessorCommunicator.name} = ${FaustAudioWorkletProcessorCommunicator.toString()}
4516
+ var FaustAudioWorkletProcessorCommunicator = ${FaustAudioWorkletProcessorCommunicator.name};
4517
+ var FFTUtils = ${fftUtils.toString()}
4518
+ // Put them in dependencies
4519
+ const dependencies = {
4520
+ FaustBaseWebAudioDsp,
4521
+ FaustMonoWebAudioDsp,
4522
+ FaustWasmInstantiator,
4523
+ FaustAudioWorkletProcessorCommunicator,
4524
+ FFTUtils
4525
+ };
4526
+ // Generate the actual AudioWorkletProcessor code
4527
+ (${FaustFFTAudioWorkletProcessor_default.toString()})(dependencies, faustData);
4528
+ `;
4529
+ const url = URL.createObjectURL(new Blob([processorCode], { type: "text/javascript" }));
4530
+ await context.audioWorklet.addModule(url);
4531
+ (_b = _FaustMonoDspGenerator.gWorkletProcessors.get(context)) == null ? void 0 : _b.add(processorName);
4532
+ } catch (e) {
4533
+ throw e;
4534
+ }
4535
+ }
4536
+ const node = new FaustMonoAudioWorkletNode(context, { channelCount: Math.max(1, Math.ceil(meta.inputs / 3)), outputChannelCount: [Math.ceil(meta.outputs / 2)], processorOptions: { name: processorName, factory, sampleSize, ...processorOptions } });
4537
+ if (fftOptions.fftSize) {
4538
+ const param = node.parameters.get("fftSize");
4539
+ if (param)
4540
+ param.value = fftOptions.fftSize;
4541
+ }
4542
+ if (fftOptions.fftOverlap) {
4543
+ const param = node.parameters.get("fftOverlap");
4544
+ if (param)
4545
+ param.value = fftOptions.fftOverlap;
4546
+ }
4547
+ if (typeof fftOptions.defaultWindowFunction === "number") {
4548
+ const param = node.parameters.get("windowFunction");
4549
+ if (param)
4550
+ param.value = fftOptions.defaultWindowFunction + 1;
4551
+ }
4552
+ if (typeof fftOptions.noIFFT === "boolean") {
4553
+ const param = node.parameters.get("noIFFT");
4554
+ if (param)
4555
+ param.value = +fftOptions.noIFFT;
4556
+ }
4557
+ return node;
4558
+ }
4559
+ async createAudioWorkletProcessor(name = this.name, factory = this.factory, processorName = (factory == null ? void 0 : factory.shaKey) || name) {
4560
+ if (!factory)
4561
+ throw new Error("Code is not compiled, please define the factory or call `await this.compile()` first.");
4562
+ const meta = JSON.parse(factory.json);
4563
+ const dependencies = {
4564
+ FaustBaseWebAudioDsp,
4565
+ FaustMonoWebAudioDsp,
4566
+ FaustWasmInstantiator: FaustWasmInstantiator_default,
4567
+ FaustAudioWorkletProcessorCommunicator,
4568
+ FaustPolyWebAudioDsp: void 0,
4569
+ FaustWebAudioDspVoice: void 0
4570
+ };
4571
+ try {
4572
+ const faustData = {
4573
+ processorName,
4574
+ dspName: name,
4575
+ dspMeta: meta,
4576
+ poly: false
4577
+ };
4578
+ const Processor = FaustAudioWorkletProcessor_default(dependencies, faustData);
4579
+ return Processor;
4580
+ } catch (e) {
4581
+ throw e;
4582
+ }
4583
+ }
4584
+ async createOfflineProcessor(sampleRate, bufferSize, factory = this.factory, context) {
4585
+ if (!factory)
4586
+ throw new Error("Code is not compiled, please define the factory or call `await this.compile()` first.");
4587
+ const meta = JSON.parse(factory.json);
4588
+ const instance = await FaustWasmInstantiator_default.createAsyncMonoDSPInstance(factory);
4589
+ const sampleSize = meta.compile_options.match("-double") ? 8 : 4;
4590
+ if (context)
4591
+ factory.soundfiles = await SoundfileReader_default.loadSoundfiles(meta, factory.soundfiles || {}, context);
4592
+ const monoDsp = new FaustMonoWebAudioDsp(instance, sampleRate, sampleSize, bufferSize, factory.soundfiles);
4593
+ return new FaustMonoOfflineProcessor(monoDsp, bufferSize);
4594
+ }
4595
+ getMeta() {
4596
+ return JSON.parse(this.factory.json);
4597
+ }
4598
+ getJSON() {
4599
+ return JSON.stringify(this.getMeta());
4600
+ }
4601
+ getUI() {
4602
+ return this.getMeta().ui;
4603
+ }
4604
+ };
4605
+ // Set of all created WorkletProcessors, each of them has to be unique
4606
+ _FaustMonoDspGenerator.gWorkletProcessors = /* @__PURE__ */ new Map();
4607
+ var FaustMonoDspGenerator = _FaustMonoDspGenerator;
4608
+ var _FaustPolyDspGenerator = class _FaustPolyDspGenerator {
4609
+ constructor() {
4610
+ this.voiceFactory = null;
4611
+ this.effectFactory = null;
4612
+ }
4613
+ async compile(compiler, name, dspCodeAux, args, effectCodeAux = `dsp_code = environment{
4614
+ ${dspCodeAux}
4615
+ };
4616
+ process = dsp_code.effect;`) {
4617
+ try {
4618
+ this.effectFactory = await compiler.createPolyDSPFactory(name, effectCodeAux, args);
4619
+ if (this.effectFactory) {
4620
+ const effectJSON = JSON.parse(this.effectFactory.json);
4621
+ const dspCode = `// Voice output is forced to 2, when DSP is stereo or effect has 2 ins or 2 outs,
4622
+ // so that the effect can process the 2 channels of the voice
4623
+ adaptOut(1,1,1) = _;
4624
+ adaptOut(1,1,2) = _ <: _,0; // The left channel only is kept
4625
+ adaptOut(1,2,1) = _ <: _,_;
4626
+ adaptOut(1,2,2) = _ <: _,_;
4627
+ adaptOut(2,1,1) = _,_;
4628
+ adaptOut(2,1,2) = _,_;
4629
+ adaptOut(2,2,1) = _,_;
4630
+ adaptOut(2,2,2) = _,_;
4631
+ adaptor(F) = adaptOut(outputs(F),${effectJSON.inputs},${effectJSON.outputs});
4632
+ dsp_code = environment{
4633
+ ${dspCodeAux}
4634
+ };
4635
+ process = dsp_code.process : adaptor(dsp_code.process);
4636
+ `;
4637
+ const effectCode = `// Inputs
4638
+ adaptIn(1,1,1) = _;
4639
+ adaptIn(1,1,2) = _,_ :> _;
4640
+ adaptIn(1,2,1) = _,_;
4641
+ adaptIn(1,2,2) = _,_;
4642
+ adaptIn(2,1,1) = _,_ :> _;
4643
+ adaptIn(2,1,2) = _,_ :> _;
4644
+ adaptIn(2,2,1) = _,_;
4645
+ adaptIn(2,2,2) = _,_;
4646
+ // Outputs
4647
+ adaptOut(1,1) = _ <: _,0; // The left channel only is kept
4648
+ adaptOut(1,2) = _,_;
4649
+ adaptOut(2,1) = _ <: _,0; // The left channel only is kept
4650
+ adaptOut(2,2) = _,_;
4651
+ adaptorIns(F) = adaptIn(outputs(F),${effectJSON.inputs},${effectJSON.outputs});
4652
+ adaptorOuts = adaptOut(${effectJSON.inputs},${effectJSON.outputs});
4653
+ dsp_code = environment{
4654
+ ${dspCodeAux}
4655
+ };
4656
+ process = adaptorIns(dsp_code.process) : dsp_code.effect : adaptorOuts;
4657
+ `;
4658
+ this.voiceFactory = await compiler.createPolyDSPFactory(name, dspCode, args);
4659
+ try {
4660
+ this.effectFactory = await compiler.createPolyDSPFactory(name, effectCode, args + " -inpl");
4661
+ } catch (e) {
4662
+ console.warn(e);
4663
+ }
4664
+ }
4665
+ } catch (e) {
4666
+ console.warn(e);
4667
+ this.voiceFactory = await compiler.createPolyDSPFactory(name, dspCodeAux, args);
4668
+ }
4669
+ if (this.voiceFactory) {
4670
+ this.name = name;
4671
+ const voiceMeta = JSON.parse(this.voiceFactory.json);
4672
+ const isDouble = voiceMeta.compile_options.match("-double");
4673
+ const { mixerBuffer, mixerModule } = await compiler.getAsyncInternalMixerModule(!!isDouble);
4674
+ this.mixerBuffer = mixerBuffer;
4675
+ this.mixerModule = mixerModule;
4676
+ return this;
4677
+ } else {
4678
+ return null;
4679
+ }
4680
+ }
4681
+ addSoundfiles(soundfileMap) {
4682
+ if (!this.voiceFactory)
4683
+ throw new Error("Code is not compiled, please define the factory or call `await this.compile()` first.");
4684
+ for (const id in soundfileMap) {
4685
+ this.voiceFactory.soundfiles[id] = soundfileMap[id];
4686
+ }
4687
+ }
4688
+ getSoundfileList() {
4689
+ if (!this.voiceFactory)
4690
+ throw new Error("Code is not compiled, please define the factory or call `await this.compile()` first.");
4691
+ const meta = JSON.parse(this.voiceFactory.json);
4692
+ const map = SoundfileReader_default.findSoundfilesFromMeta(meta);
4693
+ if (!this.effectFactory)
4694
+ return Object.keys(map);
4695
+ const effectMeta = JSON.parse(this.effectFactory.json);
4696
+ const effectMap = SoundfileReader_default.findSoundfilesFromMeta(effectMeta);
4697
+ return Object.keys({ ...effectMap, ...map });
4698
+ }
4699
+ async createNode(context, voices, name = this.name, voiceFactory = this.voiceFactory, mixerModule = this.mixerModule, effectFactory = this.effectFactory, sp = false, bufferSize = 1024, processorName = ((voiceFactory == null ? void 0 : voiceFactory.shaKey) || "") + ((effectFactory == null ? void 0 : effectFactory.shaKey) || "") || `${name}_poly`, processorOptions = {}) {
4700
+ var _a, _b;
4701
+ if (!voiceFactory)
4702
+ throw new Error("Code is not compiled, please define the factory or call `await this.compile()` first.");
4703
+ const voiceMeta = JSON.parse(voiceFactory.json);
4704
+ const effectMeta = effectFactory ? JSON.parse(effectFactory.json) : void 0;
4705
+ const sampleSize = voiceMeta.compile_options.match("-double") ? 8 : 4;
4706
+ voiceFactory.soundfiles = await SoundfileReader_default.loadSoundfiles(voiceMeta, voiceFactory.soundfiles || {}, context);
4707
+ if (effectFactory)
4708
+ effectFactory.soundfiles = await SoundfileReader_default.loadSoundfiles(effectMeta, effectFactory.soundfiles || {}, context);
4709
+ if (sp) {
4710
+ const instance = await FaustWasmInstantiator_default.createAsyncPolyDSPInstance(voiceFactory, mixerModule, voices, effectFactory || void 0);
4711
+ const soundfiles = { ...effectFactory == null ? void 0 : effectFactory.soundfiles, ...voiceFactory.soundfiles };
4712
+ const polyDsp = new FaustPolyWebAudioDsp(instance, context.sampleRate, sampleSize, bufferSize, soundfiles);
4713
+ const sp2 = context.createScriptProcessor(bufferSize, polyDsp.getNumInputs(), polyDsp.getNumOutputs());
4714
+ Object.setPrototypeOf(sp2, FaustPolyScriptProcessorNode.prototype);
4715
+ sp2.init(polyDsp);
4716
+ return sp2;
4717
+ } else {
4718
+ if (!_FaustPolyDspGenerator.gWorkletProcessors.has(context))
4719
+ _FaustPolyDspGenerator.gWorkletProcessors.set(context, /* @__PURE__ */ new Set());
4720
+ if (!((_a = _FaustPolyDspGenerator.gWorkletProcessors.get(context)) == null ? void 0 : _a.has(processorName))) {
4721
+ try {
4722
+ const processorCode = `
4723
+ // DSP name and JSON string for DSP are generated
4724
+ const faustData = ${JSON.stringify({
4725
+ processorName,
4726
+ dspName: name,
4727
+ dspMeta: voiceMeta,
4728
+ poly: true,
4729
+ effectMeta
4730
+ })};
4731
+ // Implementation needed classes of functions
4732
+ var ${FaustDspInstance.name} = ${FaustDspInstance.toString()}
4733
+ var FaustDspInstance = ${FaustDspInstance.name};
4734
+ var ${FaustBaseWebAudioDsp.name} = ${FaustBaseWebAudioDsp.toString()}
4735
+ var FaustBaseWebAudioDsp = ${FaustBaseWebAudioDsp.name};
4736
+ var ${FaustPolyWebAudioDsp.name} = ${FaustPolyWebAudioDsp.toString()}
4737
+ var FaustPolyWebAudioDsp = ${FaustPolyWebAudioDsp.name};
4738
+ var ${FaustWebAudioDspVoice.name} = ${FaustWebAudioDspVoice.toString()}
4739
+ var FaustWebAudioDspVoice = ${FaustWebAudioDspVoice.name};
4740
+ var ${FaustWasmInstantiator_default.name} = ${FaustWasmInstantiator_default.toString()}
4741
+ var FaustWasmInstantiator = ${FaustWasmInstantiator_default.name};
4742
+ var ${Soundfile.name} = ${Soundfile.toString()}
4743
+ var Soundfile = ${Soundfile.name};
4744
+ var ${WasmAllocator.name} = ${WasmAllocator.toString()}
4745
+ var WasmAllocator = ${WasmAllocator.name};
4746
+ var ${FaustSensors.name} = ${FaustSensors.toString()}
4747
+ var FaustSensors = ${FaustSensors.name};
4748
+ var ${FaustAudioWorkletCommunicator.name} = ${FaustAudioWorkletCommunicator.toString()}
4749
+ var FaustAudioWorkletCommunicator = ${FaustAudioWorkletCommunicator.name};
4750
+ var ${FaustAudioWorkletProcessorCommunicator.name} = ${FaustAudioWorkletProcessorCommunicator.toString()}
4751
+ var FaustAudioWorkletProcessorCommunicator = ${FaustAudioWorkletProcessorCommunicator.name};
4752
+ // Put them in dependencies
4753
+ const dependencies = {
4754
+ FaustBaseWebAudioDsp,
4755
+ FaustPolyWebAudioDsp,
4756
+ FaustWasmInstantiator,
4757
+ FaustAudioWorkletProcessorCommunicator
4758
+ };
4759
+ // Generate the actual AudioWorkletProcessor code
4760
+ (${FaustAudioWorkletProcessor_default.toString()})(dependencies, faustData);
4761
+ `;
4762
+ const url = URL.createObjectURL(new Blob([processorCode], { type: "text/javascript" }));
4763
+ await context.audioWorklet.addModule(url);
4764
+ (_b = _FaustPolyDspGenerator.gWorkletProcessors.get(context)) == null ? void 0 : _b.add(processorName);
4765
+ } catch (e) {
4766
+ throw e;
4767
+ }
4768
+ }
4769
+ const node = new FaustPolyAudioWorkletNode(context, { processorOptions: { name: processorName, voiceFactory, mixerModule, voices, sampleSize, effectFactory: effectFactory || void 0, ...processorOptions } });
4770
+ return node;
4771
+ }
4772
+ }
4773
+ async createAudioWorkletProcessor(name = this.name, voiceFactory = this.voiceFactory, effectFactory = this.effectFactory, processorName = ((voiceFactory == null ? void 0 : voiceFactory.shaKey) || "") + ((effectFactory == null ? void 0 : effectFactory.shaKey) || "") || `${name}_poly`) {
4774
+ if (!voiceFactory)
4775
+ throw new Error("Code is not compiled, please define the factory or call `await this.compile()` first.");
4776
+ const voiceMeta = JSON.parse(voiceFactory.json);
4777
+ const effectMeta = effectFactory ? JSON.parse(effectFactory.json) : void 0;
4778
+ const sampleSize = voiceMeta.compile_options.match("-double") ? 8 : 4;
4779
+ try {
4780
+ const dependencies = {
4781
+ FaustBaseWebAudioDsp,
4782
+ FaustMonoWebAudioDsp: void 0,
4783
+ FaustWasmInstantiator: FaustWasmInstantiator_default,
4784
+ FaustPolyWebAudioDsp,
4785
+ FaustWebAudioDspVoice,
4786
+ FaustAudioWorkletProcessorCommunicator
4787
+ };
4788
+ const faustData = {
4789
+ processorName,
4790
+ dspName: name,
4791
+ dspMeta: voiceMeta,
4792
+ poly: true,
4793
+ effectMeta
4794
+ };
4795
+ const Processor = FaustAudioWorkletProcessor_default(dependencies, faustData);
4796
+ return Processor;
4797
+ } catch (e) {
4798
+ throw e;
4799
+ }
4800
+ }
4801
+ async createOfflineProcessor(sampleRate, bufferSize, voices, voiceFactory = this.voiceFactory, mixerModule = this.mixerModule, effectFactory = this.effectFactory, context) {
4802
+ if (!voiceFactory)
4803
+ throw new Error("Code is not compiled, please define the factory or call `await this.compile()` first.");
4804
+ const voiceMeta = JSON.parse(voiceFactory.json);
4805
+ const effectMeta = effectFactory ? JSON.parse(effectFactory.json) : void 0;
4806
+ const instance = await FaustWasmInstantiator_default.createAsyncPolyDSPInstance(voiceFactory, mixerModule, voices, effectFactory || void 0);
4807
+ const sampleSize = voiceMeta.compile_options.match("-double") ? 8 : 4;
4808
+ if (context) {
4809
+ voiceFactory.soundfiles = await SoundfileReader_default.loadSoundfiles(voiceMeta, voiceFactory.soundfiles || {}, context);
4810
+ if (effectFactory)
4811
+ effectFactory.soundfiles = await SoundfileReader_default.loadSoundfiles(effectMeta, effectFactory.soundfiles || {}, context);
4812
+ }
4813
+ const soundfiles = { ...effectFactory == null ? void 0 : effectFactory.soundfiles, ...voiceFactory.soundfiles };
4814
+ const polyDsp = new FaustPolyWebAudioDsp(instance, sampleRate, sampleSize, bufferSize, soundfiles);
4815
+ return new FaustPolyOfflineProcessor(polyDsp, bufferSize);
4816
+ }
4817
+ getMeta() {
4818
+ const o = this.voiceFactory ? JSON.parse(this.voiceFactory.json) : null;
4819
+ const e = this.effectFactory ? JSON.parse(this.effectFactory.json) : null;
4820
+ const r = { ...o };
4821
+ if (e) {
4822
+ r.ui = [{
4823
+ type: "tgroup",
4824
+ label: "Sequencer",
4825
+ items: [
4826
+ { type: "vgroup", label: "Instrument", items: o.ui },
4827
+ { type: "vgroup", label: "Effect", items: e.ui }
4828
+ ]
4829
+ }];
4830
+ } else {
4831
+ r.ui = [{
4832
+ type: "tgroup",
4833
+ label: "Polyphonic",
4834
+ items: [
4835
+ { type: "vgroup", label: "Voices", items: o.ui }
4836
+ ]
4837
+ }];
4838
+ }
4839
+ return r;
4840
+ }
4841
+ getJSON() {
4842
+ return JSON.stringify(this.getMeta());
4843
+ }
4844
+ getUI() {
4845
+ return this.getMeta().ui;
4846
+ }
4847
+ };
4848
+ // Set of all created WorkletProcessors, each of them has to be unique
4849
+ _FaustPolyDspGenerator.gWorkletProcessors = /* @__PURE__ */ new Map();
4850
+ var FaustPolyDspGenerator = _FaustPolyDspGenerator;
4851
+ export {
4852
+ FaustAudioWorkletNode,
4853
+ FaustBaseWebAudioDsp,
4854
+ FaustCmajor_default as FaustCmajor,
4855
+ FaustCompiler_default as FaustCompiler,
4856
+ FaustDspInstance,
4857
+ FaustMonoAudioWorkletNode,
4858
+ FaustMonoDspGenerator,
4859
+ FaustMonoOfflineProcessor,
4860
+ FaustMonoScriptProcessorNode,
4861
+ FaustMonoWebAudioDsp,
4862
+ FaustOfflineProcessor_default as FaustOfflineProcessor,
4863
+ FaustPolyAudioWorkletNode,
4864
+ FaustPolyDspGenerator,
4865
+ FaustPolyOfflineProcessor,
4866
+ FaustPolyScriptProcessorNode,
4867
+ FaustPolyWebAudioDsp,
4868
+ FaustScriptProcessorNode,
4869
+ FaustSvgDiagrams_default as FaustSvgDiagrams,
4870
+ FaustWasmInstantiator_default as FaustWasmInstantiator,
4871
+ FaustWebAudioDspVoice,
4872
+ LibFaust_default as LibFaust,
4873
+ Soundfile,
4874
+ SoundfileReader_default as SoundfileReader,
4875
+ WasmAllocator,
4876
+ WavDecoder_default as WavDecoder,
4877
+ WavEncoder_default as WavEncoder,
4878
+ ab2str,
4879
+ FaustAudioWorkletProcessor_default as getFaustAudioWorkletProcessor,
4880
+ FaustFFTAudioWorkletProcessor_default as getFaustFFTAudioWorkletProcessor,
4881
+ instantiateFaustModuleFromFile_default as instantiateFaustModuleFromFile,
4882
+ str2ab
4883
+ };
4884
+ //# sourceMappingURL=index.js.map