@grame/faustwasm 0.0.25

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 (111) hide show
  1. package/README.md +181 -0
  2. package/assets/standalone/faust-ui/index.css +414 -0
  3. package/assets/standalone/faust-ui/index.css.map +1 -0
  4. package/assets/standalone/faust-ui/index.d.ts +1 -0
  5. package/assets/standalone/faust-ui/index.js +3478 -0
  6. package/assets/standalone/faust-ui/index.js.map +1 -0
  7. package/assets/standalone/faustwasm/index.d.ts +1252 -0
  8. package/assets/standalone/faustwasm/index.js +3772 -0
  9. package/assets/standalone/faustwasm/index.js.map +7 -0
  10. package/assets/standalone/index.html +73 -0
  11. package/assets/standalone/index.js +198 -0
  12. package/assets/standalone/types.d.ts +9 -0
  13. package/dist/cjs/index.d.ts +1252 -0
  14. package/dist/cjs/index.js +3752 -0
  15. package/dist/cjs/index.js.map +7 -0
  16. package/dist/cjs-bundle/index.d.ts +1259 -0
  17. package/dist/cjs-bundle/index.js +11507 -0
  18. package/dist/cjs-bundle/index.js.map +7 -0
  19. package/dist/esm/index.d.ts +1252 -0
  20. package/dist/esm/index.js +3772 -0
  21. package/dist/esm/index.js.map +7 -0
  22. package/dist/esm-bundle/index.d.ts +1259 -0
  23. package/dist/esm-bundle/index.js +11495 -0
  24. package/dist/esm-bundle/index.js.map +7 -0
  25. package/fileutils.js +40 -0
  26. package/libfaust-wasm/libfaust-wasm.d.cts +3 -0
  27. package/libfaust-wasm/libfaust-wasm.d.ts +3 -0
  28. package/libfaust-wasm/libfaust-wasm.data +0 -0
  29. package/libfaust-wasm/libfaust-wasm.data.d.ts +2 -0
  30. package/libfaust-wasm/libfaust-wasm.js +21 -0
  31. package/libfaust-wasm/libfaust-wasm.wasm +0 -0
  32. package/libfaust-wasm/libfaust-wasm.wasm.d.ts +2 -0
  33. package/library.md +91 -0
  34. package/package.json +43 -0
  35. package/postbuild-bundled.js +11 -0
  36. package/postbuild.js +63 -0
  37. package/prebuild-bundled.js +11 -0
  38. package/rsrc/overview.png +0 -0
  39. package/rsrc/overview.xlsx +0 -0
  40. package/scripts/faust2sndfile.js +43 -0
  41. package/scripts/faust2svg.js +17 -0
  42. package/scripts/faust2wasm.js +29 -0
  43. package/src/FaustAudioWorkletNode.ts +264 -0
  44. package/src/FaustAudioWorkletProcessor.ts +273 -0
  45. package/src/FaustCompiler.ts +252 -0
  46. package/src/FaustDspGenerator.ts +498 -0
  47. package/src/FaustDspInstance.ts +141 -0
  48. package/src/FaustFFTAudioWorkletProcessor.ts +554 -0
  49. package/src/FaustOfflineProcessor.ts +141 -0
  50. package/src/FaustScriptProcessorNode.ts +80 -0
  51. package/src/FaustSvgDiagrams.ts +37 -0
  52. package/src/FaustWasmInstantiator.ts +202 -0
  53. package/src/FaustWebAudioDsp.ts +1060 -0
  54. package/src/LibFaust.ts +57 -0
  55. package/src/WavDecoder.ts +207 -0
  56. package/src/WavEncoder.ts +204 -0
  57. package/src/copyWebStandaloneAssets.d.ts +3 -0
  58. package/src/copyWebStandaloneAssets.js +20 -0
  59. package/src/exports-bundle.ts +5 -0
  60. package/src/exports.ts +24 -0
  61. package/src/faust2svgFiles.d.ts +3 -0
  62. package/src/faust2svgFiles.js +43 -0
  63. package/src/faust2wasmFiles.d.ts +5 -0
  64. package/src/faust2wasmFiles.js +93 -0
  65. package/src/faust2wavFiles.d.ts +3 -0
  66. package/src/faust2wavFiles.js +58 -0
  67. package/src/index-bundle-iife.ts +7 -0
  68. package/src/index-bundle.ts +5 -0
  69. package/src/index.ts +5 -0
  70. package/src/instantiateFaustModule.ts +32 -0
  71. package/src/instantiateFaustModuleFromFile.ts +57 -0
  72. package/src/types.ts +234 -0
  73. package/test/clarinet.dsp +1 -0
  74. package/test/faustlive-wasm/faust-ui/index.css +414 -0
  75. package/test/faustlive-wasm/faust-ui/index.css.map +1 -0
  76. package/test/faustlive-wasm/faust-ui/index.d.ts +1 -0
  77. package/test/faustlive-wasm/faust-ui/index.js +3478 -0
  78. package/test/faustlive-wasm/faust-ui/index.js.map +1 -0
  79. package/test/faustlive-wasm/faustwasm/index.d.ts +1252 -0
  80. package/test/faustlive-wasm/faustwasm/index.js +3772 -0
  81. package/test/faustlive-wasm/faustwasm/index.js.map +7 -0
  82. package/test/faustlive-wasm/index.css +97 -0
  83. package/test/faustlive-wasm/index.html +130 -0
  84. package/test/faustlive-wasm/index.js +638 -0
  85. package/test/guitar.dsp +1 -0
  86. package/test/guitar1.dsp +2 -0
  87. package/test/libfaust-in-worklet/index.html +13 -0
  88. package/test/libfaust-in-worklet/index.js +40 -0
  89. package/test/mono.dsp +8 -0
  90. package/test/node/test.js +17 -0
  91. package/test/noise.dsp +3 -0
  92. package/test/organ.dsp +5 -0
  93. package/test/organ1.dsp +6 -0
  94. package/test/osc.dsp +4 -0
  95. package/test/osc2.dsp +5 -0
  96. package/test/osc3.dsp +4 -0
  97. package/test/p-dj.dsp +4 -0
  98. package/test/poly.dsp +13 -0
  99. package/test/rev.dsp +2 -0
  100. package/test/t1.dsp +1 -0
  101. package/test/web/fft.html +87 -0
  102. package/test/web/fft1.html +88 -0
  103. package/test/web/fft2.html +114 -0
  104. package/test/web/fftw.js +1907 -0
  105. package/test/web/index.html +12 -0
  106. package/test/web/index.js +235 -0
  107. package/test/web/kissfft.js +904 -0
  108. package/test/web/mono.html +46 -0
  109. package/test/web/poly-key.html +62 -0
  110. package/test/web/poly.html +59 -0
  111. package/tsconfig.json +22 -0
