@grame/faustwasm 0.12.2 → 0.13.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. package/.prettierrc +5 -0
  2. package/README.md +21 -3
  3. package/assets/standalone/faustwasm/index.d.ts +38 -16
  4. package/assets/standalone/faustwasm/index.js +1593 -404
  5. package/assets/standalone/faustwasm/index.js.map +2 -2
  6. package/dist/cjs/index.d.ts +38 -16
  7. package/dist/cjs/index.js +1592 -404
  8. package/dist/cjs/index.js.map +2 -2
  9. package/dist/cjs-bundle/index.d.ts +38 -16
  10. package/dist/cjs-bundle/index.js +1595 -406
  11. package/dist/cjs-bundle/index.js.map +2 -2
  12. package/dist/esm/index.d.ts +38 -16
  13. package/dist/esm/index.js +1593 -404
  14. package/dist/esm/index.js.map +2 -2
  15. package/dist/esm-bundle/index.d.ts +38 -16
  16. package/dist/esm-bundle/index.js +1595 -406
  17. package/dist/esm-bundle/index.js.map +2 -2
  18. package/eslint.config.js +11 -0
  19. package/package.json +57 -51
  20. package/sound.cpp +163 -0
  21. package/sound.dsp +4 -0
  22. package/sound.json +1 -0
  23. package/sound.wasm +0 -0
  24. package/src/FaustAudioWorkletCommunicator.ts +150 -143
  25. package/src/FaustAudioWorkletNode.ts +173 -75
  26. package/src/FaustAudioWorkletProcessor.ts +218 -90
  27. package/src/FaustCmajor.ts +9 -3
  28. package/src/FaustCompiler.ts +112 -35
  29. package/src/FaustDspGenerator.ts +589 -117
  30. package/src/FaustDspInstance.ts +58 -24
  31. package/src/FaustFFTAudioWorkletProcessor.ts +822 -612
  32. package/src/FaustOfflineProcessor.ts +187 -56
  33. package/src/FaustScriptProcessorNode.ts +156 -49
  34. package/src/FaustSensors.ts +426 -96
  35. package/src/FaustSvgDiagrams.ts +18 -5
  36. package/src/FaustWasmInstantiator.ts +224 -70
  37. package/src/FaustWebAudioDsp.ts +1060 -349
  38. package/src/LibFaust.ts +13 -4
  39. package/src/SoundfileReader.ts +175 -131
  40. package/src/WavDecoder.ts +42 -20
  41. package/src/WavEncoder.ts +35 -21
  42. package/src/copyWebStandaloneAssets.d.ts +20 -5
  43. package/src/copyWebStandaloneAssets.js +203 -75
  44. package/src/exports-bundle.ts +5 -5
  45. package/src/exports.ts +24 -24
  46. package/src/faust2CmajorFiles.d.ts +7 -3
  47. package/src/faust2cmajorFiles.js +10 -8
  48. package/src/faust2svgFiles.d.ts +7 -3
  49. package/src/faust2svgFiles.js +9 -7
  50. package/src/faust2wasmFiles.d.ts +10 -5
  51. package/src/faust2wasmFiles.js +34 -17
  52. package/src/faust2wavFiles.d.ts +12 -3
  53. package/src/faust2wavFiles.js +25 -12
  54. package/src/index-bundle-iife.ts +2 -2
  55. package/src/index-bundle.ts +1 -1
  56. package/src/index.ts +1 -1
  57. package/src/instantiateFaustModule.ts +43 -36
  58. package/src/instantiateFaustModuleFromFile.ts +30 -14
  59. package/src/types.ts +101 -25
  60. package/test/faustlive-wasm/faustwasm/index.d.ts +38 -16
  61. package/test/faustlive-wasm/faustwasm/index.js +1593 -404
  62. package/test/faustlive-wasm/faustwasm/index.js.map +2 -2
  63. package/test/web/create-faust-node.html +53 -0
  64. package/test/web/create-faust-node.js +181 -0
  65. package/test/organ/create-node.js +0 -252
  66. package/test/organ/dsp-meta.json +0 -131
  67. package/test/organ/dsp-module.wasm +0 -0
  68. package/test/organ/faust-pwa.js +0 -344
  69. package/test/organ/faust-ui/index.css +0 -442
  70. package/test/organ/faust-ui/index.css.map +0 -1
  71. package/test/organ/faust-ui/index.d.ts +0 -1
  72. package/test/organ/faust-ui/index.js +0 -3756
  73. package/test/organ/faust-ui/index.js.map +0 -1
  74. package/test/organ/faustwasm/index.d.ts +0 -1705
  75. package/test/organ/faustwasm/index.js +0 -4773
  76. package/test/organ/faustwasm/index.js.map +0 -7
  77. package/test/organ/icon.png +0 -0
  78. package/test/organ/index.html +0 -76
  79. package/test/organ/index.js +0 -69
  80. package/test/organ/manifest.json +0 -17
  81. package/test/organ/service-worker.js +0 -165
