@grame/faustwasm 0.1.7 → 0.2.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.
- package/assets/standalone/faustwasm/index.d.ts +132 -99
- package/assets/standalone/faustwasm/index.js +907 -1230
- package/assets/standalone/faustwasm/index.js.map +4 -4
- package/dist/cjs/index.d.ts +132 -99
- package/dist/cjs/index.js +909 -1212
- package/dist/cjs/index.js.map +4 -4
- package/dist/cjs-bundle/index.d.ts +132 -99
- package/dist/cjs-bundle/index.js +1012 -1317
- package/dist/cjs-bundle/index.js.map +4 -4
- package/dist/esm/index.d.ts +132 -99
- package/dist/esm/index.js +907 -1230
- package/dist/esm/index.js.map +4 -4
- package/dist/esm-bundle/index.d.ts +132 -99
- package/dist/esm-bundle/index.js +1012 -1321
- package/dist/esm-bundle/index.js.map +4 -4
- package/libfaust-wasm/libfaust-wasm.js +1 -1
- package/libfaust-wasm/libfaust-wasm.wasm +0 -0
- package/package.json +15 -15
- package/src/FaustAudioWorkletProcessor.ts +3 -14
- package/src/FaustCmajor.ts +6 -6
- package/src/FaustCompiler.ts +2 -2
- package/src/FaustDspGenerator.ts +109 -75
- package/src/FaustDspInstance.ts +2 -2
- package/src/FaustFFTAudioWorkletProcessor.ts +3 -1
- package/src/FaustWebAudioDsp.ts +224 -449
- package/src/SoundfileReader.ts +117 -0
- package/src/exports.ts +1 -0
- package/src/faust2wasmFiles.js +1 -1
- package/src/types.ts +15 -7
- package/test/faustlive-wasm/faustwasm/index.d.ts +132 -99
- package/test/faustlive-wasm/faustwasm/index.js +907 -1230
- package/test/faustlive-wasm/faustwasm/index.js.map +4 -4
- package/test/soundfile.dsp +15 -0
- package/test/soundfile1.dsp +23 -0
- package/test/web/soundfile.html +69 -0
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@grame/faustwasm",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "WebAssembly version of Faust Compiler",
|
|
5
5
|
"main": "dist/cjs/index.js",
|
|
6
6
|
"types": "dist/esm/index.d.ts",
|
|
@@ -9,9 +9,9 @@
|
|
|
9
9
|
"scripts": {
|
|
10
10
|
"build": "npm run build-cjs && npm run build-cjs-bundle && npm run build-esm && npm run build-esm-bundle && node postbuild-bundled.js & npm run build-types & npm run build-types-bundle",
|
|
11
11
|
"build-cjs": "esbuild src/index.ts --target=es2019 --bundle --sourcemap --outdir=dist/cjs --format=iife --external:fs --external:url",
|
|
12
|
-
"build-cjs-bundle": "node prebuild-bundled.js && esbuild src/index-bundle-iife.ts --target=es2019 --bundle --sourcemap --loader:.wasm=binary --loader:.data=binary --outfile=dist/cjs-bundle/index.js --format=iife --external:fs --external:url --external:path && node postbuild-bundled.js",
|
|
12
|
+
"build-cjs-bundle": "node prebuild-bundled.js && esbuild src/index-bundle-iife.ts --target=es2019 --bundle --sourcemap --loader:.wasm=binary --loader:.data=binary --outfile=dist/cjs-bundle/index.js --format=iife --external:fs --external:url --external:path --external:ws && node postbuild-bundled.js",
|
|
13
13
|
"build-esm": "esbuild src/index.ts --target=es2019 --bundle --sourcemap --outdir=dist/esm --format=esm --external:fs --external:url",
|
|
14
|
-
"build-esm-bundle": "node prebuild-bundled.js && esbuild src/index-bundle.ts --target=es2019 --bundle --sourcemap --loader:.wasm=binary --loader:.data=binary --outfile=dist/esm-bundle/index.js --format=esm --external:fs --external:url --external:path && node postbuild-bundled.js",
|
|
14
|
+
"build-esm-bundle": "node prebuild-bundled.js && esbuild src/index-bundle.ts --target=es2019 --bundle --sourcemap --loader:.wasm=binary --loader:.data=binary --outfile=dist/esm-bundle/index.js --format=esm --external:fs --external:url --external:path --external:ws && node postbuild-bundled.js",
|
|
15
15
|
"build-types": "dts-bundle-generator -o dist/cjs/index.d.ts src/index.ts --external-imports",
|
|
16
16
|
"build-types-bundle": "dts-bundle-generator -o dist/cjs-bundle/index.d.ts src/index-bundle.ts --external-imports",
|
|
17
17
|
"postbuild": "node postbuild.js"
|
|
@@ -27,9 +27,9 @@
|
|
|
27
27
|
"signal processing"
|
|
28
28
|
],
|
|
29
29
|
"bin": {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
30
|
+
"faust2sndfile-ts": "scripts/faust2sndfile.js",
|
|
31
|
+
"faust2svg-ts": "scripts/faust2svg.js",
|
|
32
|
+
"faust2wasm-ts": "scripts/faust2wasm.js"
|
|
33
33
|
},
|
|
34
34
|
"author": "Grame-CNCM",
|
|
35
35
|
"license": "LGPL-3.0",
|
|
@@ -37,16 +37,16 @@
|
|
|
37
37
|
"url": "https://github.com/grame-cncm/faustwasm/issues"
|
|
38
38
|
},
|
|
39
39
|
"homepage": "https://github.com/grame-cncm/faustwasm#readme",
|
|
40
|
-
"dependencies": {
|
|
41
|
-
"@types/emscripten": "^1.39.5"
|
|
42
|
-
},
|
|
43
40
|
"devDependencies": {
|
|
44
|
-
"@aws-crypto/sha256-js": "^2.0
|
|
41
|
+
"@aws-crypto/sha256-js": "^5.2.0",
|
|
45
42
|
"@shren/faust-ui": "^1.1.9",
|
|
46
|
-
"@types/node": "^
|
|
47
|
-
"@types/webmidi": "^2.0.
|
|
48
|
-
"dts-bundle-generator": "^
|
|
49
|
-
"esbuild": "^0.
|
|
50
|
-
"typescript": "^
|
|
43
|
+
"@types/node": "^20.12.7",
|
|
44
|
+
"@types/webmidi": "^2.0.10",
|
|
45
|
+
"dts-bundle-generator": "^9.5.1",
|
|
46
|
+
"esbuild": "^0.20.2",
|
|
47
|
+
"typescript": "^5.4.5"
|
|
48
|
+
},
|
|
49
|
+
"dependencies": {
|
|
50
|
+
"@types/emscripten": "^1.39.10"
|
|
51
51
|
}
|
|
52
52
|
}
|
|
@@ -190,13 +190,7 @@ const getFaustAudioWorkletProcessor = <Poly extends boolean = false>(dependencie
|
|
|
190
190
|
const instance = FaustWasmInstantiator.createSyncMonoDSPInstance(factory);
|
|
191
191
|
|
|
192
192
|
// Create Monophonic DSP
|
|
193
|
-
this.fDSPCode = new FaustMonoWebAudioDsp(instance, sampleRate, sampleSize, 128);
|
|
194
|
-
|
|
195
|
-
// Check for soundfile support
|
|
196
|
-
if (this.fDSPCode.hasSoundfiles()) {
|
|
197
|
-
console.error("FaustAudioWorkletProcessor: Soundfile support is not implemented yet, switch to ScriptProcessorNode for now");
|
|
198
|
-
return;
|
|
199
|
-
}
|
|
193
|
+
this.fDSPCode = new FaustMonoWebAudioDsp(instance, sampleRate, sampleSize, 128, factory.soundfiles);
|
|
200
194
|
|
|
201
195
|
// Setup output handler
|
|
202
196
|
this.fDSPCode.setOutputParamHandler((path, value) => this.port.postMessage({ path, value, type: "param" }));
|
|
@@ -218,14 +212,9 @@ const getFaustAudioWorkletProcessor = <Poly extends boolean = false>(dependencie
|
|
|
218
212
|
|
|
219
213
|
const instance = FaustWasmInstantiator.createSyncPolyDSPInstance(voiceFactory, mixerModule, voices, effectFactory);
|
|
220
214
|
|
|
215
|
+
const soundfiles = { ...effectFactory?.soundfiles, ...voiceFactory.soundfiles };
|
|
221
216
|
// Create Polyphonic DSP
|
|
222
|
-
this.fDSPCode = new FaustPolyWebAudioDsp(instance, sampleRate, sampleSize, 128);
|
|
223
|
-
|
|
224
|
-
// Check for soundfile support
|
|
225
|
-
if (this.fDSPCode.hasSoundfiles()) {
|
|
226
|
-
console.error("FaustAudioWorkletProcessor: Soundfile support is not implemented yet, switch to ScriptProcessorNode for now");
|
|
227
|
-
return;
|
|
228
|
-
}
|
|
217
|
+
this.fDSPCode = new FaustPolyWebAudioDsp(instance, sampleRate, sampleSize, 128, soundfiles);
|
|
229
218
|
|
|
230
219
|
// Setup port message handling
|
|
231
220
|
this.port.onmessage = (e: MessageEvent) => this.handleMessageAux(e);
|
package/src/FaustCmajor.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import type FaustCompiler from "./FaustCompiler";
|
|
2
2
|
|
|
3
3
|
interface IFaustCmajor {
|
|
4
4
|
/**
|
|
@@ -13,15 +13,15 @@ interface IFaustCmajor {
|
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
class FaustCmajor implements IFaustCmajor {
|
|
16
|
-
private
|
|
16
|
+
private fCompiler: FaustCompiler;
|
|
17
17
|
|
|
18
|
-
constructor(
|
|
19
|
-
this.
|
|
18
|
+
constructor(compiler: FaustCompiler) {
|
|
19
|
+
this.fCompiler = compiler;
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
compile(name: string, code: string, args: string) {
|
|
23
|
-
const fs = this.
|
|
24
|
-
const success = this.
|
|
23
|
+
const fs = this.fCompiler.fs();
|
|
24
|
+
const success = this.fCompiler.generateAuxFiles(name, code, `-lang cmajor-hybrid -cn ${name} -o ${name}.cmajor`);
|
|
25
25
|
return (success) ? fs.readFile(`${name}.cmajor`, { encoding: "utf8" }) as string : "";
|
|
26
26
|
}
|
|
27
27
|
}
|
package/src/FaustCompiler.ts
CHANGED
|
@@ -127,7 +127,7 @@ class FaustCompiler implements IFaustCompiler {
|
|
|
127
127
|
const factory = table[shaKey];
|
|
128
128
|
const { code, json, poly } = factory;
|
|
129
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 })));
|
|
130
|
+
awaited.push(WebAssembly.compile(ab).then(module => this.gFactories.set(shaKey, { shaKey, cfactory: 0, code: ab, module, json: JSON.stringify(json), poly, soundfiles: {} })));
|
|
131
131
|
}
|
|
132
132
|
return Promise.all(awaited);
|
|
133
133
|
}
|
|
@@ -167,7 +167,7 @@ class FaustCompiler implements IFaustCompiler {
|
|
|
167
167
|
const ui8Code = this.intVec2intArray(faustDspWasm.data);
|
|
168
168
|
faustDspWasm.data.delete();
|
|
169
169
|
const module = await WebAssembly.compile(ui8Code);
|
|
170
|
-
const factory: FaustDspFactory = { shaKey, cfactory: faustDspWasm.cfactory, code: ui8Code, module, json: faustDspWasm.json, poly };
|
|
170
|
+
const factory: FaustDspFactory = { shaKey, cfactory: faustDspWasm.cfactory, code: ui8Code, module, json: faustDspWasm.json, poly, soundfiles: {} };
|
|
171
171
|
// Factory C++ side can be deallocated immediately
|
|
172
172
|
this.deleteDSPFactory(factory);
|
|
173
173
|
// Keep the compiled factory in the cache
|
package/src/FaustDspGenerator.ts
CHANGED
|
@@ -5,9 +5,10 @@ import { FaustDspInstance } from "./FaustDspInstance";
|
|
|
5
5
|
import FaustWasmInstantiator from "./FaustWasmInstantiator";
|
|
6
6
|
import { FaustMonoOfflineProcessor, FaustPolyOfflineProcessor, IFaustMonoOfflineProcessor, IFaustPolyOfflineProcessor } from "./FaustOfflineProcessor";
|
|
7
7
|
import { FaustMonoScriptProcessorNode, FaustPolyScriptProcessorNode } from "./FaustScriptProcessorNode";
|
|
8
|
-
import { FaustBaseWebAudioDsp, FaustMonoWebAudioDsp, FaustPolyWebAudioDsp, FaustWebAudioDspVoice, IFaustMonoWebAudioNode, IFaustPolyWebAudioNode } from "./FaustWebAudioDsp";
|
|
8
|
+
import { FaustBaseWebAudioDsp, FaustMonoWebAudioDsp, FaustPolyWebAudioDsp, FaustWebAudioDspVoice, IFaustMonoWebAudioNode, IFaustPolyWebAudioNode, Soundfile, WasmAllocator } from "./FaustWebAudioDsp";
|
|
9
9
|
import type { IFaustCompiler } from "./FaustCompiler";
|
|
10
10
|
import type { FaustDspFactory, FaustUIDescriptor, FaustDspMeta, FFTUtils, LooseFaustDspFactory } from "./types";
|
|
11
|
+
import SoundfileReader from "./SoundfileReader";
|
|
11
12
|
|
|
12
13
|
export interface IFaustMonoDspGenerator {
|
|
13
14
|
/**
|
|
@@ -73,7 +74,11 @@ export interface IFaustMonoDspGenerator {
|
|
|
73
74
|
* @param factory - default is the compiled factory
|
|
74
75
|
* @returns the compiled processor or 'null' if failure
|
|
75
76
|
*/
|
|
76
|
-
createOfflineProcessor(
|
|
77
|
+
createOfflineProcessor(
|
|
78
|
+
sampleRate: number,
|
|
79
|
+
bufferSize: number,
|
|
80
|
+
factory?: LooseFaustDspFactory
|
|
81
|
+
): Promise<IFaustMonoOfflineProcessor | null>;
|
|
77
82
|
|
|
78
83
|
/**
|
|
79
84
|
* Get DSP JSON description with its UI and metadata as object.
|
|
@@ -134,7 +139,8 @@ export interface IFaustPolyDspGenerator {
|
|
|
134
139
|
mixerModule?: WebAssembly.Module,
|
|
135
140
|
effectFactory?: LooseFaustDspFactory | null,
|
|
136
141
|
sp?: boolean,
|
|
137
|
-
bufferSize?: number
|
|
142
|
+
bufferSize?: number,
|
|
143
|
+
processorName?: string
|
|
138
144
|
): Promise<IFaustPolyWebAudioNode | null>;
|
|
139
145
|
|
|
140
146
|
/**
|
|
@@ -153,7 +159,8 @@ export interface IFaustPolyDspGenerator {
|
|
|
153
159
|
voices: number,
|
|
154
160
|
voiceFactory?: LooseFaustDspFactory,
|
|
155
161
|
mixerModule?: WebAssembly.Module,
|
|
156
|
-
effectFactory?: LooseFaustDspFactory | null
|
|
162
|
+
effectFactory?: LooseFaustDspFactory | null,
|
|
163
|
+
processorName?: string
|
|
157
164
|
): Promise<IFaustPolyOfflineProcessor | null>;
|
|
158
165
|
|
|
159
166
|
/**
|
|
@@ -210,11 +217,10 @@ export class FaustMonoDspGenerator implements IFaustMonoDspGenerator {
|
|
|
210
217
|
|
|
211
218
|
const meta = JSON.parse(factory.json);
|
|
212
219
|
const sampleSize = meta.compile_options.match("-double") ? 8 : 4;
|
|
220
|
+
factory.soundfiles = await SoundfileReader.loadSoundfiles(meta, factory.soundfiles || {}, context);
|
|
213
221
|
if (sp) {
|
|
214
222
|
const instance = await FaustWasmInstantiator.createAsyncMonoDSPInstance(factory);
|
|
215
|
-
const monoDsp = new FaustMonoWebAudioDsp(instance, context.sampleRate, sampleSize, bufferSize);
|
|
216
|
-
// Initialize the DSP instance, possibly loading soundfiles
|
|
217
|
-
await monoDsp.init(context);
|
|
223
|
+
const monoDsp = new FaustMonoWebAudioDsp(instance, context.sampleRate, sampleSize, bufferSize, factory.soundfiles);
|
|
218
224
|
const sp = context.createScriptProcessor(bufferSize, monoDsp.getNumInputs(), monoDsp.getNumOutputs()) as FaustMonoScriptProcessorNode;
|
|
219
225
|
Object.setPrototypeOf(sp, FaustMonoScriptProcessorNode.prototype);
|
|
220
226
|
sp.init(monoDsp);
|
|
@@ -233,15 +239,23 @@ const faustData = ${JSON.stringify({
|
|
|
233
239
|
poly: false
|
|
234
240
|
} as FaustData)};
|
|
235
241
|
// Implementation needed classes of functions
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
242
|
+
var ${FaustDspInstance.name} = ${FaustDspInstance.toString()}
|
|
243
|
+
var FaustDspInstance = ${FaustDspInstance.name};
|
|
244
|
+
var ${FaustBaseWebAudioDsp.name} = ${FaustBaseWebAudioDsp.toString()}
|
|
245
|
+
var FaustBaseWebAudioDsp = ${FaustBaseWebAudioDsp.name};
|
|
246
|
+
var ${FaustMonoWebAudioDsp.name} = ${FaustMonoWebAudioDsp.toString()}
|
|
247
|
+
var FaustMonoWebAudioDsp = ${FaustMonoWebAudioDsp.name};
|
|
248
|
+
var ${FaustWasmInstantiator.name} = ${FaustWasmInstantiator.toString()}
|
|
249
|
+
var FaustWasmInstantiator = ${FaustWasmInstantiator.name};
|
|
250
|
+
var ${Soundfile.name} = ${Soundfile.toString()}
|
|
251
|
+
var Soundfile = ${Soundfile.name};
|
|
252
|
+
var ${WasmAllocator.name} = ${WasmAllocator.toString()}
|
|
253
|
+
var WasmAllocator = ${WasmAllocator.name};
|
|
240
254
|
// Put them in dependencies
|
|
241
255
|
const dependencies = {
|
|
242
|
-
FaustBaseWebAudioDsp
|
|
243
|
-
FaustMonoWebAudioDsp
|
|
244
|
-
FaustWasmInstantiator
|
|
256
|
+
FaustBaseWebAudioDsp,
|
|
257
|
+
FaustMonoWebAudioDsp,
|
|
258
|
+
FaustWasmInstantiator
|
|
245
259
|
};
|
|
246
260
|
// Generate the actual AudioWorkletProcessor code
|
|
247
261
|
(${getFaustAudioWorkletProcessor.toString()})(dependencies, faustData);
|
|
@@ -274,6 +288,7 @@ const dependencies = {
|
|
|
274
288
|
|
|
275
289
|
const meta: FaustDspMeta = JSON.parse(factory.json);
|
|
276
290
|
const sampleSize = meta.compile_options.match("-double") ? 8 : 4;
|
|
291
|
+
factory.soundfiles = await SoundfileReader.loadSoundfiles(meta, factory.soundfiles || {}, context);
|
|
277
292
|
// Dynamically create AudioWorkletProcessor if code not yet created
|
|
278
293
|
if (!FaustMonoDspGenerator.gWorkletProcessors.has(context)) FaustMonoDspGenerator.gWorkletProcessors.set(context, new Set());
|
|
279
294
|
if (!FaustMonoDspGenerator.gWorkletProcessors.get(context)?.has(processorName)) {
|
|
@@ -287,16 +302,24 @@ const faustData = ${JSON.stringify({
|
|
|
287
302
|
fftOptions
|
|
288
303
|
} as FaustFFTData)};
|
|
289
304
|
// Implementation needed classes of functions
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
305
|
+
var ${FaustDspInstance.name} = ${FaustDspInstance.toString()}
|
|
306
|
+
var FaustDspInstance = ${FaustDspInstance.name};
|
|
307
|
+
var ${FaustBaseWebAudioDsp.name} = ${FaustBaseWebAudioDsp.toString()}
|
|
308
|
+
var FaustBaseWebAudioDsp = ${FaustBaseWebAudioDsp.name};
|
|
309
|
+
var ${FaustMonoWebAudioDsp.name} = ${FaustMonoWebAudioDsp.toString()}
|
|
310
|
+
var FaustMonoWebAudioDsp = ${FaustMonoWebAudioDsp.name};
|
|
311
|
+
var ${FaustWasmInstantiator.name} = ${FaustWasmInstantiator.toString()}
|
|
312
|
+
var FaustWasmInstantiator = ${FaustWasmInstantiator.name};
|
|
313
|
+
var ${Soundfile.name} = ${Soundfile.toString()}
|
|
314
|
+
var Soundfile = ${Soundfile.name};
|
|
315
|
+
var ${WasmAllocator.name} = ${WasmAllocator.toString()}
|
|
316
|
+
var WasmAllocator = ${WasmAllocator.name};
|
|
317
|
+
var FFTUtils = ${fftUtils.toString()}
|
|
295
318
|
// Put them in dependencies
|
|
296
319
|
const dependencies = {
|
|
297
|
-
FaustBaseWebAudioDsp
|
|
298
|
-
FaustMonoWebAudioDsp
|
|
299
|
-
FaustWasmInstantiator
|
|
320
|
+
FaustBaseWebAudioDsp,
|
|
321
|
+
FaustMonoWebAudioDsp,
|
|
322
|
+
FaustWasmInstantiator,
|
|
300
323
|
FFTUtils
|
|
301
324
|
};
|
|
302
325
|
// Generate the actual AudioWorkletProcessor code
|
|
@@ -371,16 +394,14 @@ const dependencies = {
|
|
|
371
394
|
async createOfflineProcessor(
|
|
372
395
|
sampleRate: number,
|
|
373
396
|
bufferSize: number,
|
|
374
|
-
factory = this.factory as LooseFaustDspFactory
|
|
397
|
+
factory = this.factory as LooseFaustDspFactory
|
|
375
398
|
) {
|
|
376
399
|
if (!factory) throw new Error("Code is not compiled, please define the factory or call `await this.compile()` first.");
|
|
377
400
|
|
|
378
401
|
const meta = JSON.parse(factory.json);
|
|
379
402
|
const instance = await FaustWasmInstantiator.createAsyncMonoDSPInstance(factory);
|
|
380
403
|
const sampleSize = meta.compile_options.match("-double") ? 8 : 4;
|
|
381
|
-
const monoDsp = new FaustMonoWebAudioDsp(instance, sampleRate, sampleSize, bufferSize);
|
|
382
|
-
// Initialize the DSP instance, no soundfiles loading for now (TODO ?)
|
|
383
|
-
await monoDsp.init(null);
|
|
404
|
+
const monoDsp = new FaustMonoWebAudioDsp(instance, sampleRate, sampleSize, bufferSize, factory.soundfiles);
|
|
384
405
|
return new FaustMonoOfflineProcessor(monoDsp, bufferSize);
|
|
385
406
|
}
|
|
386
407
|
|
|
@@ -421,43 +442,45 @@ export class FaustPolyDspGenerator implements IFaustPolyDspGenerator {
|
|
|
421
442
|
// the voice and effect are adapted, possibly clearing buffers
|
|
422
443
|
if (this.effectFactory) {
|
|
423
444
|
const effectJSON = JSON.parse(this.effectFactory.json);
|
|
424
|
-
const dspCode =
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
445
|
+
const dspCode = `\
|
|
446
|
+
// Voice output is forced to 2, when DSP is stereo or effect has 2 ins or 2 outs,
|
|
447
|
+
// so that the effect can process the 2 channels of the voice
|
|
448
|
+
adaptOut(1,1,1) = _;
|
|
449
|
+
adaptOut(1,1,2) = _ <: _,0; // The left channel only is kept
|
|
450
|
+
adaptOut(1,2,1) = _ <: _,_;
|
|
451
|
+
adaptOut(1,2,2) = _ <: _,_;
|
|
452
|
+
adaptOut(2,1,1) = _,_;
|
|
453
|
+
adaptOut(2,1,2) = _,_;
|
|
454
|
+
adaptOut(2,2,1) = _,_;
|
|
455
|
+
adaptOut(2,2,2) = _,_;
|
|
456
|
+
adaptor(F) = adaptOut(outputs(F),${effectJSON.inputs},${effectJSON.outputs});
|
|
457
|
+
dsp_code = environment{
|
|
458
|
+
${dspCodeAux}
|
|
459
|
+
};
|
|
460
|
+
process = dsp_code.process : adaptor(dsp_code.process);
|
|
461
|
+
`;
|
|
462
|
+
const effectCode = `\
|
|
463
|
+
// Inputs
|
|
464
|
+
adaptIn(1,1,1) = _;
|
|
465
|
+
adaptIn(1,1,2) = _,_ :> _;
|
|
466
|
+
adaptIn(1,2,1) = _,_;
|
|
467
|
+
adaptIn(1,2,2) = _,_;
|
|
468
|
+
adaptIn(2,1,1) = _,_ :> _;
|
|
469
|
+
adaptIn(2,1,2) = _,_ :> _;
|
|
470
|
+
adaptIn(2,2,1) = _,_;
|
|
471
|
+
adaptIn(2,2,2) = _,_;
|
|
472
|
+
// Outputs
|
|
473
|
+
adaptOut(1,1) = _ <: _,0; // The left channel only is kept
|
|
474
|
+
adaptOut(1,2) = _,_;
|
|
475
|
+
adaptOut(2,1) = _ <: _,0; // The left channel only is kept
|
|
476
|
+
adaptOut(2,2) = _,_;
|
|
477
|
+
adaptorIns(F) = adaptIn(outputs(F),${effectJSON.inputs},${effectJSON.outputs});
|
|
478
|
+
adaptorOuts = adaptOut(${effectJSON.inputs},${effectJSON.outputs});
|
|
479
|
+
dsp_code = environment{
|
|
480
|
+
${dspCodeAux}
|
|
481
|
+
};
|
|
482
|
+
process = adaptorIns(dsp_code.process) : dsp_code.effect : adaptorOuts;
|
|
483
|
+
`;
|
|
461
484
|
this.voiceFactory = await compiler.createPolyDSPFactory(name, dspCode, args);
|
|
462
485
|
try {
|
|
463
486
|
// Effect is processing same buffers for inputs and outputs, so has to use -inpl option
|
|
@@ -500,11 +523,12 @@ export class FaustPolyDspGenerator implements IFaustPolyDspGenerator {
|
|
|
500
523
|
const voiceMeta = JSON.parse(voiceFactory.json);
|
|
501
524
|
const effectMeta = effectFactory ? JSON.parse(effectFactory.json) : undefined;
|
|
502
525
|
const sampleSize = voiceMeta.compile_options.match("-double") ? 8 : 4;
|
|
526
|
+
voiceFactory.soundfiles = await SoundfileReader.loadSoundfiles(voiceMeta, voiceFactory.soundfiles || {}, context);
|
|
527
|
+
if (effectFactory) effectFactory.soundfiles = await SoundfileReader.loadSoundfiles(effectMeta, effectFactory.soundfiles || {}, context);
|
|
503
528
|
if (sp) {
|
|
504
529
|
const instance = await FaustWasmInstantiator.createAsyncPolyDSPInstance(voiceFactory, mixerModule, voices, effectFactory || undefined);
|
|
505
|
-
const
|
|
506
|
-
|
|
507
|
-
await polyDsp.init(context);
|
|
530
|
+
const soundfiles = { ...effectFactory?.soundfiles, ...voiceFactory.soundfiles };
|
|
531
|
+
const polyDsp = new FaustPolyWebAudioDsp(instance, context.sampleRate, sampleSize, bufferSize, soundfiles);
|
|
508
532
|
const sp = context.createScriptProcessor(bufferSize, polyDsp.getNumInputs(), polyDsp.getNumOutputs()) as FaustPolyScriptProcessorNode;
|
|
509
533
|
Object.setPrototypeOf(sp, FaustPolyScriptProcessorNode.prototype);
|
|
510
534
|
sp.init(polyDsp);
|
|
@@ -524,16 +548,25 @@ const faustData = ${JSON.stringify({
|
|
|
524
548
|
effectMeta
|
|
525
549
|
} as FaustData)};
|
|
526
550
|
// Implementation needed classes of functions
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
551
|
+
var ${FaustDspInstance.name} = ${FaustDspInstance.toString()}
|
|
552
|
+
var FaustDspInstance = ${FaustDspInstance.name};
|
|
553
|
+
var ${FaustBaseWebAudioDsp.name} = ${FaustBaseWebAudioDsp.toString()}
|
|
554
|
+
var FaustBaseWebAudioDsp = ${FaustBaseWebAudioDsp.name};
|
|
555
|
+
var ${FaustPolyWebAudioDsp.name} = ${FaustPolyWebAudioDsp.toString()}
|
|
556
|
+
var FaustPolyWebAudioDsp = ${FaustPolyWebAudioDsp.name};
|
|
557
|
+
var ${FaustWebAudioDspVoice.name} = ${FaustWebAudioDspVoice.toString()}
|
|
558
|
+
var FaustWebAudioDspVoice = ${FaustWebAudioDspVoice.name};
|
|
559
|
+
var ${FaustWasmInstantiator.name} = ${FaustWasmInstantiator.toString()}
|
|
560
|
+
var FaustWasmInstantiator = ${FaustWasmInstantiator.name};
|
|
561
|
+
var ${Soundfile.name} = ${Soundfile.toString()}
|
|
562
|
+
var Soundfile = ${Soundfile.name};
|
|
563
|
+
var ${WasmAllocator.name} = ${WasmAllocator.toString()}
|
|
564
|
+
var WasmAllocator = ${WasmAllocator.name};
|
|
532
565
|
// Put them in dependencies
|
|
533
566
|
const dependencies = {
|
|
534
|
-
FaustBaseWebAudioDsp
|
|
535
|
-
FaustPolyWebAudioDsp
|
|
536
|
-
FaustWasmInstantiator
|
|
567
|
+
FaustBaseWebAudioDsp,
|
|
568
|
+
FaustPolyWebAudioDsp,
|
|
569
|
+
FaustWasmInstantiator
|
|
537
570
|
};
|
|
538
571
|
// Generate the actual AudioWorkletProcessor code
|
|
539
572
|
(${getFaustAudioWorkletProcessor.toString()})(dependencies, faustData);
|
|
@@ -606,7 +639,8 @@ const dependencies = {
|
|
|
606
639
|
const effectMeta = effectFactory ? JSON.parse(effectFactory.json) : undefined;
|
|
607
640
|
const instance = await FaustWasmInstantiator.createAsyncPolyDSPInstance(voiceFactory, mixerModule, voices, effectFactory || undefined);
|
|
608
641
|
const sampleSize = voiceMeta.compile_options.match("-double") ? 8 : 4;
|
|
609
|
-
const
|
|
642
|
+
const soundfiles = { ...effectFactory?.soundfiles, ...voiceFactory.soundfiles };
|
|
643
|
+
const polyDsp = new FaustPolyWebAudioDsp(instance, sampleRate, sampleSize, bufferSize, soundfiles);
|
|
610
644
|
return new FaustPolyOfflineProcessor(polyDsp, bufferSize);
|
|
611
645
|
}
|
|
612
646
|
|
package/src/FaustDspInstance.ts
CHANGED
|
@@ -31,7 +31,7 @@ export interface IFaustDspInstance {
|
|
|
31
31
|
*
|
|
32
32
|
* @param $dsp - the DSP pointer
|
|
33
33
|
* @param index - the parameter index
|
|
34
|
-
* @
|
|
34
|
+
* @return the parameter value
|
|
35
35
|
*/
|
|
36
36
|
getParamValue($dsp: number, index: number): number;
|
|
37
37
|
|
|
@@ -39,7 +39,7 @@ export interface IFaustDspInstance {
|
|
|
39
39
|
* Give the Faust wasm instance sample rate.
|
|
40
40
|
*
|
|
41
41
|
* @param $dsp - the DSP pointer
|
|
42
|
-
* @
|
|
42
|
+
* @return the sample rate
|
|
43
43
|
*/
|
|
44
44
|
getSampleRate($dsp: number): number;
|
|
45
45
|
|
|
@@ -162,6 +162,7 @@ const getFaustFFTAudioWorkletProcessor = (dependencies: FaustFFTAudioWorkletProc
|
|
|
162
162
|
private fPlotHandler: PlotHandler | null = null;
|
|
163
163
|
private fCachedEvents: { type: string; data: any }[] = [];
|
|
164
164
|
private fBufferNum = 0;
|
|
165
|
+
private soundfiles: LooseFaustDspFactory["soundfiles"] = {};
|
|
165
166
|
get fftProcessorBufferSize() {
|
|
166
167
|
return this.fftSize / 2 + 1;
|
|
167
168
|
}
|
|
@@ -182,6 +183,7 @@ const getFaustFFTAudioWorkletProcessor = (dependencies: FaustFFTAudioWorkletProc
|
|
|
182
183
|
|
|
183
184
|
this.dspInstance = FaustWasmInstantiator.createSyncMonoDSPInstance(factory);
|
|
184
185
|
this.sampleSize = sampleSize;
|
|
186
|
+
this.soundfiles = factory.soundfiles;
|
|
185
187
|
|
|
186
188
|
// Init the FFT constructor and the Faust FFT Processor
|
|
187
189
|
this.initFFT();
|
|
@@ -509,7 +511,7 @@ const getFaustFFTAudioWorkletProcessor = (dependencies: FaustFFTAudioWorkletProc
|
|
|
509
511
|
this.fDSPCode?.destroy();
|
|
510
512
|
|
|
511
513
|
// Create Monophonic DSP
|
|
512
|
-
this.fDSPCode = new FaustMonoWebAudioDsp(this.dspInstance, sampleRate, this.sampleSize, this.fftProcessorBufferSize);
|
|
514
|
+
this.fDSPCode = new FaustMonoWebAudioDsp(this.dspInstance, sampleRate, this.sampleSize, this.fftProcessorBufferSize, this.soundfiles);
|
|
513
515
|
|
|
514
516
|
// Setup output handler
|
|
515
517
|
this.fDSPCode.setOutputParamHandler((path, value) => this.port.postMessage({ path, value, type: "param" }));
|