@grame/faustwasm 0.12.2 → 0.13.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/.prettierrc +5 -0
- package/README.md +21 -3
- package/assets/standalone/faustwasm/index.d.ts +38 -16
- package/assets/standalone/faustwasm/index.js +1574 -404
- package/assets/standalone/faustwasm/index.js.map +2 -2
- package/dist/cjs/index.d.ts +38 -16
- package/dist/cjs/index.js +1573 -404
- package/dist/cjs/index.js.map +2 -2
- package/dist/cjs-bundle/index.d.ts +38 -16
- package/dist/cjs-bundle/index.js +1576 -406
- package/dist/cjs-bundle/index.js.map +2 -2
- package/dist/esm/index.d.ts +38 -16
- package/dist/esm/index.js +1574 -404
- package/dist/esm/index.js.map +2 -2
- package/dist/esm-bundle/index.d.ts +38 -16
- package/dist/esm-bundle/index.js +1576 -406
- package/dist/esm-bundle/index.js.map +2 -2
- package/eslint.config.js +11 -0
- package/package.json +57 -51
- package/sound.cpp +163 -0
- package/sound.dsp +4 -0
- package/sound.json +1 -0
- package/sound.wasm +0 -0
- package/src/FaustAudioWorkletCommunicator.ts +150 -143
- package/src/FaustAudioWorkletNode.ts +173 -75
- package/src/FaustAudioWorkletProcessor.ts +218 -90
- package/src/FaustCmajor.ts +9 -3
- package/src/FaustCompiler.ts +112 -35
- package/src/FaustDspGenerator.ts +561 -117
- package/src/FaustDspInstance.ts +58 -24
- package/src/FaustFFTAudioWorkletProcessor.ts +822 -612
- package/src/FaustOfflineProcessor.ts +187 -56
- package/src/FaustScriptProcessorNode.ts +156 -49
- package/src/FaustSensors.ts +426 -96
- package/src/FaustSvgDiagrams.ts +18 -5
- package/src/FaustWasmInstantiator.ts +224 -70
- package/src/FaustWebAudioDsp.ts +1060 -349
- package/src/LibFaust.ts +13 -4
- package/src/SoundfileReader.ts +175 -131
- package/src/WavDecoder.ts +42 -20
- package/src/WavEncoder.ts +35 -21
- package/src/copyWebStandaloneAssets.d.ts +20 -5
- package/src/copyWebStandaloneAssets.js +203 -75
- package/src/exports-bundle.ts +5 -5
- package/src/exports.ts +24 -24
- package/src/faust2CmajorFiles.d.ts +7 -3
- package/src/faust2cmajorFiles.js +10 -8
- package/src/faust2svgFiles.d.ts +7 -3
- package/src/faust2svgFiles.js +9 -7
- package/src/faust2wasmFiles.d.ts +10 -5
- package/src/faust2wasmFiles.js +34 -17
- package/src/faust2wavFiles.d.ts +12 -3
- package/src/faust2wavFiles.js +25 -12
- package/src/index-bundle-iife.ts +2 -2
- package/src/index-bundle.ts +1 -1
- package/src/index.ts +1 -1
- package/src/instantiateFaustModule.ts +43 -36
- package/src/instantiateFaustModuleFromFile.ts +30 -14
- package/src/types.ts +101 -25
- package/test/faustlive-wasm/faustwasm/index.d.ts +38 -16
- package/test/faustlive-wasm/faustwasm/index.js +1574 -404
- package/test/faustlive-wasm/faustwasm/index.js.map +2 -2
- package/test/web/create-faust-node.html +53 -0
- package/test/web/create-faust-node.js +186 -0
- package/test/organ/create-node.js +0 -252
- package/test/organ/dsp-meta.json +0 -131
- package/test/organ/dsp-module.wasm +0 -0
- package/test/organ/faust-pwa.js +0 -344
- package/test/organ/faust-ui/index.css +0 -442
- package/test/organ/faust-ui/index.css.map +0 -1
- package/test/organ/faust-ui/index.d.ts +0 -1
- package/test/organ/faust-ui/index.js +0 -3756
- package/test/organ/faust-ui/index.js.map +0 -1
- package/test/organ/faustwasm/index.d.ts +0 -1705
- package/test/organ/faustwasm/index.js +0 -4773
- package/test/organ/faustwasm/index.js.map +0 -7
- package/test/organ/icon.png +0 -0
- package/test/organ/index.html +0 -76
- package/test/organ/index.js +0 -69
- package/test/organ/manifest.json +0 -17
- package/test/organ/service-worker.js +0 -165
|
@@ -1,8 +1,22 @@
|
|
|
1
|
-
import type { FaustAudioWorkletProcessorCommunicator } from
|
|
2
|
-
import type FaustWasmInstantiator from
|
|
3
|
-
import type {
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
import type { FaustAudioWorkletProcessorCommunicator } from './FaustAudioWorkletCommunicator';
|
|
2
|
+
import type FaustWasmInstantiator from './FaustWasmInstantiator';
|
|
3
|
+
import type {
|
|
4
|
+
FaustBaseWebAudioDsp,
|
|
5
|
+
FaustWebAudioDspVoice,
|
|
6
|
+
FaustMonoWebAudioDsp,
|
|
7
|
+
FaustPolyWebAudioDsp
|
|
8
|
+
} from './FaustWebAudioDsp';
|
|
9
|
+
import type {
|
|
10
|
+
AudioParamDescriptor,
|
|
11
|
+
AudioWorkletGlobalScope,
|
|
12
|
+
LooseFaustDspFactory,
|
|
13
|
+
FaustDspMeta,
|
|
14
|
+
FaustUIItem
|
|
15
|
+
} from './types';
|
|
16
|
+
import type {
|
|
17
|
+
AudioWorkletGlobalScope as WamAudioWorkletGlobalScope,
|
|
18
|
+
WamParamMgrSDKBaseModuleScope
|
|
19
|
+
} from '@webaudiomodules/sdk-parammgr';
|
|
6
20
|
|
|
7
21
|
/**
|
|
8
22
|
* Injected in the string to be compiled on AudioWorkletProcessor side
|
|
@@ -13,22 +27,35 @@ export interface FaustData {
|
|
|
13
27
|
dspMeta: FaustDspMeta;
|
|
14
28
|
poly: boolean;
|
|
15
29
|
effectMeta?: FaustDspMeta;
|
|
16
|
-
}
|
|
17
|
-
export interface FaustAudioWorkletProcessorDependencies<
|
|
30
|
+
}
|
|
31
|
+
export interface FaustAudioWorkletProcessorDependencies<
|
|
32
|
+
Poly extends boolean = false
|
|
33
|
+
> {
|
|
18
34
|
FaustBaseWebAudioDsp: typeof FaustBaseWebAudioDsp;
|
|
19
|
-
FaustMonoWebAudioDsp: Poly extends true
|
|
20
|
-
|
|
21
|
-
|
|
35
|
+
FaustMonoWebAudioDsp: Poly extends true
|
|
36
|
+
? undefined
|
|
37
|
+
: typeof FaustMonoWebAudioDsp;
|
|
38
|
+
FaustPolyWebAudioDsp: Poly extends true
|
|
39
|
+
? typeof FaustPolyWebAudioDsp
|
|
40
|
+
: undefined;
|
|
41
|
+
FaustWebAudioDspVoice: Poly extends true
|
|
42
|
+
? typeof FaustWebAudioDspVoice
|
|
43
|
+
: undefined;
|
|
22
44
|
FaustWasmInstantiator: typeof FaustWasmInstantiator;
|
|
23
45
|
FaustAudioWorkletProcessorCommunicator: typeof FaustAudioWorkletProcessorCommunicator;
|
|
24
46
|
}
|
|
25
|
-
export interface FaustAudioWorkletNodeOptions<Poly extends boolean = false>
|
|
26
|
-
|
|
47
|
+
export interface FaustAudioWorkletNodeOptions<Poly extends boolean = false>
|
|
48
|
+
extends AudioWorkletNodeOptions {
|
|
49
|
+
processorOptions: Poly extends true
|
|
50
|
+
? FaustPolyAudioWorkletProcessorOptions
|
|
51
|
+
: FaustMonoAudioWorkletProcessorOptions;
|
|
27
52
|
}
|
|
28
|
-
export interface FaustMonoAudioWorkletNodeOptions
|
|
53
|
+
export interface FaustMonoAudioWorkletNodeOptions
|
|
54
|
+
extends AudioWorkletNodeOptions {
|
|
29
55
|
processorOptions: FaustMonoAudioWorkletProcessorOptions;
|
|
30
56
|
}
|
|
31
|
-
export interface FaustPolyAudioWorkletNodeOptions
|
|
57
|
+
export interface FaustPolyAudioWorkletNodeOptions
|
|
58
|
+
extends AudioWorkletNodeOptions {
|
|
32
59
|
processorOptions: FaustPolyAudioWorkletProcessorOptions;
|
|
33
60
|
}
|
|
34
61
|
export interface FaustAudioWorkletProcessorOptions {
|
|
@@ -38,10 +65,12 @@ export interface FaustAudioWorkletProcessorOptions {
|
|
|
38
65
|
moduleId?: string;
|
|
39
66
|
instanceId?: string;
|
|
40
67
|
}
|
|
41
|
-
export interface FaustMonoAudioWorkletProcessorOptions
|
|
68
|
+
export interface FaustMonoAudioWorkletProcessorOptions
|
|
69
|
+
extends FaustAudioWorkletProcessorOptions {
|
|
42
70
|
factory: LooseFaustDspFactory;
|
|
43
71
|
}
|
|
44
|
-
export interface FaustPolyAudioWorkletProcessorOptions
|
|
72
|
+
export interface FaustPolyAudioWorkletProcessorOptions
|
|
73
|
+
extends FaustAudioWorkletProcessorOptions {
|
|
45
74
|
voiceFactory: LooseFaustDspFactory;
|
|
46
75
|
mixerModule: WebAssembly.Module;
|
|
47
76
|
voices: number;
|
|
@@ -49,8 +78,13 @@ export interface FaustPolyAudioWorkletProcessorOptions extends FaustAudioWorklet
|
|
|
49
78
|
}
|
|
50
79
|
|
|
51
80
|
// Dynamic AudioWorkletProcessor code generator
|
|
52
|
-
const getFaustAudioWorkletProcessor = <Poly extends boolean = false>(
|
|
53
|
-
|
|
81
|
+
const getFaustAudioWorkletProcessor = <Poly extends boolean = false>(
|
|
82
|
+
dependencies: FaustAudioWorkletProcessorDependencies<Poly>,
|
|
83
|
+
faustData: FaustData,
|
|
84
|
+
register = true
|
|
85
|
+
): typeof AudioWorkletProcessor => {
|
|
86
|
+
const { registerProcessor, AudioWorkletProcessor, sampleRate } =
|
|
87
|
+
globalThis as unknown as AudioWorkletGlobalScope;
|
|
54
88
|
|
|
55
89
|
const {
|
|
56
90
|
FaustBaseWebAudioDsp,
|
|
@@ -58,34 +92,56 @@ const getFaustAudioWorkletProcessor = <Poly extends boolean = false>(dependencie
|
|
|
58
92
|
FaustAudioWorkletProcessorCommunicator
|
|
59
93
|
} = dependencies;
|
|
60
94
|
|
|
61
|
-
const {
|
|
62
|
-
processorName,
|
|
63
|
-
dspName,
|
|
64
|
-
dspMeta,
|
|
65
|
-
effectMeta,
|
|
66
|
-
poly
|
|
67
|
-
} = faustData;
|
|
95
|
+
const { processorName, dspName, dspMeta, effectMeta, poly } = faustData;
|
|
68
96
|
|
|
69
97
|
// Analyse voice JSON to generate AudioParam parameters
|
|
70
|
-
const analysePolyParameters = (
|
|
71
|
-
|
|
72
|
-
|
|
98
|
+
const analysePolyParameters = (
|
|
99
|
+
item: FaustUIItem
|
|
100
|
+
): AudioParamDescriptor | null => {
|
|
101
|
+
const polyKeywords = [
|
|
102
|
+
'/gate',
|
|
103
|
+
'/freq',
|
|
104
|
+
'/gain',
|
|
105
|
+
'/key',
|
|
106
|
+
'/vel',
|
|
107
|
+
'/velocity'
|
|
108
|
+
];
|
|
109
|
+
const isPolyReserved =
|
|
110
|
+
'address' in item &&
|
|
111
|
+
!!polyKeywords.find((k) => item.address.endsWith(k));
|
|
73
112
|
if (poly && isPolyReserved) return null;
|
|
74
|
-
if (
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
113
|
+
if (
|
|
114
|
+
item.type === 'vslider' ||
|
|
115
|
+
item.type === 'hslider' ||
|
|
116
|
+
item.type === 'nentry'
|
|
117
|
+
) {
|
|
118
|
+
return {
|
|
119
|
+
name: item.address,
|
|
120
|
+
defaultValue: item.init || 0,
|
|
121
|
+
minValue: item.min || 0,
|
|
122
|
+
maxValue: item.max || 0
|
|
123
|
+
};
|
|
124
|
+
} else if (item.type === 'button' || item.type === 'checkbox') {
|
|
125
|
+
return {
|
|
126
|
+
name: item.address,
|
|
127
|
+
defaultValue: item.init || 0,
|
|
128
|
+
minValue: 0,
|
|
129
|
+
maxValue: 1
|
|
130
|
+
};
|
|
78
131
|
}
|
|
79
132
|
return null;
|
|
80
|
-
}
|
|
133
|
+
};
|
|
81
134
|
|
|
82
135
|
/**
|
|
83
136
|
* Base class for Monophonic and Polyphonic AudioWorkletProcessor
|
|
84
137
|
*/
|
|
85
|
-
abstract class FaustAudioWorkletProcessor<
|
|
86
|
-
|
|
138
|
+
abstract class FaustAudioWorkletProcessor<
|
|
139
|
+
Poly extends boolean = false
|
|
140
|
+
> extends AudioWorkletProcessor {
|
|
87
141
|
// Use ! syntax when the field is not defined in the constructor
|
|
88
|
-
protected fDSPCode!: Poly extends true
|
|
142
|
+
protected fDSPCode!: Poly extends true
|
|
143
|
+
? FaustPolyWebAudioDsp
|
|
144
|
+
: FaustMonoWebAudioDsp;
|
|
89
145
|
|
|
90
146
|
protected paramValuesCache: Record<string, number> = {};
|
|
91
147
|
|
|
@@ -96,12 +152,15 @@ const getFaustAudioWorkletProcessor = <Poly extends boolean = false>(dependencie
|
|
|
96
152
|
super(options);
|
|
97
153
|
|
|
98
154
|
// Setup port message handling
|
|
99
|
-
this.fCommunicator = new FaustAudioWorkletProcessorCommunicator(
|
|
155
|
+
this.fCommunicator = new FaustAudioWorkletProcessorCommunicator(
|
|
156
|
+
this.port
|
|
157
|
+
);
|
|
100
158
|
|
|
101
|
-
const { parameterDescriptors } =
|
|
159
|
+
const { parameterDescriptors } = this
|
|
160
|
+
.constructor as typeof AudioWorkletProcessor;
|
|
102
161
|
parameterDescriptors.forEach((pd) => {
|
|
103
162
|
this.paramValuesCache[pd.name] = pd.defaultValue || 0;
|
|
104
|
-
})
|
|
163
|
+
});
|
|
105
164
|
|
|
106
165
|
const { moduleId, instanceId } = options.processorOptions;
|
|
107
166
|
if (!moduleId || !instanceId) return;
|
|
@@ -114,28 +173,37 @@ const getFaustAudioWorkletProcessor = <Poly extends boolean = false>(dependencie
|
|
|
114
173
|
const callback = (item: FaustUIItem) => {
|
|
115
174
|
const param = analysePolyParameters(item);
|
|
116
175
|
if (param) params.push(param);
|
|
117
|
-
}
|
|
176
|
+
};
|
|
118
177
|
FaustBaseWebAudioDsp.parseUI(dspMeta.ui, callback);
|
|
119
178
|
// Analyse effect JSON to generate AudioParam parameters
|
|
120
|
-
if (effectMeta)
|
|
179
|
+
if (effectMeta)
|
|
180
|
+
FaustBaseWebAudioDsp.parseUI(effectMeta.ui, callback);
|
|
121
181
|
return params;
|
|
122
182
|
}
|
|
123
183
|
|
|
124
184
|
setupWamEventHandler() {
|
|
125
185
|
if (!this.wamInfo) return;
|
|
126
186
|
const { moduleId, instanceId } = this.wamInfo;
|
|
127
|
-
const { webAudioModules } =
|
|
128
|
-
|
|
129
|
-
const
|
|
187
|
+
const { webAudioModules } =
|
|
188
|
+
globalThis as unknown as WamAudioWorkletGlobalScope;
|
|
189
|
+
const ModuleScope = webAudioModules.getModuleScope(
|
|
190
|
+
moduleId
|
|
191
|
+
) as WamParamMgrSDKBaseModuleScope;
|
|
192
|
+
const paramMgrProcessor =
|
|
193
|
+
ModuleScope?.paramMgrProcessors?.[instanceId];
|
|
130
194
|
if (!paramMgrProcessor) return;
|
|
131
195
|
if (paramMgrProcessor.handleEvent) return;
|
|
132
196
|
paramMgrProcessor.handleEvent = (event) => {
|
|
133
|
-
if (event.type ===
|
|
197
|
+
if (event.type === 'wam-midi')
|
|
198
|
+
this.midiMessage(event.data.bytes);
|
|
134
199
|
};
|
|
135
200
|
}
|
|
136
201
|
|
|
137
|
-
process(
|
|
138
|
-
|
|
202
|
+
process(
|
|
203
|
+
inputs: Float32Array[][],
|
|
204
|
+
outputs: Float32Array[][],
|
|
205
|
+
parameters: { [key: string]: Float32Array }
|
|
206
|
+
) {
|
|
139
207
|
// Update controls (possibly needed for sample accurate control)
|
|
140
208
|
for (const path in parameters) {
|
|
141
209
|
const [paramValue] = parameters[path];
|
|
@@ -163,59 +231,67 @@ const getFaustAudioWorkletProcessor = <Poly extends boolean = false>(dependencie
|
|
|
163
231
|
return this.fDSPCode.compute(inputs[0], outputs[0]);
|
|
164
232
|
}
|
|
165
233
|
|
|
166
|
-
protected handleMessageAux(e: MessageEvent) {
|
|
234
|
+
protected handleMessageAux(e: MessageEvent) {
|
|
235
|
+
// use arrow function for binding
|
|
167
236
|
const msg = e.data;
|
|
168
237
|
|
|
169
238
|
switch (msg.type) {
|
|
170
239
|
// Generic MIDI message
|
|
171
|
-
case
|
|
240
|
+
case 'midi': {
|
|
172
241
|
this.midiMessage(msg.data);
|
|
173
242
|
break;
|
|
174
243
|
}
|
|
175
244
|
// Typed MIDI message
|
|
176
|
-
case
|
|
245
|
+
case 'ctrlChange': {
|
|
177
246
|
this.ctrlChange(msg.data[0], msg.data[1], msg.data[2]);
|
|
178
247
|
break;
|
|
179
248
|
}
|
|
180
|
-
case
|
|
249
|
+
case 'pitchWheel': {
|
|
181
250
|
this.pitchWheel(msg.data[0], msg.data[1]);
|
|
182
251
|
break;
|
|
183
252
|
}
|
|
184
|
-
case
|
|
253
|
+
case 'keyOn': {
|
|
185
254
|
this.keyOn(msg.data[0], msg.data[1], msg.data[2]);
|
|
186
255
|
break;
|
|
187
256
|
}
|
|
188
|
-
case
|
|
257
|
+
case 'keyOff': {
|
|
189
258
|
this.keyOff(msg.data[0], msg.data[1], msg.data[2]);
|
|
190
259
|
break;
|
|
191
260
|
}
|
|
192
261
|
// Generic data message
|
|
193
|
-
case
|
|
262
|
+
case 'param': {
|
|
194
263
|
this.setParamValue(msg.data.path, msg.data.value);
|
|
195
264
|
break;
|
|
196
265
|
}
|
|
197
266
|
// Plot handler set on demand
|
|
198
|
-
case
|
|
267
|
+
case 'setPlotHandler': {
|
|
199
268
|
if (msg.data) {
|
|
200
|
-
this.fDSPCode.setPlotHandler((output, index, events) =>
|
|
269
|
+
this.fDSPCode.setPlotHandler((output, index, events) =>
|
|
270
|
+
this.port.postMessage({
|
|
271
|
+
type: 'plot',
|
|
272
|
+
value: output,
|
|
273
|
+
index,
|
|
274
|
+
events
|
|
275
|
+
})
|
|
276
|
+
);
|
|
201
277
|
} else {
|
|
202
278
|
this.fDSPCode.setPlotHandler(null);
|
|
203
279
|
}
|
|
204
280
|
break;
|
|
205
281
|
}
|
|
206
|
-
case
|
|
282
|
+
case 'setupWamEventHandler': {
|
|
207
283
|
this.setupWamEventHandler();
|
|
208
284
|
break;
|
|
209
285
|
}
|
|
210
|
-
case
|
|
286
|
+
case 'start': {
|
|
211
287
|
this.fDSPCode.start();
|
|
212
288
|
break;
|
|
213
289
|
}
|
|
214
|
-
case
|
|
290
|
+
case 'stop': {
|
|
215
291
|
this.fDSPCode.stop();
|
|
216
292
|
break;
|
|
217
293
|
}
|
|
218
|
-
case
|
|
294
|
+
case 'destroy': {
|
|
219
295
|
this.port.close();
|
|
220
296
|
this.fDSPCode.destroy();
|
|
221
297
|
break;
|
|
@@ -250,11 +326,18 @@ const getFaustAudioWorkletProcessor = <Poly extends boolean = false>(dependencie
|
|
|
250
326
|
this.fDSPCode.keyOff(channel, pitch, velocity);
|
|
251
327
|
}
|
|
252
328
|
|
|
253
|
-
protected propagateAcc(
|
|
329
|
+
protected propagateAcc(
|
|
330
|
+
accelerationIncludingGravity: NonNullable<
|
|
331
|
+
DeviceMotionEvent['accelerationIncludingGravity']
|
|
332
|
+
>,
|
|
333
|
+
invert: boolean = false
|
|
334
|
+
) {
|
|
254
335
|
this.fDSPCode.propagateAcc(accelerationIncludingGravity, invert);
|
|
255
336
|
}
|
|
256
337
|
|
|
257
|
-
protected propagateGyr(
|
|
338
|
+
protected propagateGyr(
|
|
339
|
+
event: Pick<DeviceOrientationEvent, 'alpha' | 'beta' | 'gamma'>
|
|
340
|
+
) {
|
|
258
341
|
this.fDSPCode.propagateGyr(event);
|
|
259
342
|
}
|
|
260
343
|
}
|
|
@@ -263,55 +346,87 @@ const getFaustAudioWorkletProcessor = <Poly extends boolean = false>(dependencie
|
|
|
263
346
|
* Monophonic AudioWorkletProcessor
|
|
264
347
|
*/
|
|
265
348
|
class FaustMonoAudioWorkletProcessor extends FaustAudioWorkletProcessor<false> {
|
|
266
|
-
|
|
267
349
|
constructor(options: FaustAudioWorkletNodeOptions) {
|
|
268
350
|
super(options);
|
|
269
|
-
const { FaustMonoWebAudioDsp } =
|
|
351
|
+
const { FaustMonoWebAudioDsp } =
|
|
352
|
+
dependencies as FaustAudioWorkletProcessorDependencies<false>;
|
|
270
353
|
const { factory, sampleSize } = options.processorOptions;
|
|
271
354
|
|
|
272
|
-
const instance =
|
|
355
|
+
const instance =
|
|
356
|
+
FaustWasmInstantiator.createSyncMonoDSPInstance(factory);
|
|
273
357
|
|
|
274
358
|
// Create Monophonic DSP
|
|
275
|
-
this.fDSPCode = new FaustMonoWebAudioDsp(
|
|
359
|
+
this.fDSPCode = new FaustMonoWebAudioDsp(
|
|
360
|
+
instance,
|
|
361
|
+
sampleRate,
|
|
362
|
+
sampleSize,
|
|
363
|
+
128,
|
|
364
|
+
factory.soundfiles
|
|
365
|
+
);
|
|
276
366
|
|
|
277
367
|
// Setup port message handling
|
|
278
|
-
this.port.addEventListener(
|
|
368
|
+
this.port.addEventListener('message', this.handleMessageAux);
|
|
279
369
|
this.port.start();
|
|
280
370
|
|
|
281
371
|
// Setup output handler
|
|
282
|
-
this.fDSPCode.setOutputParamHandler((path, value) =>
|
|
372
|
+
this.fDSPCode.setOutputParamHandler((path, value) =>
|
|
373
|
+
this.port.postMessage({ path, value, type: 'param' })
|
|
374
|
+
);
|
|
283
375
|
|
|
284
376
|
this.fDSPCode.start();
|
|
285
377
|
}
|
|
286
378
|
|
|
287
|
-
protected handleMessageAux = (e: MessageEvent) => {
|
|
379
|
+
protected handleMessageAux = (e: MessageEvent) => {
|
|
380
|
+
// use arrow function for binding
|
|
288
381
|
super.handleMessageAux(e);
|
|
289
|
-
}
|
|
382
|
+
};
|
|
290
383
|
}
|
|
291
384
|
|
|
292
385
|
/**
|
|
293
386
|
* Polyphonic AudioWorkletProcessor
|
|
294
387
|
*/
|
|
295
388
|
class FaustPolyAudioWorkletProcessor extends FaustAudioWorkletProcessor<true> {
|
|
296
|
-
|
|
297
389
|
constructor(options: FaustPolyAudioWorkletNodeOptions) {
|
|
298
390
|
super(options);
|
|
299
|
-
const { FaustPolyWebAudioDsp } =
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
391
|
+
const { FaustPolyWebAudioDsp } =
|
|
392
|
+
dependencies as FaustAudioWorkletProcessorDependencies<true>;
|
|
393
|
+
|
|
394
|
+
const {
|
|
395
|
+
voiceFactory,
|
|
396
|
+
mixerModule,
|
|
397
|
+
voices,
|
|
398
|
+
effectFactory,
|
|
399
|
+
sampleSize
|
|
400
|
+
} = options.processorOptions;
|
|
401
|
+
|
|
402
|
+
const instance = FaustWasmInstantiator.createSyncPolyDSPInstance(
|
|
403
|
+
voiceFactory,
|
|
404
|
+
mixerModule,
|
|
405
|
+
voices,
|
|
406
|
+
effectFactory
|
|
407
|
+
);
|
|
408
|
+
|
|
409
|
+
const soundfiles = {
|
|
410
|
+
...effectFactory?.soundfiles,
|
|
411
|
+
...voiceFactory.soundfiles
|
|
412
|
+
};
|
|
306
413
|
// Create Polyphonic DSP
|
|
307
|
-
this.fDSPCode = new FaustPolyWebAudioDsp(
|
|
414
|
+
this.fDSPCode = new FaustPolyWebAudioDsp(
|
|
415
|
+
instance,
|
|
416
|
+
sampleRate,
|
|
417
|
+
sampleSize,
|
|
418
|
+
128,
|
|
419
|
+
soundfiles
|
|
420
|
+
);
|
|
308
421
|
|
|
309
422
|
// Setup port message handling
|
|
310
|
-
this.port.addEventListener(
|
|
423
|
+
this.port.addEventListener('message', this.handleMessageAux);
|
|
311
424
|
this.port.start();
|
|
312
425
|
|
|
313
426
|
// Setup output handler
|
|
314
|
-
this.fDSPCode.setOutputParamHandler((path, value) =>
|
|
427
|
+
this.fDSPCode.setOutputParamHandler((path, value) =>
|
|
428
|
+
this.port.postMessage({ path, value, type: 'param' })
|
|
429
|
+
);
|
|
315
430
|
|
|
316
431
|
this.fDSPCode.start();
|
|
317
432
|
}
|
|
@@ -321,21 +436,27 @@ const getFaustAudioWorkletProcessor = <Poly extends boolean = false>(dependencie
|
|
|
321
436
|
const channel = data[0] & 0xf;
|
|
322
437
|
const data1 = data[1];
|
|
323
438
|
const data2 = data[2];
|
|
324
|
-
if (cmd === 8 || (cmd === 9 && data2 === 0))
|
|
439
|
+
if (cmd === 8 || (cmd === 9 && data2 === 0))
|
|
440
|
+
this.keyOff(channel, data1, data2);
|
|
325
441
|
else if (cmd === 9) this.keyOn(channel, data1, data2);
|
|
326
442
|
else super.midiMessage(data);
|
|
327
443
|
}
|
|
328
444
|
|
|
329
|
-
protected handleMessageAux = (e: MessageEvent) => {
|
|
445
|
+
protected handleMessageAux = (e: MessageEvent) => {
|
|
446
|
+
// use arrow function for binding
|
|
330
447
|
const msg = e.data;
|
|
331
448
|
switch (msg.type) {
|
|
332
|
-
case
|
|
333
|
-
|
|
449
|
+
case 'keyOn':
|
|
450
|
+
this.keyOn(msg.data[0], msg.data[1], msg.data[2]);
|
|
451
|
+
break;
|
|
452
|
+
case 'keyOff':
|
|
453
|
+
this.keyOff(msg.data[0], msg.data[1], msg.data[2]);
|
|
454
|
+
break;
|
|
334
455
|
default:
|
|
335
456
|
super.handleMessageAux(e);
|
|
336
457
|
break;
|
|
337
458
|
}
|
|
338
|
-
}
|
|
459
|
+
};
|
|
339
460
|
|
|
340
461
|
// Public API
|
|
341
462
|
keyOn(channel: number, pitch: number, velocity: number) {
|
|
@@ -351,16 +472,23 @@ const getFaustAudioWorkletProcessor = <Poly extends boolean = false>(dependencie
|
|
|
351
472
|
}
|
|
352
473
|
}
|
|
353
474
|
|
|
354
|
-
const Processor = poly
|
|
475
|
+
const Processor = poly
|
|
476
|
+
? FaustPolyAudioWorkletProcessor
|
|
477
|
+
: FaustMonoAudioWorkletProcessor;
|
|
355
478
|
if (register) {
|
|
356
479
|
try {
|
|
357
|
-
registerProcessor(
|
|
480
|
+
registerProcessor(
|
|
481
|
+
processorName || dspName || (poly ? 'mydsp_poly' : 'mydsp'),
|
|
482
|
+
Processor
|
|
483
|
+
);
|
|
358
484
|
} catch (error) {
|
|
359
485
|
console.warn(error);
|
|
360
486
|
}
|
|
361
487
|
}
|
|
362
488
|
|
|
363
|
-
return poly
|
|
364
|
-
|
|
489
|
+
return poly
|
|
490
|
+
? FaustPolyAudioWorkletProcessor
|
|
491
|
+
: FaustMonoAudioWorkletProcessor;
|
|
492
|
+
};
|
|
365
493
|
|
|
366
494
|
export default getFaustAudioWorkletProcessor;
|
package/src/FaustCmajor.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type FaustCompiler from
|
|
1
|
+
import type FaustCompiler from './FaustCompiler';
|
|
2
2
|
|
|
3
3
|
interface IFaustCmajor {
|
|
4
4
|
/**
|
|
@@ -21,8 +21,14 @@ class FaustCmajor implements IFaustCmajor {
|
|
|
21
21
|
|
|
22
22
|
compile(name: string, code: string, args: string) {
|
|
23
23
|
const fs = this.fCompiler.fs();
|
|
24
|
-
const success = this.fCompiler.generateAuxFiles(
|
|
25
|
-
|
|
24
|
+
const success = this.fCompiler.generateAuxFiles(
|
|
25
|
+
name,
|
|
26
|
+
code,
|
|
27
|
+
`-lang cmajor-hybrid -cn ${name} -o ${name}.cmajor`
|
|
28
|
+
);
|
|
29
|
+
return success
|
|
30
|
+
? (fs.readFile(`${name}.cmajor`, { encoding: 'utf8' }) as string)
|
|
31
|
+
: '';
|
|
26
32
|
}
|
|
27
33
|
}
|
|
28
34
|
|