@@ -1,8 +1,9 @@
1
- import { Sha256 } from "@aws-crypto/sha256-js";
2
- import type { ILibFaust } from "./LibFaust";
3
- import type { FaustDspFactory, IntVector } from "./types";
1
+ import { Sha256 } from '@aws-crypto/sha256-js';
2
+ import type { ILibFaust } from './LibFaust';
3
+ import type { FaustDspFactory, IntVector } from './types';
4
4
 
5
- export const ab2str = (buf: Uint8Array) => String.fromCharCode.apply(null, Array.from(buf));
5
+ export const ab2str = (buf: Uint8Array) =>
6
+ String.fromCharCode.apply(null, Array.from(buf));
6
7
 
7
8
  export const str2ab = (str: string) => {
8
9
  const buf = new ArrayBuffer(str.length);
@@ -16,7 +17,9 @@ const sha256 = async (str: string) => {
16
17
  const sha256 = new Sha256();
17
18
  sha256.update(str);
18
19
  const hashArray = Array.from(await sha256.digest());
19
- const hashHex = hashArray.map(b => b.toString(16).padStart(2, "0")).join("");
20
+ const hashHex = hashArray
21
+ .map((b) => b.toString(16).padStart(2, '0'))
22
+ .join('');
20
23
  return hashHex;
21
24
  };
22
25
 
@@ -34,7 +37,7 @@ export interface IFaustCompiler {
34
37
  getErrorMessage(): string;
35
38
 
36
39
  /**
37
- * Create a wasm factory from Faust code i.e. wasm compiled code, to be used to create monophonic instances.
40
+ * Create a wasm factory from Faust code i.e. wasm compiled code, to be used to create monophonic instances.
38
41
  * This function is running asynchronously.
39
42
  *
40
43
  * @param name - an arbitrary name for the Faust factory
@@ -42,10 +45,14 @@ export interface IFaustCompiler {
42
45
  * @param args - the compiler options
43
46
  * @returns returns the wasm factory
44
47
  */
45
- createMonoDSPFactory(name: string, code: string, args: string): Promise<FaustDspFactory | null>;
48
+ createMonoDSPFactory(
49
+ name: string,
50
+ code: string,
51
+ args: string
52
+ ): Promise<FaustDspFactory | null>;
46
53
 
47
54
  /**
48
- * Create a wasm factory from Faust code i.e. wasm compiled code, to be used to create polyphonic instances.
55
+ * Create a wasm factory from Faust code i.e. wasm compiled code, to be used to create polyphonic instances.
49
56
  * This function is running asynchronously.
50
57
  *
51
58
  * @param name - an arbitrary name for the Faust factory
@@ -53,7 +60,11 @@ export interface IFaustCompiler {
53
60
  * @param args - the compiler options
54
61
  * @returns returns the wasm factory
55
62
  */
56
- createPolyDSPFactory(name: string, code: string, args: string): Promise<FaustDspFactory | null>;
63
+ createPolyDSPFactory(
64
+ name: string,
65
+ code: string,
66
+ args: string
67
+ ): Promise<FaustDspFactory | null>;
57
68
 
58
69
  /**
59
70
  * Delete a dsp factory.
@@ -88,14 +99,22 @@ export interface IFaustCompiler {
88
99
 
89
100
  fs(): typeof FS;
90
101
 
91
- getAsyncInternalMixerModule(isDouble?: boolean): Promise<{ mixerBuffer: Uint8Array; mixerModule: WebAssembly.Module }>;
92
- getSyncInternalMixerModule(isDouble?: boolean): { mixerBuffer: Uint8Array; mixerModule: WebAssembly.Module };
102
+ getAsyncInternalMixerModule(
103
+ isDouble?: boolean
104
+ ): Promise<{ mixerBuffer: Uint8Array; mixerModule: WebAssembly.Module }>;
105
+ getSyncInternalMixerModule(isDouble?: boolean): {
106
+ mixerBuffer: Uint8Array;
107
+ mixerModule: WebAssembly.Module;
108
+ };
93
109
  }
94
110
 
95
111
  class FaustCompiler implements IFaustCompiler {
96
112
  private fLibFaust: ILibFaust;
97
113
  private fErrorMessage: string;
98
- private static gFactories: Map<string, FaustDspFactory> = new Map<string, FaustDspFactory>();
114
+ private static gFactories: Map<string, FaustDspFactory> = new Map<
115
+ string,
116
+ FaustDspFactory
117
+ >();
99
118
  private mixer32Buffer!: Uint8Array;
100
119
  private mixer64Buffer!: Uint8Array;
101
120
  private mixer32Module!: WebAssembly.Module;
@@ -105,10 +124,17 @@ class FaustCompiler implements IFaustCompiler {
105
124
  * Get a stringified DSP factories table
106
125
  */
107
126
  static serializeDSPFactories() {
108
- const table: Record<string, { code: string, json: any; poly: boolean }> = {};
127
+ const table: Record<
128
+ string,
129
+ { code: string; json: any; poly: boolean }
130
+ > = {};
109
131
  this.gFactories.forEach((factory, shaKey) => {
110
132
  const { code, json, poly } = factory;
111
- table[shaKey] = { code: btoa(ab2str(code)), json: JSON.parse(json), poly };
133
+ table[shaKey] = {
134
+ code: btoa(ab2str(code)),
135
+ json: JSON.parse(json),
136
+ poly
137
+ };
112
138
  });
113
139
  return table;
114
140
  }
@@ -121,13 +147,27 @@ class FaustCompiler implements IFaustCompiler {
121
147
  /**
122
148
  * Import a DSP factories table
123
149
  */
124
- static deserializeDSPFactories(table: Record<string, { code: string, json: any; poly: boolean }>) {
150
+ static deserializeDSPFactories(
151
+ table: Record<string, { code: string; json: any; poly: boolean }>
152
+ ) {
125
153
  const awaited: Promise<Map<string, FaustDspFactory>>[] = [];
126
154
  for (const shaKey in table) {
127
155
  const factory = table[shaKey];
128
156
  const { code, json, poly } = factory;
129
- const ab = str2ab(atob(code))
130
- awaited.push(WebAssembly.compile(ab).then(module => this.gFactories.set(shaKey, { shaKey, cfactory: 0, code: ab, module, json: JSON.stringify(json), poly, soundfiles: {} })));
157
+ const ab = str2ab(atob(code));
158
+ awaited.push(
159
+ WebAssembly.compile(ab).then((module) =>
160
+ this.gFactories.set(shaKey, {
161
+ shaKey,
162
+ cfactory: 0,
163
+ code: ab,
164
+ module,
165
+ json: JSON.stringify(json),
166
+ poly,
167
+ soundfiles: {}
168
+ })
169
+ )
170
+ );
131
171
  }
132
172
  return Promise.all(awaited);
133
173
  }
@@ -135,12 +175,15 @@ class FaustCompiler implements IFaustCompiler {
135
175
  * Import a stringified DSP factories table
136
176
  */
137
177
  static importDSPFactories(tableStr: string) {
138
- const table: Record<string, { code: string, json: any; poly: boolean }> = JSON.parse(tableStr);
178
+ const table: Record<
179
+ string,
180
+ { code: string; json: any; poly: boolean }
181
+ > = JSON.parse(tableStr);
139
182
  return this.deserializeDSPFactories(table);
140
183
  }
141
184
  constructor(libFaust: ILibFaust) {
142
185
  this.fLibFaust = libFaust;
143
- this.fErrorMessage = "";
186
+ this.fErrorMessage = '';
144
187
  }
145
188
  private intVec2intArray(vec: IntVector) {
146
189
  const size = vec.size();
@@ -150,24 +193,44 @@ class FaustCompiler implements IFaustCompiler {
150
193
  }
151
194
  return ui8Code;
152
195
  }
153
- private async createDSPFactory(name: string, code: string, args: string, poly: boolean) {
196
+ private async createDSPFactory(
197
+ name: string,
198
+ code: string,
199
+ args: string,
200
+ poly: boolean
201
+ ) {
154
202
  // Cleanup the cache
155
203
  if (FaustCompiler.gFactories.size > 10) {
156
204
  FaustCompiler.gFactories.clear();
157
205
  }
158
206
 
159
207
  // If code is already compiled, return the cached factory
160
- let shaKey = await sha256(name + code + args + (poly ? "poly" : "mono"));
208
+ const shaKey = await sha256(
209
+ name + code + args + (poly ? 'poly' : 'mono')
210
+ );
161
211
  if (FaustCompiler.gFactories.has(shaKey)) {
162
212
  return FaustCompiler.gFactories.get(shaKey) || null;
163
213
  } else {
164
214
  try {
165
215
  // Can possibly raise a C++ exception catched by the second catch()
166
- const faustDspWasm = this.fLibFaust.createDSPFactory(name, code, args, !poly);
216
+ const faustDspWasm = this.fLibFaust.createDSPFactory(
217
+ name,
218
+ code,
219
+ args,
220
+ !poly
221
+ );
167
222
  const ui8Code = this.intVec2intArray(faustDspWasm.data);
168
223
  faustDspWasm.data.delete();
169
224
  const module = await WebAssembly.compile(ui8Code);
170
- const factory: FaustDspFactory = { shaKey, cfactory: faustDspWasm.cfactory, code: ui8Code, module, json: faustDspWasm.json, poly, soundfiles: {} };
225
+ const factory: FaustDspFactory = {
226
+ shaKey,
227
+ cfactory: faustDspWasm.cfactory,
228
+ code: ui8Code,
229
+ module,
230
+ json: faustDspWasm.json,
231
+ poly,
232
+ soundfiles: {}
233
+ };
171
234
  // Factory C++ side can be deallocated immediately
172
235
  this.deleteDSPFactory(factory);
173
236
  // Keep the compiled factory in the cache
@@ -199,7 +262,7 @@ class FaustCompiler implements IFaustCompiler {
199
262
  }
200
263
  expandDSP(code: string, args: string) {
201
264
  try {
202
- return this.fLibFaust.expandDSP("FaustDSP", code, args);
265
+ return this.fLibFaust.expandDSP('FaustDSP', code, args);
203
266
  } catch (e) {
204
267
  this.fErrorMessage = this.fLibFaust.getErrorAfterException();
205
268
  // console.error(`=> exception raised while running expandDSP: ${this.fErrorMessage}`);
@@ -224,23 +287,37 @@ class FaustCompiler implements IFaustCompiler {
224
287
  return this.fLibFaust.fs();
225
288
  }
226
289
  async getAsyncInternalMixerModule(isDouble = false) {
227
- const bufferKey = isDouble ? "mixer64Buffer" : "mixer32Buffer";
228
- const moduleKey = isDouble ? "mixer64Module" : "mixer32Module";
229
- if (this[moduleKey]) return { mixerBuffer: this[bufferKey], mixerModule: this[moduleKey] };
230
- const path = isDouble ? "/usr/rsrc/mixer64.wasm" : "/usr/rsrc/mixer32.wasm";
231
- const mixerBuffer = this.fs().readFile(path, { encoding: "binary" });
290
+ const bufferKey = isDouble ? 'mixer64Buffer' : 'mixer32Buffer';
291
+ const moduleKey = isDouble ? 'mixer64Module' : 'mixer32Module';
292
+ if (this[moduleKey])
293
+ return {
294
+ mixerBuffer: this[bufferKey],
295
+ mixerModule: this[moduleKey]
296
+ };
297
+ const path = isDouble
298
+ ? '/usr/rsrc/mixer64.wasm'
299
+ : '/usr/rsrc/mixer32.wasm';
300
+ const mixerBuffer = this.fs().readFile(path, { encoding: 'binary' });
232
301
  this[bufferKey] = mixerBuffer;
233
302
  // Compile mixer
234
- const mixerModule = await WebAssembly.compile(new Uint8Array(mixerBuffer));
303
+ const mixerModule = await WebAssembly.compile(
304
+ new Uint8Array(mixerBuffer)
305
+ );
235
306
  this[moduleKey] = mixerModule;
236
307
  return { mixerBuffer, mixerModule };
237
308
  }
238
309
  getSyncInternalMixerModule(isDouble = false) {
239
- const bufferKey = isDouble ? "mixer64Buffer" : "mixer32Buffer";
240
- const moduleKey = isDouble ? "mixer64Module" : "mixer32Module";
241
- if (this[moduleKey]) return { mixerBuffer: this[bufferKey], mixerModule: this[moduleKey] };
242
- const path = isDouble ? "/usr/rsrc/mixer64.wasm" : "/usr/rsrc/mixer32.wasm";
243
- const mixerBuffer = this.fs().readFile(path, { encoding: "binary" });
310
+ const bufferKey = isDouble ? 'mixer64Buffer' : 'mixer32Buffer';
311
+ const moduleKey = isDouble ? 'mixer64Module' : 'mixer32Module';
312
+ if (this[moduleKey])
313
+ return {
314
+ mixerBuffer: this[bufferKey],
315
+ mixerModule: this[moduleKey]
316
+ };
317
+ const path = isDouble
318
+ ? '/usr/rsrc/mixer64.wasm'
319
+ : '/usr/rsrc/mixer32.wasm';
320
+ const mixerBuffer = this.fs().readFile(path, { encoding: 'binary' });
244
321
  this[bufferKey] = mixerBuffer;
245
322
  // Compile mixer
246
323
  const mixerModule = new WebAssembly.Module(new Uint8Array(mixerBuffer));