@grame/faustwasm 0.7.9 → 0.8.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/README.md +2 -2
- package/assets/standalone/faustwasm/index.d.ts +76 -9
- package/assets/standalone/faustwasm/index.js +270 -77
- package/assets/standalone/faustwasm/index.js.map +4 -4
- package/assets/standalone/index-pwa.js +7 -8
- package/assets/standalone/index-template.js +2 -2
- package/assets/standalone/index.js +59 -61
- package/assets/standalone/service-worker.js +47 -8
- package/dist/cjs/index.d.ts +76 -9
- package/dist/cjs/index.js +270 -77
- package/dist/cjs/index.js.map +4 -4
- package/dist/cjs-bundle/index.d.ts +76 -9
- package/dist/cjs-bundle/index.js +271 -78
- package/dist/cjs-bundle/index.js.map +4 -4
- package/dist/esm/index.d.ts +76 -9
- package/dist/esm/index.js +270 -77
- package/dist/esm/index.js.map +4 -4
- package/dist/esm-bundle/index.d.ts +76 -9
- package/dist/esm-bundle/index.js +271 -78
- package/dist/esm-bundle/index.js.map +4 -4
- package/libfaust-wasm/libfaust-wasm.wasm +0 -0
- package/package.json +1 -1
- package/src/FaustAudioWorkletCommunicator.ts +143 -0
- package/src/FaustAudioWorkletNode.ts +23 -12
- package/src/FaustAudioWorkletProcessor.ts +34 -15
- package/src/FaustDspGenerator.ts +20 -2
- package/src/FaustFFTAudioWorkletProcessor.ts +31 -2
- package/src/FaustOfflineProcessor.ts +6 -0
- package/src/FaustScriptProcessorNode.ts +4 -1
- package/src/FaustWebAudioDsp.ts +38 -10
- package/test/faustlive-wasm/faustwasm/index.d.ts +76 -9
- package/test/faustlive-wasm/faustwasm/index.js +270 -77
- package/test/faustlive-wasm/faustwasm/index.js.map +4 -4
- package/assets/standalone/coi-serviceworker.js +0 -146
|
Binary file
|
package/package.json
CHANGED
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
|
|
2
|
+
/**
|
|
3
|
+
* Layout:
|
|
4
|
+
*
|
|
5
|
+
*
|
|
6
|
+
* invert-isAndroid (uint8)
|
|
7
|
+
* new-acc-data-available (uint8)
|
|
8
|
+
* new-gyr-data-available (uint8)
|
|
9
|
+
* empty (uint8)
|
|
10
|
+
*
|
|
11
|
+
* acc.x, acc.y, acc.z (f32)
|
|
12
|
+
*
|
|
13
|
+
* gyr.alpha, gyr.beta, gyr.gamma (f32)
|
|
14
|
+
*/
|
|
15
|
+
export class FaustAudioWorkletCommunicator {
|
|
16
|
+
protected readonly port: MessagePort;
|
|
17
|
+
protected readonly supportSharedArrayBuffer: boolean;
|
|
18
|
+
protected readonly byteLength: number;
|
|
19
|
+
protected uin8Invert: Uint8ClampedArray;
|
|
20
|
+
protected uin8NewAccData: Uint8ClampedArray;
|
|
21
|
+
protected uin8NewGyrData: Uint8ClampedArray;
|
|
22
|
+
protected f32Acc: Float32Array;
|
|
23
|
+
protected f32Gyr: Float32Array;
|
|
24
|
+
constructor(port: MessagePort) {
|
|
25
|
+
this.port = port;
|
|
26
|
+
this.supportSharedArrayBuffer = !!globalThis.SharedArrayBuffer;
|
|
27
|
+
this.byteLength
|
|
28
|
+
= 4 * Uint8Array.BYTES_PER_ELEMENT
|
|
29
|
+
+ 3 * Float32Array.BYTES_PER_ELEMENT
|
|
30
|
+
+ 3 * Float32Array.BYTES_PER_ELEMENT;
|
|
31
|
+
}
|
|
32
|
+
initializeBuffer(ab: SharedArrayBuffer | ArrayBuffer) {
|
|
33
|
+
let ptr = 0;
|
|
34
|
+
this.uin8Invert = new Uint8ClampedArray(ab, ptr, 1);
|
|
35
|
+
ptr += Uint8ClampedArray.BYTES_PER_ELEMENT;
|
|
36
|
+
this.uin8NewAccData = new Uint8ClampedArray(ab, ptr, 1);
|
|
37
|
+
ptr += Uint8ClampedArray.BYTES_PER_ELEMENT;
|
|
38
|
+
this.uin8NewGyrData = new Uint8ClampedArray(ab, ptr, 1);
|
|
39
|
+
ptr += Uint8ClampedArray.BYTES_PER_ELEMENT;
|
|
40
|
+
ptr += Uint8ClampedArray.BYTES_PER_ELEMENT;; // empty
|
|
41
|
+
this.f32Acc = new Float32Array(ab, ptr, 3);
|
|
42
|
+
ptr += 3 * Float32Array.BYTES_PER_ELEMENT;
|
|
43
|
+
this.f32Gyr = new Float32Array(ab, ptr, 3);
|
|
44
|
+
ptr += 3 * Float32Array.BYTES_PER_ELEMENT;
|
|
45
|
+
}
|
|
46
|
+
setNewAccDataAvailable(value: boolean) {
|
|
47
|
+
if (!this.uin8NewAccData) return;
|
|
48
|
+
this.uin8NewAccData[0] = +value;
|
|
49
|
+
}
|
|
50
|
+
getNewAccDataAvailable() {
|
|
51
|
+
return !!this.uin8NewAccData?.[0];
|
|
52
|
+
}
|
|
53
|
+
setNewGyrDataAvailable(value: boolean) {
|
|
54
|
+
if (!this.uin8NewGyrData) return;
|
|
55
|
+
this.uin8NewGyrData[0] = +value;
|
|
56
|
+
}
|
|
57
|
+
getNewGyrDataAvailable() {
|
|
58
|
+
return !!this.uin8NewGyrData?.[0];
|
|
59
|
+
}
|
|
60
|
+
setAcc({ x, y, z }: { x: number, y: number, z: number }, invert = false) {
|
|
61
|
+
if (!this.supportSharedArrayBuffer) {
|
|
62
|
+
const e = { type: "acc", data: { x, y, z }, invert };
|
|
63
|
+
this.port.postMessage(e);
|
|
64
|
+
}
|
|
65
|
+
if (!this.uin8NewAccData) return;
|
|
66
|
+
this.uin8Invert[0] = +invert;
|
|
67
|
+
this.f32Acc[0] = x;
|
|
68
|
+
this.f32Acc[1] = y;
|
|
69
|
+
this.f32Acc[2] = z;
|
|
70
|
+
this.uin8NewAccData[0] = 1;
|
|
71
|
+
}
|
|
72
|
+
getAcc() {
|
|
73
|
+
if (!this.uin8NewAccData) return;
|
|
74
|
+
const invert = !!this.uin8Invert[0];
|
|
75
|
+
const [x, y, z] = this.f32Acc;
|
|
76
|
+
return { x, y, z, invert };
|
|
77
|
+
}
|
|
78
|
+
setGyr({ alpha, beta, gamma }: { alpha: number, beta: number, gamma: number }) {
|
|
79
|
+
if (!this.supportSharedArrayBuffer) {
|
|
80
|
+
const e = { type: "gyr", data: { alpha, beta, gamma } };
|
|
81
|
+
this.port.postMessage(e);
|
|
82
|
+
}
|
|
83
|
+
if (!this.uin8NewGyrData) return;
|
|
84
|
+
this.f32Gyr[0] = alpha;
|
|
85
|
+
this.f32Gyr[1] = beta;
|
|
86
|
+
this.f32Gyr[2] = gamma;
|
|
87
|
+
this.uin8NewGyrData[0] = 1;
|
|
88
|
+
}
|
|
89
|
+
getGyr() {
|
|
90
|
+
if (!this.uin8NewGyrData) return;
|
|
91
|
+
const [alpha, beta, gamma] = this.f32Gyr;
|
|
92
|
+
return { alpha, beta, gamma };
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export class FaustAudioWorkletNodeCommunicator extends FaustAudioWorkletCommunicator {
|
|
97
|
+
constructor(port: MessagePort) {
|
|
98
|
+
super(port);
|
|
99
|
+
if (this.supportSharedArrayBuffer) {
|
|
100
|
+
const sab = new SharedArrayBuffer(this.byteLength);
|
|
101
|
+
this.initializeBuffer(sab);
|
|
102
|
+
this.port.postMessage({ type: "initSab", sab });
|
|
103
|
+
} else {
|
|
104
|
+
const ab = new ArrayBuffer(this.byteLength);
|
|
105
|
+
this.initializeBuffer(ab);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export class FaustAudioWorkletProcessorCommunicator extends FaustAudioWorkletCommunicator {
|
|
111
|
+
constructor(port: MessagePort) {
|
|
112
|
+
super(port);
|
|
113
|
+
|
|
114
|
+
if (this.supportSharedArrayBuffer) {
|
|
115
|
+
this.port.addEventListener("message", (event) => {
|
|
116
|
+
const { data } = event;
|
|
117
|
+
if (data.type === "initSab") {
|
|
118
|
+
this.initializeBuffer(data.sab);
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
} else {
|
|
122
|
+
const ab = new ArrayBuffer(this.byteLength);
|
|
123
|
+
this.initializeBuffer(ab);
|
|
124
|
+
this.port.addEventListener("message", (event) => {
|
|
125
|
+
const msg = event.data;
|
|
126
|
+
|
|
127
|
+
switch (msg.type) {
|
|
128
|
+
// Sensors messages
|
|
129
|
+
case "acc": {
|
|
130
|
+
this.setAcc(msg.data, msg.invert);
|
|
131
|
+
break;
|
|
132
|
+
}
|
|
133
|
+
case "gyr": {
|
|
134
|
+
this.setGyr(msg.data);
|
|
135
|
+
break;
|
|
136
|
+
}
|
|
137
|
+
default:
|
|
138
|
+
break;
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { OutputParamHandler, ComputeHandler, PlotHandler, UIHandler, MetadataHandler, FaustBaseWebAudioDsp, IFaustMonoWebAudioDsp, IFaustPolyWebAudioDsp } from "./FaustWebAudioDsp";
|
|
2
2
|
import type { FaustAudioWorkletNodeOptions } from "./FaustAudioWorkletProcessor";
|
|
3
3
|
import type { LooseFaustDspFactory, FaustDspMeta, FaustUIInputItem, FaustUIItem } from "./types";
|
|
4
|
+
import { FaustAudioWorkletNodeCommunicator } from "./FaustAudioWorkletCommunicator";
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* Base class for Monophonic and Polyphonic AudioWorkletNode
|
|
@@ -15,6 +16,7 @@ export class FaustAudioWorkletNode<Poly extends boolean = false> extends (global
|
|
|
15
16
|
protected fPlotHandler: PlotHandler | null;
|
|
16
17
|
protected fUICallback: UIHandler;
|
|
17
18
|
protected fDescriptor: FaustUIInputItem[];
|
|
19
|
+
protected fCommunicator: FaustAudioWorkletNodeCommunicator;
|
|
18
20
|
#hasAccInput = false;
|
|
19
21
|
#hasGyrInput = false;
|
|
20
22
|
|
|
@@ -60,17 +62,20 @@ export class FaustAudioWorkletNode<Poly extends boolean = false> extends (global
|
|
|
60
62
|
|
|
61
63
|
FaustBaseWebAudioDsp.parseUI(this.fJSONDsp.ui, this.fUICallback);
|
|
62
64
|
|
|
65
|
+
this.fCommunicator = new FaustAudioWorkletNodeCommunicator(this.port);
|
|
66
|
+
|
|
63
67
|
// Patch it with additional functions
|
|
64
|
-
this.port.
|
|
65
|
-
|
|
66
|
-
this.fOutputHandler(e.data.path, e.data.value);
|
|
67
|
-
} else if (e.data.type === "plot" && this.fPlotHandler) {
|
|
68
|
-
this.fPlotHandler(e.data.value, e.data.index, e.data.events);
|
|
69
|
-
}
|
|
70
|
-
};
|
|
68
|
+
this.port.addEventListener("message", this.handleMessageAux);
|
|
69
|
+
this.port.start();
|
|
71
70
|
}
|
|
72
71
|
|
|
73
|
-
|
|
72
|
+
protected handleMessageAux = (e: MessageEvent) => {
|
|
73
|
+
if (e.data.type === "param" && this.fOutputHandler) {
|
|
74
|
+
this.fOutputHandler(e.data.path, e.data.value);
|
|
75
|
+
} else if (e.data.type === "plot" && this.fPlotHandler) {
|
|
76
|
+
this.fPlotHandler(e.data.value, e.data.index, e.data.events);
|
|
77
|
+
}
|
|
78
|
+
};
|
|
74
79
|
|
|
75
80
|
// Accelerometer and gyroscope handlers
|
|
76
81
|
private handleDeviceMotion = ({ accelerationIncludingGravity }: DeviceMotionEvent) => {
|
|
@@ -84,6 +89,8 @@ export class FaustAudioWorkletNode<Poly extends boolean = false> extends (global
|
|
|
84
89
|
this.propagateGyr({ alpha, beta, gamma });
|
|
85
90
|
};
|
|
86
91
|
|
|
92
|
+
// Public API
|
|
93
|
+
|
|
87
94
|
/** Setup accelerometer and gyroscope handlers */
|
|
88
95
|
async startSensors() {
|
|
89
96
|
if (this.hasAccInput) {
|
|
@@ -140,6 +147,7 @@ export class FaustAudioWorkletNode<Poly extends boolean = false> extends (global
|
|
|
140
147
|
window.removeEventListener("deviceorientation", this.handleDeviceOrientation, true);
|
|
141
148
|
}
|
|
142
149
|
}
|
|
150
|
+
|
|
143
151
|
setOutputParamHandler(handler: OutputParamHandler | null) {
|
|
144
152
|
this.fOutputHandler = handler;
|
|
145
153
|
}
|
|
@@ -166,6 +174,7 @@ export class FaustAudioWorkletNode<Poly extends boolean = false> extends (global
|
|
|
166
174
|
getPlotHandler(): PlotHandler | null {
|
|
167
175
|
return this.fPlotHandler;
|
|
168
176
|
}
|
|
177
|
+
|
|
169
178
|
setupWamEventHandler() {
|
|
170
179
|
this.port.postMessage({ type: "setupWamEventHandler" });
|
|
171
180
|
}
|
|
@@ -208,17 +217,19 @@ export class FaustAudioWorkletNode<Poly extends boolean = false> extends (global
|
|
|
208
217
|
}
|
|
209
218
|
|
|
210
219
|
get hasAccInput() { return this.#hasAccInput; }
|
|
220
|
+
|
|
211
221
|
propagateAcc(accelerationIncludingGravity: NonNullable<DeviceMotionEvent["accelerationIncludingGravity"]>, invert: boolean = false) {
|
|
212
222
|
if (!accelerationIncludingGravity) return;
|
|
213
|
-
const
|
|
214
|
-
this.
|
|
223
|
+
const { x, y, z } = accelerationIncludingGravity;
|
|
224
|
+
this.fCommunicator.setAcc({ x: x!, y: y!, z: z! }, invert);
|
|
215
225
|
}
|
|
216
226
|
|
|
217
227
|
get hasGyrInput() { return this.#hasGyrInput; }
|
|
228
|
+
|
|
218
229
|
propagateGyr(event: Pick<DeviceOrientationEvent, "alpha" | "beta" | "gamma">) {
|
|
219
230
|
if (!event) return;
|
|
220
|
-
const
|
|
221
|
-
this.
|
|
231
|
+
const { alpha, beta, gamma } = event;
|
|
232
|
+
this.fCommunicator.setGyr({ alpha: alpha!, beta: beta!, gamma: gamma! });
|
|
222
233
|
}
|
|
223
234
|
|
|
224
235
|
setParamValue(path: string, value: number) {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { FaustAudioWorkletProcessorCommunicator } from "./FaustAudioWorkletCommunicator";
|
|
1
2
|
import type FaustWasmInstantiator from "./FaustWasmInstantiator";
|
|
2
3
|
import type { FaustBaseWebAudioDsp, FaustWebAudioDspVoice, FaustMonoWebAudioDsp, FaustPolyWebAudioDsp } from "./FaustWebAudioDsp";
|
|
3
4
|
import type { AudioParamDescriptor, AudioWorkletGlobalScope, LooseFaustDspFactory, FaustDspMeta, FaustUIItem } from "./types";
|
|
@@ -19,6 +20,7 @@ export interface FaustAudioWorkletProcessorDependencies<Poly extends boolean = f
|
|
|
19
20
|
FaustPolyWebAudioDsp: Poly extends true ? typeof FaustPolyWebAudioDsp : undefined;
|
|
20
21
|
FaustWebAudioDspVoice: Poly extends true ? typeof FaustWebAudioDspVoice : undefined;
|
|
21
22
|
FaustWasmInstantiator: typeof FaustWasmInstantiator;
|
|
23
|
+
FaustAudioWorkletProcessorCommunicator: typeof FaustAudioWorkletProcessorCommunicator;
|
|
22
24
|
}
|
|
23
25
|
export interface FaustAudioWorkletNodeOptions<Poly extends boolean = false> extends AudioWorkletNodeOptions {
|
|
24
26
|
processorOptions: Poly extends true ? FaustPolyAudioWorkletProcessorOptions : FaustMonoAudioWorkletProcessorOptions;
|
|
@@ -52,7 +54,8 @@ const getFaustAudioWorkletProcessor = <Poly extends boolean = false>(dependencie
|
|
|
52
54
|
|
|
53
55
|
const {
|
|
54
56
|
FaustBaseWebAudioDsp,
|
|
55
|
-
FaustWasmInstantiator
|
|
57
|
+
FaustWasmInstantiator,
|
|
58
|
+
FaustAudioWorkletProcessorCommunicator
|
|
56
59
|
} = dependencies;
|
|
57
60
|
|
|
58
61
|
const {
|
|
@@ -79,7 +82,7 @@ const getFaustAudioWorkletProcessor = <Poly extends boolean = false>(dependencie
|
|
|
79
82
|
/**
|
|
80
83
|
* Base class for Monophonic and Polyphonic AudioWorkletProcessor
|
|
81
84
|
*/
|
|
82
|
-
class FaustAudioWorkletProcessor<Poly extends boolean = false> extends AudioWorkletProcessor {
|
|
85
|
+
abstract class FaustAudioWorkletProcessor<Poly extends boolean = false> extends AudioWorkletProcessor {
|
|
83
86
|
|
|
84
87
|
// Use ! syntax when the field is not defined in the constructor
|
|
85
88
|
protected fDSPCode!: Poly extends true ? FaustPolyWebAudioDsp : FaustMonoWebAudioDsp;
|
|
@@ -87,18 +90,19 @@ const getFaustAudioWorkletProcessor = <Poly extends boolean = false>(dependencie
|
|
|
87
90
|
protected paramValuesCache: Record<string, number> = {};
|
|
88
91
|
|
|
89
92
|
protected wamInfo?: { moduleId: string; instanceId: string };
|
|
93
|
+
protected fCommunicator: FaustAudioWorkletProcessorCommunicator;
|
|
90
94
|
|
|
91
95
|
constructor(options: FaustAudioWorkletNodeOptions<Poly>) {
|
|
92
96
|
super(options);
|
|
93
97
|
|
|
94
98
|
// Setup port message handling
|
|
95
|
-
this.
|
|
99
|
+
this.fCommunicator = new FaustAudioWorkletProcessorCommunicator(this.port);
|
|
96
100
|
|
|
97
101
|
const { parameterDescriptors } = (this.constructor as typeof AudioWorkletProcessor);
|
|
98
102
|
parameterDescriptors.forEach((pd) => {
|
|
99
103
|
this.paramValuesCache[pd.name] = pd.defaultValue || 0;
|
|
100
104
|
})
|
|
101
|
-
|
|
105
|
+
|
|
102
106
|
const { moduleId, instanceId } = options.processorOptions;
|
|
103
107
|
if (!moduleId || !instanceId) return;
|
|
104
108
|
this.wamInfo = { moduleId, instanceId };
|
|
@@ -120,7 +124,7 @@ const getFaustAudioWorkletProcessor = <Poly extends boolean = false>(dependencie
|
|
|
120
124
|
setupWamEventHandler() {
|
|
121
125
|
if (!this.wamInfo) return;
|
|
122
126
|
const { moduleId, instanceId } = this.wamInfo;
|
|
123
|
-
|
|
127
|
+
const { webAudioModules } = (globalThis as unknown as WamAudioWorkletGlobalScope);
|
|
124
128
|
const ModuleScope = webAudioModules.getModuleScope(moduleId) as WamParamMgrSDKBaseModuleScope;
|
|
125
129
|
const paramMgrProcessor = ModuleScope?.paramMgrProcessors?.[instanceId];
|
|
126
130
|
if (!paramMgrProcessor) return;
|
|
@@ -140,6 +144,21 @@ const getFaustAudioWorkletProcessor = <Poly extends boolean = false>(dependencie
|
|
|
140
144
|
this.paramValuesCache[path] = paramValue;
|
|
141
145
|
}
|
|
142
146
|
}
|
|
147
|
+
if (this.fCommunicator.getNewAccDataAvailable()) {
|
|
148
|
+
const acc = this.fCommunicator.getAcc();
|
|
149
|
+
if (acc) {
|
|
150
|
+
this.fCommunicator.setNewAccDataAvailable(false);
|
|
151
|
+
const { invert, ...data } = acc;
|
|
152
|
+
this.propagateAcc(data, invert);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
if (this.fCommunicator.getNewGyrDataAvailable()) {
|
|
156
|
+
const gyr = this.fCommunicator.getGyr();
|
|
157
|
+
if (gyr) {
|
|
158
|
+
this.fCommunicator.setNewGyrDataAvailable(false);
|
|
159
|
+
this.propagateGyr(gyr);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
143
162
|
|
|
144
163
|
return this.fDSPCode.compute(inputs[0], outputs[0]);
|
|
145
164
|
}
|
|
@@ -148,15 +167,6 @@ const getFaustAudioWorkletProcessor = <Poly extends boolean = false>(dependencie
|
|
|
148
167
|
const msg = e.data;
|
|
149
168
|
|
|
150
169
|
switch (msg.type) {
|
|
151
|
-
// Sensors messages
|
|
152
|
-
case "acc": {
|
|
153
|
-
this.propagateAcc(msg.data, msg.invert);
|
|
154
|
-
break;
|
|
155
|
-
}
|
|
156
|
-
case "gyr": {
|
|
157
|
-
this.propagateGyr(msg.data);
|
|
158
|
-
break;
|
|
159
|
-
}
|
|
160
170
|
// Generic MIDI message
|
|
161
171
|
case "midi": {
|
|
162
172
|
this.midiMessage(msg.data);
|
|
@@ -248,11 +258,19 @@ const getFaustAudioWorkletProcessor = <Poly extends boolean = false>(dependencie
|
|
|
248
258
|
// Create Monophonic DSP
|
|
249
259
|
this.fDSPCode = new FaustMonoWebAudioDsp(instance, sampleRate, sampleSize, 128, factory.soundfiles);
|
|
250
260
|
|
|
261
|
+
// Setup port message handling
|
|
262
|
+
this.port.addEventListener("message", this.handleMessageAux);
|
|
263
|
+
this.port.start();
|
|
264
|
+
|
|
251
265
|
// Setup output handler
|
|
252
266
|
this.fDSPCode.setOutputParamHandler((path, value) => this.port.postMessage({ path, value, type: "param" }));
|
|
253
267
|
|
|
254
268
|
this.fDSPCode.start();
|
|
255
269
|
}
|
|
270
|
+
|
|
271
|
+
protected handleMessageAux = (e: MessageEvent) => { // use arrow function for binding
|
|
272
|
+
super.handleMessageAux(e);
|
|
273
|
+
}
|
|
256
274
|
}
|
|
257
275
|
|
|
258
276
|
/**
|
|
@@ -273,7 +291,8 @@ const getFaustAudioWorkletProcessor = <Poly extends boolean = false>(dependencie
|
|
|
273
291
|
this.fDSPCode = new FaustPolyWebAudioDsp(instance, sampleRate, sampleSize, 128, soundfiles);
|
|
274
292
|
|
|
275
293
|
// Setup port message handling
|
|
276
|
-
this.port.
|
|
294
|
+
this.port.addEventListener("message", this.handleMessageAux);
|
|
295
|
+
this.port.start();
|
|
277
296
|
|
|
278
297
|
// Setup output handler
|
|
279
298
|
this.fDSPCode.setOutputParamHandler((path, value) => this.port.postMessage({ path, value, type: "param" }));
|
package/src/FaustDspGenerator.ts
CHANGED
|
@@ -10,6 +10,7 @@ import SoundfileReader from "./SoundfileReader";
|
|
|
10
10
|
import FaustSensors from "./FaustSensors";
|
|
11
11
|
import type { IFaustCompiler } from "./FaustCompiler";
|
|
12
12
|
import type { FaustDspFactory, FaustUIDescriptor, FaustDspMeta, FFTUtils, LooseFaustDspFactory, AudioData } from "./types";
|
|
13
|
+
import { FaustAudioWorkletCommunicator, FaustAudioWorkletProcessorCommunicator } from "./FaustAudioWorkletCommunicator";
|
|
13
14
|
|
|
14
15
|
|
|
15
16
|
export interface GeneratorSupportingSoundfiles {
|
|
@@ -294,11 +295,16 @@ var ${WasmAllocator.name} = ${WasmAllocator.toString()}
|
|
|
294
295
|
var WasmAllocator = ${WasmAllocator.name};
|
|
295
296
|
var ${FaustSensors.name} = ${FaustSensors.toString()}
|
|
296
297
|
var FaustSensors = ${FaustSensors.name};
|
|
298
|
+
var ${FaustAudioWorkletCommunicator.name} = ${FaustAudioWorkletCommunicator.toString()}
|
|
299
|
+
var FaustAudioWorkletCommunicator = ${FaustAudioWorkletCommunicator.name};
|
|
300
|
+
var ${FaustAudioWorkletProcessorCommunicator.name} = ${FaustAudioWorkletProcessorCommunicator.toString()}
|
|
301
|
+
var FaustAudioWorkletProcessorCommunicator = ${FaustAudioWorkletProcessorCommunicator.name};
|
|
297
302
|
// Put them in dependencies
|
|
298
303
|
const dependencies = {
|
|
299
304
|
FaustBaseWebAudioDsp,
|
|
300
305
|
FaustMonoWebAudioDsp,
|
|
301
|
-
FaustWasmInstantiator
|
|
306
|
+
FaustWasmInstantiator,
|
|
307
|
+
FaustAudioWorkletProcessorCommunicator
|
|
302
308
|
};
|
|
303
309
|
// Generate the actual AudioWorkletProcessor code
|
|
304
310
|
(${getFaustAudioWorkletProcessor.toString()})(dependencies, faustData);
|
|
@@ -361,12 +367,17 @@ var ${WasmAllocator.name} = ${WasmAllocator.toString()}
|
|
|
361
367
|
var WasmAllocator = ${WasmAllocator.name};
|
|
362
368
|
var ${FaustSensors.name} = ${FaustSensors.toString()}
|
|
363
369
|
var FaustSensors = ${FaustSensors.name};
|
|
370
|
+
var ${FaustAudioWorkletCommunicator.name} = ${FaustAudioWorkletCommunicator.toString()}
|
|
371
|
+
var FaustAudioWorkletCommunicator = ${FaustAudioWorkletCommunicator.name};
|
|
372
|
+
var ${FaustAudioWorkletProcessorCommunicator.name} = ${FaustAudioWorkletProcessorCommunicator.toString()}
|
|
373
|
+
var FaustAudioWorkletProcessorCommunicator = ${FaustAudioWorkletProcessorCommunicator.name};
|
|
364
374
|
var FFTUtils = ${fftUtils.toString()}
|
|
365
375
|
// Put them in dependencies
|
|
366
376
|
const dependencies = {
|
|
367
377
|
FaustBaseWebAudioDsp,
|
|
368
378
|
FaustMonoWebAudioDsp,
|
|
369
379
|
FaustWasmInstantiator,
|
|
380
|
+
FaustAudioWorkletProcessorCommunicator,
|
|
370
381
|
FFTUtils
|
|
371
382
|
};
|
|
372
383
|
// Generate the actual AudioWorkletProcessor code
|
|
@@ -415,6 +426,7 @@ const dependencies = {
|
|
|
415
426
|
FaustBaseWebAudioDsp,
|
|
416
427
|
FaustMonoWebAudioDsp,
|
|
417
428
|
FaustWasmInstantiator,
|
|
429
|
+
FaustAudioWorkletProcessorCommunicator,
|
|
418
430
|
FaustPolyWebAudioDsp: undefined,
|
|
419
431
|
FaustWebAudioDspVoice: undefined,
|
|
420
432
|
}
|
|
@@ -631,11 +643,16 @@ var ${WasmAllocator.name} = ${WasmAllocator.toString()}
|
|
|
631
643
|
var WasmAllocator = ${WasmAllocator.name};
|
|
632
644
|
var ${FaustSensors.name} = ${FaustSensors.toString()}
|
|
633
645
|
var FaustSensors = ${FaustSensors.name};
|
|
646
|
+
var ${FaustAudioWorkletCommunicator.name} = ${FaustAudioWorkletCommunicator.toString()}
|
|
647
|
+
var FaustAudioWorkletCommunicator = ${FaustAudioWorkletCommunicator.name};
|
|
648
|
+
var ${FaustAudioWorkletProcessorCommunicator.name} = ${FaustAudioWorkletProcessorCommunicator.toString()}
|
|
649
|
+
var FaustAudioWorkletProcessorCommunicator = ${FaustAudioWorkletProcessorCommunicator.name};
|
|
634
650
|
// Put them in dependencies
|
|
635
651
|
const dependencies = {
|
|
636
652
|
FaustBaseWebAudioDsp,
|
|
637
653
|
FaustPolyWebAudioDsp,
|
|
638
|
-
FaustWasmInstantiator
|
|
654
|
+
FaustWasmInstantiator,
|
|
655
|
+
FaustAudioWorkletProcessorCommunicator
|
|
639
656
|
};
|
|
640
657
|
// Generate the actual AudioWorkletProcessor code
|
|
641
658
|
(${getFaustAudioWorkletProcessor.toString()})(dependencies, faustData);
|
|
@@ -676,6 +693,7 @@ const dependencies = {
|
|
|
676
693
|
FaustWasmInstantiator,
|
|
677
694
|
FaustPolyWebAudioDsp,
|
|
678
695
|
FaustWebAudioDspVoice,
|
|
696
|
+
FaustAudioWorkletProcessorCommunicator
|
|
679
697
|
};
|
|
680
698
|
// DSP name and JSON string for DSP are generated
|
|
681
699
|
const faustData = {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { FaustAudioWorkletProcessorCommunicator } from "./FaustAudioWorkletCommunicator";
|
|
1
2
|
import type { FaustMonoDspInstance } from "./FaustDspInstance";
|
|
2
3
|
import type FaustWasmInstantiator from "./FaustWasmInstantiator";
|
|
3
4
|
import type { FaustBaseWebAudioDsp, FaustMonoWebAudioDsp, PlotHandler } from "./FaustWebAudioDsp";
|
|
@@ -25,6 +26,7 @@ export interface FaustFFTAudioWorkletProcessorDependencies {
|
|
|
25
26
|
FaustBaseWebAudioDsp: typeof FaustBaseWebAudioDsp;
|
|
26
27
|
FaustMonoWebAudioDsp: typeof FaustMonoWebAudioDsp;
|
|
27
28
|
FaustWasmInstantiator: typeof FaustWasmInstantiator;
|
|
29
|
+
FaustAudioWorkletProcessorCommunicator: typeof FaustAudioWorkletProcessorCommunicator;
|
|
28
30
|
FFTUtils: typeof FFTUtils;
|
|
29
31
|
}
|
|
30
32
|
export interface FaustFFTAudioWorkletNodeOptions extends AudioWorkletNodeOptions {
|
|
@@ -48,6 +50,7 @@ const getFaustFFTAudioWorkletProcessor = (dependencies: FaustFFTAudioWorkletProc
|
|
|
48
50
|
FaustBaseWebAudioDsp,
|
|
49
51
|
FaustWasmInstantiator,
|
|
50
52
|
FaustMonoWebAudioDsp,
|
|
53
|
+
FaustAudioWorkletProcessorCommunicator,
|
|
51
54
|
FFTUtils
|
|
52
55
|
} = dependencies;
|
|
53
56
|
|
|
@@ -127,6 +130,7 @@ const getFaustFFTAudioWorkletProcessor = (dependencies: FaustFFTAudioWorkletProc
|
|
|
127
130
|
protected paramValuesCache: Record<string, number> = {};
|
|
128
131
|
|
|
129
132
|
protected wamInfo?: { moduleId: string; instanceId: string };
|
|
133
|
+
protected communicator: FaustAudioWorkletProcessorCommunicator;
|
|
130
134
|
|
|
131
135
|
private dspInstance!: FaustMonoDspInstance;
|
|
132
136
|
private sampleSize!: number;
|
|
@@ -178,7 +182,9 @@ const getFaustFFTAudioWorkletProcessor = (dependencies: FaustFFTAudioWorkletProc
|
|
|
178
182
|
super(options);
|
|
179
183
|
|
|
180
184
|
// Setup port message handling
|
|
181
|
-
this.port.
|
|
185
|
+
this.port.addEventListener("message", this.handleMessageAux);
|
|
186
|
+
this.port.start();
|
|
187
|
+
this.communicator = new FaustAudioWorkletProcessorCommunicator(this.port);
|
|
182
188
|
|
|
183
189
|
const { parameterDescriptors } = (this.constructor as typeof AudioWorkletProcessor);
|
|
184
190
|
parameterDescriptors.forEach((pd) => {
|
|
@@ -360,6 +366,21 @@ const getFaustFFTAudioWorkletProcessor = (dependencies: FaustFFTAudioWorkletProc
|
|
|
360
366
|
this.paramValuesCache[path] = paramValue;
|
|
361
367
|
}
|
|
362
368
|
}
|
|
369
|
+
if (this.communicator.getNewAccDataAvailable()) {
|
|
370
|
+
const acc = this.communicator.getAcc();
|
|
371
|
+
if (acc) {
|
|
372
|
+
this.communicator.setNewAccDataAvailable(false);
|
|
373
|
+
const { invert, ...data } = acc;
|
|
374
|
+
this.propagateAcc(data, invert);
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
if (this.communicator.getNewGyrDataAvailable()) {
|
|
378
|
+
const gyr = this.communicator.getGyr();
|
|
379
|
+
if (gyr) {
|
|
380
|
+
this.communicator.setNewGyrDataAvailable(false);
|
|
381
|
+
this.propagateGyr(gyr);
|
|
382
|
+
}
|
|
383
|
+
}
|
|
363
384
|
|
|
364
385
|
// Write audio input into fftInput buffer, advance pointers
|
|
365
386
|
if (input?.length) {
|
|
@@ -400,7 +421,7 @@ const getFaustFFTAudioWorkletProcessor = (dependencies: FaustFFTAudioWorkletProc
|
|
|
400
421
|
return true;
|
|
401
422
|
}
|
|
402
423
|
|
|
403
|
-
protected handleMessageAux(e: MessageEvent) { // use arrow function for binding
|
|
424
|
+
protected handleMessageAux = (e: MessageEvent) => { // use arrow function for binding
|
|
404
425
|
const msg = e.data;
|
|
405
426
|
|
|
406
427
|
switch (msg.type) {
|
|
@@ -462,6 +483,14 @@ const getFaustFFTAudioWorkletProcessor = (dependencies: FaustFFTAudioWorkletProc
|
|
|
462
483
|
this.fDSPCode?.pitchWheel(channel, wheel);
|
|
463
484
|
}
|
|
464
485
|
|
|
486
|
+
protected propagateAcc(accelerationIncludingGravity: NonNullable<DeviceMotionEvent["accelerationIncludingGravity"]>, invert: boolean = false) {
|
|
487
|
+
this.fDSPCode.propagateAcc(accelerationIncludingGravity, invert);
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
protected propagateGyr(event: Pick<DeviceOrientationEvent, "alpha" | "beta" | "gamma">) {
|
|
491
|
+
this.fDSPCode.propagateGyr(event);
|
|
492
|
+
}
|
|
493
|
+
|
|
465
494
|
resetFFT(sizeIn: number, overlapIn: number, windowFunctionIn: number, inputChannels: number, outputChannels: number, bufferSize: number) {
|
|
466
495
|
const fftSize = ~~ceil(Math.max(2, sizeIn || 1024), 2);
|
|
467
496
|
const fftOverlap = ~~Math.min(fftSize, Math.max(1, overlapIn));
|
|
@@ -82,15 +82,21 @@ export class FaustOfflineProcessor<Poly extends boolean = false> {
|
|
|
82
82
|
destroy() { this.fDSPCode.destroy(); }
|
|
83
83
|
|
|
84
84
|
get hasAccInput() { return this.fDSPCode.hasAccInput; }
|
|
85
|
+
|
|
85
86
|
propagateAcc(accelerationIncludingGravity: NonNullable<DeviceMotionEvent["accelerationIncludingGravity"]>, invert: boolean = false) {
|
|
86
87
|
this.fDSPCode.propagateAcc(accelerationIncludingGravity, invert);
|
|
87
88
|
}
|
|
88
89
|
|
|
89
90
|
get hasGyrInput() { return this.fDSPCode.hasGyrInput; }
|
|
91
|
+
|
|
90
92
|
propagateGyr(event: Pick<DeviceOrientationEvent, "alpha" | "beta" | "gamma">) {
|
|
91
93
|
this.fDSPCode.propagateGyr(event);
|
|
92
94
|
}
|
|
93
95
|
|
|
96
|
+
startSensors(): void { }
|
|
97
|
+
|
|
98
|
+
stopSensors(): void { }
|
|
99
|
+
|
|
94
100
|
/**
|
|
95
101
|
* Render frames in an array.
|
|
96
102
|
*
|
|
@@ -50,7 +50,7 @@ export class FaustScriptProcessorNode<Poly extends boolean = false> extends (glo
|
|
|
50
50
|
|
|
51
51
|
// Public API
|
|
52
52
|
|
|
53
|
-
/**
|
|
53
|
+
/** Start accelerometer and gyroscope handlers */
|
|
54
54
|
async startSensors() {
|
|
55
55
|
if (this.hasAccInput) {
|
|
56
56
|
if (window.DeviceMotionEvent) {
|
|
@@ -98,6 +98,7 @@ export class FaustScriptProcessorNode<Poly extends boolean = false> extends (glo
|
|
|
98
98
|
}
|
|
99
99
|
}
|
|
100
100
|
|
|
101
|
+
/** Stop accelerometer and gyroscope handlers */
|
|
101
102
|
stopSensors() {
|
|
102
103
|
if (this.hasAccInput) {
|
|
103
104
|
window.removeEventListener("devicemotion", this.handleDeviceMotion, true);
|
|
@@ -143,11 +144,13 @@ export class FaustScriptProcessorNode<Poly extends boolean = false> extends (glo
|
|
|
143
144
|
destroy() { this.fDSPCode.destroy(); }
|
|
144
145
|
|
|
145
146
|
get hasAccInput() { return this.fDSPCode.hasAccInput; }
|
|
147
|
+
|
|
146
148
|
propagateAcc(accelerationIncludingGravity: NonNullable<DeviceMotionEvent["accelerationIncludingGravity"]>, invert: boolean = false) {
|
|
147
149
|
this.fDSPCode.propagateAcc(accelerationIncludingGravity, invert);
|
|
148
150
|
}
|
|
149
151
|
|
|
150
152
|
get hasGyrInput() { return this.fDSPCode.hasGyrInput; }
|
|
153
|
+
|
|
151
154
|
propagateGyr(event: Pick<DeviceOrientationEvent, "alpha" | "beta" | "gamma">) {
|
|
152
155
|
this.fDSPCode.propagateGyr(event);
|
|
153
156
|
}
|
package/src/FaustWebAudioDsp.ts
CHANGED
|
@@ -496,6 +496,35 @@ export interface IFaustBaseWebAudioDsp {
|
|
|
496
496
|
*/
|
|
497
497
|
getJSON(): string;
|
|
498
498
|
|
|
499
|
+
/**
|
|
500
|
+
* Start accelerometer and gyroscope handlers.
|
|
501
|
+
*/
|
|
502
|
+
startSensors(): void;
|
|
503
|
+
|
|
504
|
+
/**
|
|
505
|
+
* Stop accelerometer and gyroscope handlers.
|
|
506
|
+
*/
|
|
507
|
+
stopSensors(): void;
|
|
508
|
+
|
|
509
|
+
/** Indicating if the DSP handles the accelerometer */
|
|
510
|
+
readonly hasAccInput: boolean;
|
|
511
|
+
|
|
512
|
+
/**
|
|
513
|
+
* Accelerometer handling.
|
|
514
|
+
* accelerationIncludingGravity: DeviceMotionEvent["accelerationIncludingGravity"]
|
|
515
|
+
* invert: boolean
|
|
516
|
+
*/
|
|
517
|
+
propagateAcc(accelerationIncludingGravity: NonNullable<DeviceMotionEvent["accelerationIncludingGravity"]>, invert: boolean): void;
|
|
518
|
+
|
|
519
|
+
/** Indicating if the DSP handles the gyroscope */
|
|
520
|
+
readonly hasGyrInput: boolean;
|
|
521
|
+
|
|
522
|
+
/**
|
|
523
|
+
* Gyroscope handling.
|
|
524
|
+
* event: Pick<DeviceOrientationEvent, "alpha" | "beta" | "gamma">
|
|
525
|
+
*/
|
|
526
|
+
propagateGyr(event: Pick<DeviceOrientationEvent, "alpha" | "beta" | "gamma">): void;
|
|
527
|
+
|
|
499
528
|
/**
|
|
500
529
|
* Start the DSP audio processing.
|
|
501
530
|
*/
|
|
@@ -510,16 +539,6 @@ export interface IFaustBaseWebAudioDsp {
|
|
|
510
539
|
* Destroy the DSP.
|
|
511
540
|
*/
|
|
512
541
|
destroy(): void;
|
|
513
|
-
|
|
514
|
-
/** Indicating if the DSP handles the accelerometer */
|
|
515
|
-
readonly hasAccInput: boolean;
|
|
516
|
-
/** Accelerometer handling */
|
|
517
|
-
propagateAcc(accelerationIncludingGravity: NonNullable<DeviceMotionEvent["accelerationIncludingGravity"]>, invert: boolean): void;
|
|
518
|
-
|
|
519
|
-
/** Indicating if the DSP handles the gyroscope */
|
|
520
|
-
readonly hasGyrInput: boolean;
|
|
521
|
-
/** Gyroscope handling */
|
|
522
|
-
propagateGyr(event: Pick<DeviceOrientationEvent, "alpha" | "beta" | "gamma">): void;
|
|
523
542
|
}
|
|
524
543
|
|
|
525
544
|
export interface IFaustMonoWebAudioDsp extends IFaustBaseWebAudioDsp { }
|
|
@@ -984,6 +1003,14 @@ export class FaustBaseWebAudioDsp implements IFaustBaseWebAudioDsp {
|
|
|
984
1003
|
|
|
985
1004
|
hasSoundfiles() { return this.fSoundfiles.length > 0; }
|
|
986
1005
|
|
|
1006
|
+
startSensors(): void {
|
|
1007
|
+
this.startSensors();
|
|
1008
|
+
}
|
|
1009
|
+
|
|
1010
|
+
stopSensors(): void {
|
|
1011
|
+
this.stopSensors();
|
|
1012
|
+
}
|
|
1013
|
+
|
|
987
1014
|
start() {
|
|
988
1015
|
this.fProcessing = true;
|
|
989
1016
|
}
|
|
@@ -998,6 +1025,7 @@ export class FaustBaseWebAudioDsp implements IFaustBaseWebAudioDsp {
|
|
|
998
1025
|
this.fComputeHandler = null;
|
|
999
1026
|
this.fPlotHandler = null;
|
|
1000
1027
|
}
|
|
1028
|
+
|
|
1001
1029
|
}
|
|
1002
1030
|
|
|
1003
1031
|
export class FaustMonoWebAudioDsp extends FaustBaseWebAudioDsp implements IFaustMonoWebAudioDsp {
|