@@ -0,0 +1,638 @@
1
+ //@ts-check
2
+ /** @type {typeof AudioContext} */
3
+ const AudioContextConstructor = globalThis.AudioContext || globalThis.webkitAudioContext;
4
+ const audio_context = new AudioContextConstructor({ latencyHint: 0.00001 });
5
+ audio_context.destination.channelInterpretation = "discrete";
6
+
7
+ const isWasm = typeof WebAssembly !== "undefined";
8
+ const workletAvailable = typeof AudioWorklet !== "undefined";
9
+
10
+ /** @type {HTMLDivElement} */
11
+ const faustUIRoot = document.getElementById("faust-ui");
12
+
13
+ /** @type {import("./faustwasm").FaustCompiler} */
14
+ let faust_compiler = null;
15
+ /** @type {import("./faustwasm").FaustMonoDspGenerator} */
16
+ let faust_mono_factory = null;
17
+ /** @type {import("./faustwasm").FaustPolyDspGenerator} */
18
+ let faust_poly_factory = null;
19
+ let isPoly = false;
20
+ let buffer_size = 1024;
21
+ let audio_input = null;
22
+ let factory = null;
23
+ /** @type {import("./faustwasm").FaustAudioWorkletNode<any> | import("./faustwasm").FaustScriptProcessorNode<any>} */
24
+ let DSP = null;
25
+ /** @type {string} */
26
+ let dsp_code = null;
27
+ /** @type {typeof import("./faust-ui/index").FaustUI} */
28
+ let FaustUI;
29
+ /** @type {import("./faust-ui/index").FaustUI} */
30
+ let faustUI;
31
+ let poly_flag = "OFF";
32
+ let ftz_flag = "2";
33
+ let sample_format = "float";
34
+ let poly_nvoices = 16;
35
+ let rendering_mode = "ScriptProcessor";
36
+ /**
37
+ * @param {string} path
38
+ * @param {number} value
39
+ */
40
+ let output_handler = (path, value) => faustUI.paramChangeByDSP(path, value);
41
+
42
+ /**
43
+ * @param {HTMLSelectElement} bs_item
44
+ */
45
+ const setBufferSize = (bs_item) => {
46
+ buffer_size = parseInt(bs_item.options[bs_item.selectedIndex].value);
47
+ if (buffer_size === 128 && rendering_mode === "ScriptProcessor") {
48
+ console.log("buffer_size cannot be set to 128 in ScriptProcessor mode !");
49
+ buffer_size = 256;
50
+ restoreMenu("selectedBuffer", buffer_size.toString());
51
+ }
52
+ compileDSP();
53
+ }
54
+
55
+ /**
56
+ * @param {HTMLSelectElement} poly_item
57
+ */
58
+ const setPoly = (poly_item) => {
59
+ poly_flag = poly_item.options[poly_item.selectedIndex].value;
60
+ compileDSP();
61
+ }
62
+
63
+ /**
64
+ * @param {HTMLSelectElement} voices_item
65
+ */
66
+ const setPolyVoices = (voices_item) => {
67
+ poly_nvoices = parseInt(voices_item.options[voices_item.selectedIndex].value);
68
+ compileDSP();
69
+ }
70
+
71
+ /**
72
+ * @param {HTMLSelectElement} rendering_item
73
+ */
74
+ const setRenderingMode = (rendering_item) => {
75
+ rendering_mode = rendering_item.options[rendering_item.selectedIndex].value;
76
+ /** @type {HTMLSelectElement} */
77
+ const selectedBuffer = document.getElementById("selectedBuffer");
78
+ if (rendering_mode === "AudioWorklet") {
79
+ buffer_size = 128;
80
+ restoreMenu("selectedBuffer", buffer_size.toString());
81
+ selectedBuffer.disabled = true;
82
+ } else {
83
+ buffer_size = 1024;
84
+ restoreMenu("selectedBuffer", buffer_size.toString());
85
+ selectedBuffer.disabled = false;
86
+ }
87
+ compileDSP();
88
+ }
89
+
90
+ /**
91
+ * @param {HTMLSelectElement} ftz_item
92
+ */
93
+ const setFTZ = (ftz_item) => {
94
+ ftz_flag = ftz_item.options[ftz_item.selectedIndex].value;
95
+ compileDSP();
96
+ }
97
+
98
+ /**
99
+ * @param {HTMLSelectElement} sample_item
100
+ */
101
+ const setSampleFormat = (sample_item) => {
102
+ sample_format = sample_item.options[sample_item.selectedIndex].value;
103
+ compileDSP();
104
+ }
105
+
106
+ // MIDI input handling
107
+
108
+ /**
109
+ * @param {number} channel
110
+ * @param {number} pitch
111
+ * @param {number} velocity
112
+ */
113
+ const keyOn = (channel, pitch, velocity) => {
114
+ if (DSP && isPoly) {
115
+ DSP.keyOn(channel, pitch, velocity);
116
+ }
117
+ }
118
+
119
+ /**
120
+ * @param {number} channel
121
+ * @param {number} pitch
122
+ * @param {number} velocity
123
+ */
124
+ const keyOff = (channel, pitch, velocity) => {
125
+ if (DSP && isPoly) {
126
+ DSP.keyOff(channel, pitch, velocity);
127
+ }
128
+ }
129
+
130
+ /**
131
+ * @param {number} channel
132
+ * @param {number} bend
133
+ */
134
+ const pitchWheel = (channel, bend) => {
135
+ if (DSP) {
136
+ DSP.pitchWheel(channel, bend);
137
+ }
138
+ }
139
+
140
+ /**
141
+ * @param {number} channel
142
+ * @param {number} ctrl
143
+ * @param {number} value
144
+ */
145
+ const ctrlChange = (channel, ctrl, value) => {
146
+ if (DSP) {
147
+ DSP.ctrlChange(channel, ctrl, value);
148
+ }
149
+ }
150
+
151
+ /**
152
+ * @param {MessageEvent} ev
153
+ */
154
+ const midiMessageReceived = (ev) => {
155
+ var cmd = ev.data[0] >> 4;
156
+ var channel = ev.data[0] & 0xf;
157
+ var data1 = ev.data[1];
158
+ var data2 = ev.data[2];
159
+
160
+ if (channel === 9) {
161
+ return;
162
+ } else if (cmd === 8 || ((cmd === 9) && (data2 === 0))) {
163
+ keyOff(channel, data1, data2);
164
+ } else if (cmd === 9) {
165
+ keyOn(channel, data1, data2);
166
+ } else if (cmd === 11) {
167
+ ctrlChange(channel, data1, data2);
168
+ } else if (cmd === 14) {
169
+ pitchWheel(channel, (data2 * 128.0 + data1));
170
+ }
171
+
172
+ /*
173
+ // Direct message
174
+ if (DSP && isPoly) {
175
+ DSP.midiMessage(ev.data);
176
+ }
177
+ */
178
+ }
179
+ /**
180
+ * @param {Error} error
181
+ */
182
+ const onerrorcallback = (error) => {
183
+ console.log(error);
184
+ }
185
+
186
+ const onsuccesscallbackStandard = (access) => {
187
+ access.onstatechange = function (e) {
188
+ if (e.port.type === "input") {
189
+ if (e.port.state === "connected") {
190
+ console.log(e.port.name + " is connected");
191
+ e.port.onmidimessage = midiMessageReceived;
192
+ } else if (e.port.state === "disconnected") {
193
+ console.log(e.port.name + " is disconnected");
194
+ e.port.onmidimessage = null;
195
+ }
196
+ }
197
+ }
198
+
199
+ for (const input of access.inputs.values()) {
200
+ input.onmidimessage = midiMessageReceived;
201
+ console.log(input.name + " is connected");
202
+ }
203
+ }
204
+
205
+ const activateMIDIInput = () => {
206
+ console.log("activateMIDIInput");
207
+ if (typeof (navigator.requestMIDIAccess) !== "undefined") {
208
+ navigator.requestMIDIAccess().then(onsuccesscallbackStandard, onerrorcallback);
209
+ } else {
210
+ alert("MIDI input cannot be activated, either your browser still does't have it, or you need to explicitly activate it.");
211
+ }
212
+ }
213
+
214
+ /** Audio input handling */
215
+ const activateAudioInput = () => {
216
+ console.log("activateAudioInput");
217
+ if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
218
+ navigator.mediaDevices.getUserMedia({ audio: { echoCancellation: false } })
219
+ .then(getDevice)
220
+ .catch((e) => {
221
+ alert('Error getting audio input');
222
+ console.log(e);
223
+ audio_input = null;
224
+ });
225
+ } else {
226
+ alert('Audio input API not available');
227
+ }
228
+ }
229
+
230
+ /**
231
+ * @param {MediaStream} device
232
+ */
233
+ const getDevice = (device) => {
234
+ // Create an AudioNode from the stream.
235
+ audio_input = audio_context.createMediaStreamSource(device);
236
+
237
+ // Connect it to the destination.
238
+ audio_input.connect(DSP);
239
+ }
240
+
241
+ const setLocalStorage = (state) => {
242
+ console.log(state);
243
+ setStorageItemValue('FaustLibTester', 'FaustLocalStorage', ((state) ? "on" : "off"));
244
+ }
245
+
246
+ /**
247
+ * Save/Load functions using local storage
248
+ *
249
+ * @param {string} id
250
+ * @param {string} value
251
+ */
252
+ const restoreMenu = (id, value) => {
253
+ /** @type {HTMLSelectElement} */
254
+ const menu = document.getElementById(id);
255
+ for (let i = 0; i < menu.length; i++) {
256
+ // Weak comparison here
257
+ if (menu.options[i].value == value) {
258
+ menu.selectedIndex = i;
259
+ break;
260
+ }
261
+ }
262
+ }
263
+
264
+ /**
265
+ * set item from local storage 'item_key' key
266
+ *
267
+ * @param {string} item_key
268
+ * @param {string} key
269
+ * @returns
270
+ */
271
+ const getStorageItemValue = (item_key, key) => {
272
+ if (localStorage.getItem(item_key)) {
273
+ var item_value = JSON.parse(localStorage.getItem(item_key));
274
+ var item_index = item_value.findIndex((obj => obj[0] === key));
275
+ return (item_index >= 0) ? item_value[item_index][1] : null;
276
+ } else {
277
+ return null;
278
+ }
279
+ }
280
+
281
+ /**
282
+ * get [key, value] in local storage item_key key
283
+ * @param {string} item_key
284
+ * @param {string} key
285
+ * @param {string} value
286
+ */
287
+ const setStorageItemValue = (item_key, key, value) => {
288
+ var item_value;
289
+ if (localStorage.getItem(item_key)) {
290
+ item_value = JSON.parse(localStorage.getItem(item_key));
291
+ } else {
292
+ item_value = [];
293
+ }
294
+
295
+ // Possibly update an existing 'key'
296
+ var item_index = item_value.findIndex((obj => obj[0] === key));
297
+ if (item_index >= 0) {
298
+ item_value[item_index][1] = value;
299
+ // Otherwise push a new [key, value]
300
+ } else {
301
+ item_value.push([key, value]);
302
+ }
303
+
304
+ localStorage.setItem(item_key, JSON.stringify(item_value));
305
+ }
306
+
307
+ const saveDSPState = () => {
308
+ var params = DSP.getParams();
309
+ for (var i = 0; i < params.length; i++) {
310
+ setStorageItemValue('DSP', params[i], DSP.getParamValue(params[i]).toString());
311
+ }
312
+ }
313
+
314
+ const loadDSPState = () => {
315
+ var params = DSP.getParams();
316
+ for (var i = 0; i < params.length; i++) {
317
+ var value = getStorageItemValue('DSP', params[i]);
318
+ if (value) {
319
+ // Restore DSP state
320
+ DSP.setParamValue(params[i], Number(value));
321
+ // Restore GUI state
322
+ output_handler(params[i], Number(value));
323
+ }
324
+ }
325
+ }
326
+
327
+ const savePageState = () => {
328
+ if (getStorageItemValue('FaustLibTester', 'FaustLocalStorage') === "on") {
329
+ setStorageItemValue('FaustLibTester', 'buffer_size', buffer_size.toString());
330
+ setStorageItemValue('FaustLibTester', 'poly_flag', poly_flag);
331
+ setStorageItemValue('FaustLibTester', 'ftz_flag', ftz_flag);
332
+ setStorageItemValue('FaustLibTester', 'sample_format', sample_format);
333
+ setStorageItemValue('FaustLibTester', 'poly_nvoices', poly_nvoices.toString());
334
+ setStorageItemValue('FaustLibTester', 'rendering_mode', rendering_mode);
335
+ }
336
+ }
337
+
338
+ const loadPageState = () => {
339
+ if (getStorageItemValue('FaustLibTester', 'FaustLocalStorage') === "on") {
340
+ buffer_size = (getStorageItemValue('FaustLibTester', 'buffer_size') ? getStorageItemValue('FaustLibTester', 'buffer_size') : 256);
341
+ poly_flag = (getStorageItemValue('FaustLibTester', 'poly_flag') ? getStorageItemValue('FaustLibTester', 'poly_flag') : "OFF");
342
+ poly_nvoices = (getStorageItemValue('FaustLibTester', 'poly_nvoices') ? getStorageItemValue('FaustLibTester', 'poly_nvoices') : 16);
343
+ ftz_flag = (getStorageItemValue('FaustLibTester', 'ftz_flag') ? getStorageItemValue('FaustLibTester', 'ftz_flag') : 2);
344
+ sample_format = (getStorageItemValue('FaustLibTester', 'sample_format') ? getStorageItemValue('FaustLibTester', 'sample_format') : "float");
345
+ rendering_mode = (getStorageItemValue('FaustLibTester', 'rendering_mode') ? getStorageItemValue('FaustLibTester', 'rendering_mode') : "ScriptProcessor");
346
+
347
+ // Restore menus
348
+ restoreMenu("selectedBuffer", buffer_size.toString());
349
+ restoreMenu("selectedPoly", poly_flag);
350
+ restoreMenu("polyVoices", poly_nvoices.toString());
351
+ restoreMenu("selectedFTZ", ftz_flag);
352
+ restoreMenu("selectedSampleFormat", sample_format);
353
+ restoreMenu("selectedRenderingMode", rendering_mode);
354
+
355
+ if (rendering_mode === "AudioWorklet") {
356
+ document.getElementById("selectedBuffer").disabled = true;
357
+ }
358
+ }
359
+ }
360
+
361
+ /**
362
+ * @param {DragEvent | InputEvent} e
363
+ */
364
+ const fileDragHover = (e) => {
365
+ e.stopPropagation();
366
+ e.preventDefault();
367
+ e.target.className = (e.type === "dragover" ? "hover" : "");
368
+ }
369
+
370
+ /**
371
+ * @param {InputEvent} e
372
+ */
373
+ const fileSelectHandler = (e) => {
374
+ fileDragHover(e);
375
+ /** @type {FileList} */
376
+ const files = e.target.files || e.dataTransfer.files;
377
+ uploadFile(files[0]);
378
+ }
379
+
380
+ /**
381
+ * @param {DragEvent} e
382
+ */
383
+ const uploadOn = (e) => {
384
+ return new Promise((callback, reject) => {
385
+ if (!isWasm) {
386
+ alert("WebAssembly is not supported in this browser !");
387
+ reject("WebAssembly is not supported in this browser !");
388
+ }
389
+
390
+ // CASE 1 : THE DROPPED OBJECT IS A URL TO SOME FAUST CODE
391
+ if (e.dataTransfer.getData('URL') && e.dataTransfer.getData('URL').split(':').shift() != "file") {
392
+ const url = e.dataTransfer.getData('URL');
393
+ let filename = url.toString().split('/').pop();
394
+ filename = filename.toString().split('.').shift();
395
+ const xmlhttp = new XMLHttpRequest();
396
+
397
+ xmlhttp.onreadystatechange = () => {
398
+ if (xmlhttp.readyState === 4 && xmlhttp.status === 200) {
399
+ dsp_code = xmlhttp.responseText;
400
+ callback(dsp_code);
401
+ }
402
+ }
403
+
404
+ try {
405
+ xmlhttp.open("GET", url, false);
406
+ // Avoid error "mal formé" on firefox
407
+ xmlhttp.overrideMimeType('text/html');
408
+ xmlhttp.send();
409
+ } catch (err) {
410
+ alert(err);
411
+ reject(err);
412
+ }
413
+
414
+ } else if (e.dataTransfer.getData('URL').split(':').shift() != "file") {
415
+ dsp_code = e.dataTransfer.getData('text');
416
+
417
+ // CASE 2 : THE DROPPED OBJECT IS SOME FAUST CODE
418
+ if (dsp_code) {
419
+ callback(dsp_code);
420
+ }
421
+ // CASE 3 : THE DROPPED OBJECT IS A FILE CONTAINING SOME FAUST CODE
422
+ else {
423
+ /** @type {FileList} */
424
+ const files = e.target.files || e.dataTransfer.files;
425
+ const file = files[0];
426
+
427
+ if (location.host.indexOf("sitepointstatic") >= 0) return;
428
+
429
+ const request = new XMLHttpRequest();
430
+ if (request.upload) {
431
+
432
+ const reader = new FileReader();
433
+ const ext = file.name.toString().split('.').pop();
434
+ const filename = file.name.toString().split('.').shift();
435
+ let type;
436
+
437
+ if (ext === "dsp") {
438
+ type = "dsp";
439
+ reader.readAsText(file);
440
+ } else if (ext === "json") {
441
+ type = "json";
442
+ reader.readAsText(file);
443
+ }
444
+
445
+ reader.onloadend = (e) => {
446
+ dsp_code = reader.result;
447
+ callback(dsp_code);
448
+ };
449
+ }
450
+ }
451
+ }
452
+ // CASE 4 : ANY OTHER STRANGE THING
453
+ else {
454
+ window.alert("This object is not Faust code...");
455
+ reject(new Error("This object is not Faust code..."));
456
+ }
457
+ });
458
+ }
459
+
460
+ const checkPolyphonicDSP = (json) => {
461
+ if (!(((json.indexOf("/freq") !== -1) || (json.indexOf("/key") !== -1))
462
+ && (json.indexOf("/gate") !== -1)
463
+ && ((json.indexOf("/gain") !== -1) || (json.indexOf("/vel") !== -1) || (json.indexOf("/velocity") !== -1)))) {
464
+ alert("Faust DSP code is not Polyphonic, it will probably not work correctly in this mode...")
465
+ }
466
+ }
467
+
468
+ const deleteDSP = () => {
469
+ if (DSP) {
470
+ if (audio_input) {
471
+ audio_input.disconnect(DSP);
472
+ }
473
+ DSP.disconnect(audio_context.destination);
474
+ DSP.destroy();
475
+ faustUIRoot.innerHTML = "";
476
+ DSP = null;
477
+ faustUI = null;
478
+ }
479
+ }
480
+
481
+ const activateMonoDSP = (dsp) => {
482
+ if (!dsp) {
483
+ alert(faust_compiler.getErrorMessage());
484
+ return;
485
+ }
486
+
487
+ DSP = dsp;
488
+ if (DSP.getNumInputs() > 0) {
489
+ activateAudioInput();
490
+ } else {
491
+ audio_input = null;
492
+ }
493
+
494
+ // Setup UI
495
+ faustUI = new FaustUI({ ui: DSP.getUI(), root: faustUIRoot });
496
+ faustUI.paramChangeByUI = (path, value) => DSP.setParamValue(path, value);
497
+ DSP.setOutputParamHandler(output_handler);
498
+ console.log(DSP.getNumInputs());
499
+ console.log(DSP.getNumOutputs());
500
+ //DSP.metadata({ declare: function(key, value) { console.log("key = " + key + " value = " + value); }});
501
+ DSP.connect(audio_context.destination);
502
+ // DSP has to be explicitly started
503
+ DSP.start();
504
+ loadDSPState();
505
+ }
506
+
507
+ const activatePolyDSP = (dsp) => {
508
+ if (!dsp) {
509
+ alert(faust_compiler.getErrorMessage());
510
+ return;
511
+ }
512
+ checkPolyphonicDSP(dsp.getJSON());
513
+ DSP = dsp;
514
+
515
+ if (DSP.getNumInputs() > 0) {
516
+ activateAudioInput();
517
+ } else {
518
+ audio_input = null;
519
+ }
520
+
521
+ // Setup UI
522
+ faustUI = new FaustUI({ ui: DSP.getUI(), root: faustUIRoot });
523
+ faustUI.paramChangeByUI = (path, value) => DSP.setParamValue(path, value);
524
+ DSP.setOutputParamHandler(output_handler);
525
+ console.log(DSP.getNumInputs());
526
+ console.log(DSP.getNumOutputs());
527
+ //DSP.metadata({ declare: function(key, value) { console.log("key = " + key + " value = " + value); }});
528
+ DSP.connect(audio_context.destination);
529
+ // DSP has to be explicitly started
530
+ DSP.start();
531
+ loadDSPState();
532
+ }
533
+
534
+ const compileDSP = async () => {
535
+ if (!dsp_code) {
536
+ return;
537
+ }
538
+
539
+ deleteDSP();
540
+
541
+ // Prepare argv list
542
+ var argv = "-ftz " + ftz_flag.toString() + " -" + sample_format;
543
+ console.log(argv);
544
+
545
+ if (poly_flag === "ON") {
546
+ isPoly = true;
547
+ console.log("Poly DSP");
548
+ await faust_poly_factory.compile(faust_compiler, "FaustDSP", dsp_code, argv);
549
+ DSP = await faust_poly_factory.createNode(audio_context, poly_nvoices, undefined, undefined, undefined, undefined, (rendering_mode === "ScriptProcessor"), buffer_size);
550
+ activatePolyDSP(DSP);
551
+ } else {
552
+ isPoly = false;
553
+ console.log("Mono DSP");
554
+ await faust_mono_factory.compile(faust_compiler, "FaustDSP", dsp_code, argv);
555
+ DSP = await faust_mono_factory.createNode(audio_context, undefined, undefined, (rendering_mode === "ScriptProcessor"), buffer_size);
556
+ activateMonoDSP(DSP);
557
+ }
558
+ }
559
+
560
+ /**
561
+ * @param {DragEvent} e
562
+ */
563
+ const uploadFile = async (e) => {
564
+ fileDragHover(e);
565
+ await uploadOn(e);
566
+ compileDSP()
567
+ }
568
+
569
+ const initPage = () => {
570
+ // Restore 'save' checkbox state
571
+ document.getElementById("localstorage").checked = (getStorageItemValue('FaustLibTester', 'FaustLocalStorage') === "on");
572
+
573
+ // Load page state
574
+ loadPageState();
575
+ }
576
+
577
+ const init = async () => {
578
+ const {
579
+ instantiateFaustModuleFromFile,
580
+ FaustCompiler,
581
+ FaustMonoDspGenerator,
582
+ FaustPolyDspGenerator,
583
+ LibFaust
584
+ } = await import("./faustwasm/index.js");
585
+ FaustUI = (await import("./faust-ui/index.js")).FaustUI;
586
+ // Init Faust compiler and node factory
587
+ const module = await instantiateFaustModuleFromFile(new URL("../../libfaust-wasm/libfaust-wasm.js", location.href).href);
588
+ // const module = await instantiateFaustModule();
589
+ const libFaust = new LibFaust(module);
590
+ faust_compiler = new FaustCompiler(libFaust);
591
+ faust_mono_factory = new FaustMonoDspGenerator();
592
+ faust_poly_factory = new FaustPolyDspGenerator();
593
+
594
+ // Check AudioWorklet support
595
+ if (!workletAvailable) {
596
+ document.getElementById("selectedRenderingMode").disabled = true;
597
+ alert("AudioWorklet is not supported, ScriptProcessor model only will be available");
598
+ }
599
+
600
+ activateMIDIInput();
601
+
602
+ const filedrag1 = document.getElementById("filedrag");
603
+ filedrag1.addEventListener("dragover", fileDragHover, false);
604
+ filedrag1.addEventListener("dragleave", fileDragHover, false);
605
+ filedrag1.addEventListener("drop", uploadFile, false);
606
+ filedrag1.textContent = "Drop a Faust .dsp file or URL here (compiled using libfaust version " + faust_compiler.version() + ")";
607
+ }
608
+
609
+ // Init page
610
+ initPage();
611
+
612
+ // Timer to save page and DSP state to local storage
613
+ setInterval(() => { savePageState(); if (DSP) { saveDSPState(); } }, 1000);
614
+
615
+ // Init Faust part
616
+ init();
617
+
618
+ // To activate audio on iOS
619
+ window.addEventListener('touchstart', function () {
620
+
621
+ // create empty buffer
622
+ var buffer = audio_context.createBuffer(1, 1, 22050);
623
+ var source = audio_context.createBufferSource();
624
+ source.buffer = buffer;
625
+
626
+ // connect to output (your speakers)
627
+ source.connect(audio_context.destination);
628
+
629
+ // play the file
630
+ source.start();
631
+
632
+ }, false);
633
+
634
+ // On desktop
635
+ window.addEventListener("mousedown", () => {
636
+ if (audio_context.state !== "suspended") return;
637
+ audio_context.resume().then(() => console.log("Audio resumed"))
638
+ });
@@ -0,0 +1 @@
1
+ import("stdfaust.lib"); process = pm.guitar_ui_MIDI <: _,_;
@@ -0,0 +1,2 @@
1
+ import("stdfaust.lib"); process = pm.guitar_ui_MIDI <: _,_;
2
+ effect = *(hslider("Left", 0.1, 0, 1, 0.01)), *(hslider("Right", 0.1, 0, 1, 0.01));
@@ -0,0 +1,13 @@
1
+ <html lang="en">
2
+ <head>
3
+ <meta charset="UTF-8" />
4
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
5
+ <title>Faust Wasm Generator Demo</title>
6
+ </head>
7
+
8
+ <body>
9
+ <p id="log">...<br /></p>
10
+
11
+ <script src="../../dist/cjs-bundle/index.js"></script>
12
+ <script type="module" src="index.js"></script>
13
+ </body>
@@ -0,0 +1,40 @@
1
+ //@ts-check
2
+ const div = document.getElementById("log");
3
+ const log = (/** @type {string} */str) => div.innerHTML += str.replace("\n", "<br />") + "<br />";
4
+ const options = "-ftz 0";
5
+
6
+ (async () => {
7
+ const ctx = new AudioContext();
8
+ globalThis.ctx = ctx;
9
+ globalThis.faustModule = await faustwasm.instantiateFaustModule();
10
+ const post = async () => {
11
+ const {
12
+ instantiateFaustModule,
13
+ LibFaust,
14
+ getFaustAudioWorkletProcessor,
15
+ WavEncoder,
16
+ FaustWasmInstantiator,
17
+ FaustMonoDspGenerator,
18
+ FaustPolyDspGenerator,
19
+ FaustMonoWebAudioDsp,
20
+ FaustOfflineProcessor,
21
+ FaustCompiler,
22
+ FaustSvgDiagrams
23
+ } = faustwasm;
24
+ const faustModule = await instantiateFaustModule();
25
+ const code = `import("stdfaust.lib");
26
+ process = os.osc(440);`;
27
+ const gen = new FaustMonoDspGenerator();
28
+ const libFaust = new LibFaust(faustModule);
29
+ const compiler = new FaustCompiler(libFaust);
30
+ console.log(compiler.version());
31
+ await gen.compile(compiler, 'dsp', code, "-ftz 0");
32
+
33
+ console.log(await gen.createAudioWorkletProcessor());
34
+ const processor = await gen.createOfflineProcessor(48000, 128);
35
+ console.log(processor);
36
+ console.log(processor.render([], 48000));
37
+ };
38
+ await ctx.audioWorklet.addModule("../../dist/cjs-bundle/index.js");
39
+ await ctx.audioWorklet.addModule(URL.createObjectURL(new Blob([`(${post.toString()})()`], { type: "application/javascript" })));
40
+ })();
package/test/mono.dsp ADDED
@@ -0,0 +1,8 @@
1
+ declare name "Oscillator440";
2
+ declare version "1.0";
3
+ declare author "Fr0stbyteR";
4
+ declare license "BSD";
5
+ declare copyright "shren2021";
6
+ declare description "This is an oscillator";
7
+ import("stdfaust.lib");
8
+ process = os.osc(440);