@grame/faustwasm 0.2.2 → 0.3.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 -0
- package/assets/standalone/faustwasm/index.d.ts +49 -8
- package/assets/standalone/faustwasm/index.js +538 -15
- package/assets/standalone/faustwasm/index.js.map +3 -3
- package/assets/standalone/index.js +17 -11
- package/dist/cjs/index.d.ts +49 -8
- package/dist/cjs/index.js +537 -15
- package/dist/cjs/index.js.map +3 -3
- package/dist/cjs-bundle/index.d.ts +49 -8
- package/dist/cjs-bundle/index.js +540 -18
- package/dist/cjs-bundle/index.js.map +3 -3
- package/dist/esm/index.d.ts +49 -8
- package/dist/esm/index.js +538 -15
- package/dist/esm/index.js.map +3 -3
- package/dist/esm-bundle/index.d.ts +49 -8
- package/dist/esm-bundle/index.js +540 -18
- package/dist/esm-bundle/index.js.map +3 -3
- package/libfaust-wasm/libfaust-wasm.data +0 -0
- package/libfaust-wasm/libfaust-wasm.js +1 -1
- package/libfaust-wasm/libfaust-wasm.wasm +0 -0
- package/package.json +1 -1
- package/src/FaustAudioWorkletNode.ts +73 -0
- package/src/FaustAudioWorkletProcessor.ts +33 -4
- package/src/FaustDspGenerator.ts +14 -2
- package/src/FaustOfflineProcessor.ts +10 -0
- package/src/FaustScriptProcessorNode.ts +61 -1
- package/src/FaustSensors.ts +370 -0
- package/src/FaustWebAudioDsp.ts +122 -23
- package/test/faustlive-wasm/faustwasm/index.d.ts +49 -8
- package/test/faustlive-wasm/faustwasm/index.js +538 -15
- package/test/faustlive-wasm/faustwasm/index.js.map +3 -3
- package/test/faustlive-wasm/index.js +2 -0
- package/test/mono.dsp +1 -0
- package/test/osc.dsp +4 -2
|
@@ -0,0 +1,370 @@
|
|
|
1
|
+
export interface AccParams {
|
|
2
|
+
isEnabled: boolean;
|
|
3
|
+
acc: string;
|
|
4
|
+
address: string;
|
|
5
|
+
min: number;
|
|
6
|
+
max: number;
|
|
7
|
+
init: number;
|
|
8
|
+
label: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/** Enum describing the axis of the accelerometer or gyroscope */
|
|
12
|
+
export enum Axis { x, y, z }
|
|
13
|
+
|
|
14
|
+
/** Enum describing the curve of the accelerometer */
|
|
15
|
+
export enum Curve { Up, Down, UpDown, DownUp }
|
|
16
|
+
|
|
17
|
+
/** Object describing value off accelerometer metadata values */
|
|
18
|
+
class AccMeta {
|
|
19
|
+
axis: Axis;
|
|
20
|
+
curve: Curve;
|
|
21
|
+
amin: number;
|
|
22
|
+
amid: number;
|
|
23
|
+
amax: number;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
interface Range {
|
|
27
|
+
fLo: number;
|
|
28
|
+
fHi: number;
|
|
29
|
+
clip(x: number): number;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
interface InterpolateObject {
|
|
33
|
+
amin: number;
|
|
34
|
+
amax: number;
|
|
35
|
+
}
|
|
36
|
+
interface Interpolator {
|
|
37
|
+
fRange: Range;
|
|
38
|
+
fCoef: number;
|
|
39
|
+
fOffset: number;
|
|
40
|
+
returnMappedValue(v: number): number;
|
|
41
|
+
getLowHigh(amin: number, amax: number): InterpolateObject;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
interface InterpolateObject3pt {
|
|
45
|
+
amin: number;
|
|
46
|
+
amid: number;
|
|
47
|
+
amax: number;
|
|
48
|
+
}
|
|
49
|
+
interface Interpolator3pt {
|
|
50
|
+
fSegment1: Interpolator;
|
|
51
|
+
fSegment2: Interpolator;
|
|
52
|
+
fMid: number;
|
|
53
|
+
returnMappedValue(v: number): number;
|
|
54
|
+
getMappingValues(amin: number, amid: number, amax: number): InterpolateObject3pt;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* ValueConverter interface
|
|
59
|
+
*/
|
|
60
|
+
interface ValueConverter {
|
|
61
|
+
uiToFaust(x: number): number;
|
|
62
|
+
faustToUi(x: number): number;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* UpdatableValueConverter interface
|
|
67
|
+
*/
|
|
68
|
+
export interface UpdatableValueConverter extends ValueConverter {
|
|
69
|
+
fActive: boolean;
|
|
70
|
+
|
|
71
|
+
setMappingValues(amin: number, amid: number, amax: number, min: number, init: number, max: number): void;
|
|
72
|
+
getMappingValues(amin: number, amid: number, amax: number): InterpolateObject3pt;
|
|
73
|
+
|
|
74
|
+
setActive(onOff: boolean): void;
|
|
75
|
+
getActive(): boolean;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
export default class FaustSensors {
|
|
81
|
+
/**
|
|
82
|
+
* Function to convert a number to an axis type
|
|
83
|
+
*
|
|
84
|
+
* @param value number
|
|
85
|
+
* @returns axis type
|
|
86
|
+
*/
|
|
87
|
+
static convertToAxis(value: number): Axis {
|
|
88
|
+
switch (value) {
|
|
89
|
+
case 0:
|
|
90
|
+
return Axis.x;
|
|
91
|
+
case 1:
|
|
92
|
+
return Axis.y;
|
|
93
|
+
case 2:
|
|
94
|
+
return Axis.z;
|
|
95
|
+
default:
|
|
96
|
+
console.error("Error: Axis not found value: " + value);
|
|
97
|
+
return Axis.x;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Function to convert a number to a curve type
|
|
102
|
+
*
|
|
103
|
+
* @param value number
|
|
104
|
+
* @returns curve type
|
|
105
|
+
*/
|
|
106
|
+
static convertToCurve(value: number): Curve {
|
|
107
|
+
switch (value) {
|
|
108
|
+
case 0:
|
|
109
|
+
return Curve.Up;
|
|
110
|
+
case 1:
|
|
111
|
+
return Curve.Down;
|
|
112
|
+
case 2:
|
|
113
|
+
return Curve.UpDown;
|
|
114
|
+
case 3:
|
|
115
|
+
return Curve.DownUp;
|
|
116
|
+
default:
|
|
117
|
+
console.error("Error: Curve not found value: " + value);
|
|
118
|
+
return Curve.Up;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Converter objects use to map acc and Faust value
|
|
123
|
+
static _Range: new (x: number, y: number) => Range;
|
|
124
|
+
static get Range() {
|
|
125
|
+
if (!this._Range) {
|
|
126
|
+
this._Range = class {
|
|
127
|
+
fLo: number;
|
|
128
|
+
fHi: number;
|
|
129
|
+
|
|
130
|
+
constructor(x: number, y: number) {
|
|
131
|
+
this.fLo = Math.min(x, y);
|
|
132
|
+
this.fHi = Math.max(x, y);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
clip(x: number): number {
|
|
136
|
+
if (x < this.fLo) return this.fLo;
|
|
137
|
+
if (x > this.fHi) return this.fHi;
|
|
138
|
+
return x;
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
return this._Range;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
static _Interpolator: new (lo: number, hi: number, v1: number, v2: number) => Interpolator;
|
|
146
|
+
/**
|
|
147
|
+
* Interpolator class
|
|
148
|
+
*/
|
|
149
|
+
static get Interpolator() {
|
|
150
|
+
if (!this._Interpolator) {
|
|
151
|
+
this._Interpolator = class {
|
|
152
|
+
fRange: Range;
|
|
153
|
+
fCoef: number;
|
|
154
|
+
fOffset: number;
|
|
155
|
+
|
|
156
|
+
constructor(lo: number, hi: number, v1: number, v2: number) {
|
|
157
|
+
this.fRange = new FaustSensors.Range(lo, hi);
|
|
158
|
+
if (hi !== lo) {
|
|
159
|
+
// regular case
|
|
160
|
+
this.fCoef = (v2 - v1) / (hi - lo);
|
|
161
|
+
this.fOffset = v1 - lo * this.fCoef;
|
|
162
|
+
} else {
|
|
163
|
+
// degenerate case, avoids division by zero
|
|
164
|
+
this.fCoef = 0;
|
|
165
|
+
this.fOffset = (v1 + v2) / 2;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
returnMappedValue(v: number): number {
|
|
169
|
+
var x = this.fRange.clip(v);
|
|
170
|
+
return this.fOffset + x * this.fCoef;
|
|
171
|
+
}
|
|
172
|
+
getLowHigh(amin: number, amax: number): InterpolateObject {
|
|
173
|
+
return { amin: this.fRange.fLo, amax: this.fRange.fHi };
|
|
174
|
+
}
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
return this._Interpolator;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
static _Interpolator3pt: new (lo: number, mid: number, hi: number, v1: number, vMid: number, v2: number) => Interpolator3pt;
|
|
181
|
+
/**
|
|
182
|
+
* Interpolator3pt class, combine two interpolators
|
|
183
|
+
*/
|
|
184
|
+
static get Interpolator3pt() {
|
|
185
|
+
if (!this._Interpolator3pt) {
|
|
186
|
+
this._Interpolator3pt = class {
|
|
187
|
+
|
|
188
|
+
fSegment1: Interpolator;
|
|
189
|
+
fSegment2: Interpolator;
|
|
190
|
+
fMid: number;
|
|
191
|
+
|
|
192
|
+
constructor(lo: number, mid: number, hi: number, v1: number, vMid: number, v2: number) {
|
|
193
|
+
this.fSegment1 = new FaustSensors.Interpolator(lo, mid, v1, vMid);
|
|
194
|
+
this.fSegment2 = new FaustSensors.Interpolator(mid, hi, vMid, v2);
|
|
195
|
+
this.fMid = mid;
|
|
196
|
+
}
|
|
197
|
+
returnMappedValue(x: number): number {
|
|
198
|
+
return (x < this.fMid) ? this.fSegment1.returnMappedValue(x) : this.fSegment2.returnMappedValue(x);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
getMappingValues(amin: number, amid: number, amax: number): InterpolateObject3pt {
|
|
202
|
+
var lowHighSegment1 = this.fSegment1.getLowHigh(amin, amid);
|
|
203
|
+
var lowHighSegment2 = this.fSegment2.getLowHigh(amid, amax);
|
|
204
|
+
return { amin: lowHighSegment1.amin, amid: lowHighSegment2.amin, amax: lowHighSegment2.amax };
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
}
|
|
209
|
+
return this._Interpolator3pt;
|
|
210
|
+
}
|
|
211
|
+
static _UpConverter: new (amin: number, amid: number, amax: number, fmin: number, fmid: number, fmax: number) => UpdatableValueConverter;
|
|
212
|
+
/**
|
|
213
|
+
* UpConverter class, convert accelerometer value to Faust value
|
|
214
|
+
*/
|
|
215
|
+
static get UpConverter() {
|
|
216
|
+
if (!this._UpConverter) {
|
|
217
|
+
this._UpConverter = class implements UpdatableValueConverter {
|
|
218
|
+
|
|
219
|
+
fA2F: Interpolator3pt;
|
|
220
|
+
fF2A: Interpolator3pt;
|
|
221
|
+
fActive: boolean = true;
|
|
222
|
+
|
|
223
|
+
constructor(amin: number, amid: number, amax: number, fmin: number, fmid: number, fmax: number) {
|
|
224
|
+
this.fA2F = new FaustSensors.Interpolator3pt(amin, amid, amax, fmin, fmid, fmax);
|
|
225
|
+
this.fF2A = new FaustSensors.Interpolator3pt(fmin, fmid, fmax, amin, amid, amax);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
uiToFaust(x: number) { return this.fA2F.returnMappedValue(x) }
|
|
229
|
+
faustToUi(x: number) { return this.fF2A.returnMappedValue(x) }
|
|
230
|
+
|
|
231
|
+
setMappingValues(amin: number, amid: number, amax: number, min: number, init: number, max: number): void {
|
|
232
|
+
this.fA2F = new FaustSensors.Interpolator3pt(amin, amid, amax, min, init, max);
|
|
233
|
+
this.fF2A = new FaustSensors.Interpolator3pt(min, init, max, amin, amid, amax);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
getMappingValues(amin: number, amid: number, amax: number): InterpolateObject3pt {
|
|
237
|
+
return this.fA2F.getMappingValues(amin, amid, amax);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
setActive(onOff: boolean): void { this.fActive = onOff }
|
|
241
|
+
getActive(): boolean { return this.fActive }
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
}
|
|
245
|
+
return this._UpConverter;
|
|
246
|
+
}
|
|
247
|
+
static _DownConverter: new (amin: number, amid: number, amax: number, fmin: number, fmid: number, fmax: number) => UpdatableValueConverter;
|
|
248
|
+
/**
|
|
249
|
+
* DownConverter class, convert accelerometer value to Faust value
|
|
250
|
+
*/
|
|
251
|
+
static get DownConverter() {
|
|
252
|
+
if (!this._DownConverter) {
|
|
253
|
+
this._DownConverter = class implements UpdatableValueConverter {
|
|
254
|
+
|
|
255
|
+
fA2F: Interpolator3pt;
|
|
256
|
+
fF2A: Interpolator3pt;
|
|
257
|
+
fActive: boolean = true;
|
|
258
|
+
|
|
259
|
+
constructor(amin: number, amid: number, amax: number, fmin: number, fmid: number, fmax: number) {
|
|
260
|
+
this.fA2F = new FaustSensors.Interpolator3pt(amin, amid, amax, fmax, fmid, fmin);
|
|
261
|
+
this.fF2A = new FaustSensors.Interpolator3pt(fmin, fmid, fmax, amax, amid, amin);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
uiToFaust(x: number) { return this.fA2F.returnMappedValue(x) }
|
|
265
|
+
faustToUi(x: number) { return this.fF2A.returnMappedValue(x) }
|
|
266
|
+
|
|
267
|
+
setMappingValues(amin: number, amid: number, amax: number, min: number, init: number, max: number): void {
|
|
268
|
+
this.fA2F = new FaustSensors.Interpolator3pt(amin, amid, amax, max, init, min);
|
|
269
|
+
this.fF2A = new FaustSensors.Interpolator3pt(min, init, max, amax, amid, amin);
|
|
270
|
+
}
|
|
271
|
+
getMappingValues(amin: number, amid: number, amax: number): InterpolateObject3pt {
|
|
272
|
+
return this.fA2F.getMappingValues(amin, amid, amax);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
setActive(onOff: boolean): void { this.fActive = onOff }
|
|
276
|
+
getActive(): boolean { return this.fActive }
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
}
|
|
280
|
+
return this._DownConverter;
|
|
281
|
+
}
|
|
282
|
+
static _UpDownConverter: new (amin: number, amid: number, amax: number, fmin: number, fmid: number, fmax: number) => UpdatableValueConverter;
|
|
283
|
+
/**
|
|
284
|
+
* UpDownConverter class, convert accelerometer value to Faust value
|
|
285
|
+
*/
|
|
286
|
+
static get UpDownConverter() {
|
|
287
|
+
if (!this._UpDownConverter) {
|
|
288
|
+
this._UpDownConverter = class implements UpdatableValueConverter {
|
|
289
|
+
|
|
290
|
+
fA2F: Interpolator3pt;
|
|
291
|
+
fF2A: Interpolator;
|
|
292
|
+
fActive: boolean = true;
|
|
293
|
+
|
|
294
|
+
constructor(amin: number, amid: number, amax: number, fmin: number, fmid: number, fmax: number) {
|
|
295
|
+
this.fA2F = new FaustSensors.Interpolator3pt(amin, amid, amax, fmin, fmax, fmin);
|
|
296
|
+
this.fF2A = new FaustSensors.Interpolator(fmin, fmax, amin, amax);
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
uiToFaust(x: number) { return this.fA2F.returnMappedValue(x) }
|
|
300
|
+
faustToUi(x: number) { return this.fF2A.returnMappedValue(x) }
|
|
301
|
+
|
|
302
|
+
setMappingValues(amin: number, amid: number, amax: number, min: number, init: number, max: number): void {
|
|
303
|
+
this.fA2F = new FaustSensors.Interpolator3pt(amin, amid, amax, min, max, min);
|
|
304
|
+
this.fF2A = new FaustSensors.Interpolator(min, max, amin, amax);
|
|
305
|
+
}
|
|
306
|
+
getMappingValues(amin: number, amid: number, amax: number): InterpolateObject3pt {
|
|
307
|
+
return this.fA2F.getMappingValues(amin, amid, amax);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
setActive(onOff: boolean): void { this.fActive = onOff }
|
|
311
|
+
getActive(): boolean { return this.fActive }
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
}
|
|
315
|
+
return this._UpDownConverter;
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* DownUpConverter class, convert accelerometer value to Faust value
|
|
319
|
+
*/
|
|
320
|
+
static _DownUpConverter: new (amin: number, amid: number, amax: number, fmin: number, fmid: number, fmax: number) => UpdatableValueConverter;
|
|
321
|
+
static get DownUpConverter() {
|
|
322
|
+
if (!this._DownUpConverter) {
|
|
323
|
+
this._DownUpConverter = class implements UpdatableValueConverter {
|
|
324
|
+
|
|
325
|
+
fA2F: Interpolator3pt;
|
|
326
|
+
fF2A: Interpolator;
|
|
327
|
+
fActive: boolean = true;
|
|
328
|
+
|
|
329
|
+
constructor(amin: number, amid: number, amax: number, fmin: number, fmid: number, fmax: number) {
|
|
330
|
+
this.fA2F = new FaustSensors.Interpolator3pt(amin, amid, amax, fmax, fmin, fmax);
|
|
331
|
+
this.fF2A = new FaustSensors.Interpolator(fmin, fmax, amin, amax);
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
uiToFaust(x: number) { return this.fA2F.returnMappedValue(x) }
|
|
335
|
+
faustToUi(x: number) { return this.fF2A.returnMappedValue(x) }
|
|
336
|
+
|
|
337
|
+
setMappingValues(amin: number, amid: number, amax: number, min: number, init: number, max: number): void {
|
|
338
|
+
this.fA2F = new FaustSensors.Interpolator3pt(amin, amid, amax, max, min, max);
|
|
339
|
+
this.fF2A = new FaustSensors.Interpolator(min, max, amin, amax);
|
|
340
|
+
}
|
|
341
|
+
getMappingValues(amin: number, amid: number, amax: number): InterpolateObject3pt {
|
|
342
|
+
return this.fA2F.getMappingValues(amin, amid, amax);
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
setActive(onOff: boolean): void { this.fActive = onOff }
|
|
346
|
+
getActive(): boolean { return this.fActive }
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
return this._DownUpConverter;
|
|
350
|
+
}
|
|
351
|
+
/**
|
|
352
|
+
* Public function to build the accelerometer handler
|
|
353
|
+
*
|
|
354
|
+
* @returns `UpdatableValueConverter` built for the given curve
|
|
355
|
+
*/
|
|
356
|
+
static buildHandler(curve: Curve, amin: number, amid: number, amax: number, min: number, init: number, max: number): UpdatableValueConverter {
|
|
357
|
+
switch (curve) {
|
|
358
|
+
case Curve.Up:
|
|
359
|
+
return new FaustSensors.UpConverter(amin, amid, amax, min, init, max);
|
|
360
|
+
case Curve.Down:
|
|
361
|
+
return new FaustSensors.DownConverter(amin, amid, amax, min, init, max);
|
|
362
|
+
case Curve.UpDown:
|
|
363
|
+
return new FaustSensors.UpDownConverter(amin, amid, amax, min, init, max);
|
|
364
|
+
case Curve.DownUp:
|
|
365
|
+
return new FaustSensors.DownUpConverter(amin, amid, amax, min, init, max);
|
|
366
|
+
default:
|
|
367
|
+
return new FaustSensors.UpConverter(amin, amid, amax, min, init, max);
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
}
|
package/src/FaustWebAudioDsp.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { FaustMonoDspInstance, FaustPolyDspInstance, IFaustDspInstance } from "./FaustDspInstance";
|
|
2
2
|
import type { AudioData, FaustDspMeta, FaustUIDescriptor, FaustUIGroup, FaustUIInputItem, FaustUIItem, LooseFaustDspFactory } from "./types";
|
|
3
|
+
import FaustSensors, { Axis, Curve, UpdatableValueConverter } from "./FaustSensors";
|
|
3
4
|
|
|
4
5
|
// Public API
|
|
5
6
|
export type OutputParamHandler = (path: string, value: number) => void;
|
|
@@ -10,6 +11,16 @@ export type MetadataHandler = (key: string, value: string) => void;
|
|
|
10
11
|
// Implementation API
|
|
11
12
|
export type UIHandler = (item: FaustUIItem) => void;
|
|
12
13
|
|
|
14
|
+
// Accelerometer or gyroscope handler
|
|
15
|
+
export type SensorEventHandler = (val: number) => void;
|
|
16
|
+
|
|
17
|
+
// Define a type for the accelerometer or gyroscope handlers
|
|
18
|
+
export type SensorEventHandlers = {
|
|
19
|
+
x: SensorEventHandler[];
|
|
20
|
+
y: SensorEventHandler[];
|
|
21
|
+
z: SensorEventHandler[];
|
|
22
|
+
};
|
|
23
|
+
|
|
13
24
|
/** Definition of the AudioBufferItem type */
|
|
14
25
|
export interface AudioBufferItem {
|
|
15
26
|
pathName: string;
|
|
@@ -134,16 +145,16 @@ export class WasmAllocator {
|
|
|
134
145
|
export class Soundfile {
|
|
135
146
|
/** Maximum number of soundfile parts. */
|
|
136
147
|
static get MAX_SOUNDFILE_PARTS() { return 256; }
|
|
137
|
-
|
|
148
|
+
|
|
138
149
|
/** Maximum number of channels. */
|
|
139
150
|
static get MAX_CHAN() { return 64; }
|
|
140
|
-
|
|
151
|
+
|
|
141
152
|
/** Maximum buffer size in frames. */
|
|
142
153
|
static get BUFFER_SIZE() { return 1024; }
|
|
143
|
-
|
|
154
|
+
|
|
144
155
|
/** Default sample rate. */
|
|
145
156
|
static get SAMPLE_RATE() { return 44100; }
|
|
146
|
-
|
|
157
|
+
|
|
147
158
|
/** Pointer to the soundfile structure in wasm memory */
|
|
148
159
|
private readonly fPtr: number;
|
|
149
160
|
private readonly fBuffers: number;
|
|
@@ -332,10 +343,10 @@ export class Soundfile {
|
|
|
332
343
|
}
|
|
333
344
|
|
|
334
345
|
/**
|
|
335
|
-
* DSP implementation
|
|
346
|
+
* DSP implementation that mimic the C++ 'dsp' class:
|
|
336
347
|
* - adding MIDI control: metadata are decoded and incoming MIDI messages will control the associated controllers
|
|
337
348
|
* - an output handler can be set to treat produced output controllers (like 'bargraph')
|
|
338
|
-
* - regular controllers are handled using setParamValue/getParamValue
|
|
349
|
+
* - regular controllers are handled using setParamValue/getParamValue and getParams methods
|
|
339
350
|
*/
|
|
340
351
|
export interface IFaustBaseWebAudioDsp {
|
|
341
352
|
/**
|
|
@@ -464,13 +475,6 @@ export interface IFaustBaseWebAudioDsp {
|
|
|
464
475
|
*/
|
|
465
476
|
getMeta(): FaustDspMeta;
|
|
466
477
|
|
|
467
|
-
/**
|
|
468
|
-
* Get DSP JSON description with its UI and metadata.
|
|
469
|
-
*
|
|
470
|
-
* @return the DSP JSON description
|
|
471
|
-
*/
|
|
472
|
-
getJSON(): string;
|
|
473
|
-
|
|
474
478
|
/**
|
|
475
479
|
* Get DSP UI description.
|
|
476
480
|
*
|
|
@@ -485,6 +489,13 @@ export interface IFaustBaseWebAudioDsp {
|
|
|
485
489
|
*/
|
|
486
490
|
getDescriptors(): FaustUIInputItem[];
|
|
487
491
|
|
|
492
|
+
/**
|
|
493
|
+
* Get DSP JSON description with its UI and metadata.
|
|
494
|
+
*
|
|
495
|
+
* @return the DSP JSON description
|
|
496
|
+
*/
|
|
497
|
+
getJSON(): string;
|
|
498
|
+
|
|
488
499
|
/**
|
|
489
500
|
* Start the DSP.
|
|
490
501
|
*/
|
|
@@ -499,6 +510,16 @@ export interface IFaustBaseWebAudioDsp {
|
|
|
499
510
|
* Destroy the DSP.
|
|
500
511
|
*/
|
|
501
512
|
destroy(): void;
|
|
513
|
+
|
|
514
|
+
/** Indicating if the DSP handles the accelerometer */
|
|
515
|
+
readonly hasAccInput: boolean;
|
|
516
|
+
/** Accelerometer handling */
|
|
517
|
+
propagateAcc(accelerationIncludingGravity: NonNullable<DeviceMotionEvent["accelerationIncludingGravity"]>): 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;
|
|
502
523
|
}
|
|
503
524
|
|
|
504
525
|
export interface IFaustMonoWebAudioDsp extends IFaustBaseWebAudioDsp { }
|
|
@@ -557,6 +578,10 @@ export class FaustBaseWebAudioDsp implements IFaustBaseWebAudioDsp {
|
|
|
557
578
|
/** Keep the end of memory offset before soundfiles */
|
|
558
579
|
protected fEndMemory: number;
|
|
559
580
|
|
|
581
|
+
// Accelerometer handling
|
|
582
|
+
protected fAcc: SensorEventHandlers; // array of accelerometer handlers on x,y,y axes, to be called with DeviceMotionEvent
|
|
583
|
+
protected fGyr: SensorEventHandlers; // array of gyroscope handlers on alpha,beta,gama axes, to be called with DeviceMotionEvent
|
|
584
|
+
|
|
560
585
|
// Buffers in wasm memory
|
|
561
586
|
protected fAudioInputs!: number;
|
|
562
587
|
protected fAudioOutputs!: number;
|
|
@@ -579,18 +604,30 @@ export class FaustBaseWebAudioDsp implements IFaustBaseWebAudioDsp {
|
|
|
579
604
|
this.fInputsItems.push(item.address);
|
|
580
605
|
this.fPathTable[item.address] = item.index;
|
|
581
606
|
this.fDescriptor.push(item);
|
|
582
|
-
// Parse 'midi' metadata
|
|
583
607
|
if (!item.meta) return;
|
|
584
608
|
item.meta.forEach((meta) => {
|
|
585
|
-
const { midi } = meta;
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
609
|
+
const { midi, acc, gyr } = meta;
|
|
610
|
+
// Parse 'midi' metadata
|
|
611
|
+
if (midi) {
|
|
612
|
+
const strMidi = midi.trim();
|
|
613
|
+
if (strMidi === "pitchwheel") {
|
|
614
|
+
this.fPitchwheelLabel.push({ path: item.address, min: item.min as number, max: item.max as number });
|
|
615
|
+
} else {
|
|
616
|
+
const matched = strMidi.match(/^ctrl\s(\d+)/);
|
|
617
|
+
if (matched) {
|
|
618
|
+
this.fCtrlLabel[parseInt(matched[1])].push({ path: item.address, min: item.min as number, max: item.max as number });
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
// Parse 'acc' metadata
|
|
623
|
+
if (acc) {
|
|
624
|
+
const numAcc: number[] = acc.trim().split(" ").map(Number);
|
|
625
|
+
this.setupAccHandler(item.address, FaustSensors.convertToAxis(numAcc[0]), FaustSensors.convertToCurve(numAcc[1]), numAcc[2], numAcc[3], numAcc[4], item.min as number, item.init as number, item.max as number);
|
|
626
|
+
}
|
|
627
|
+
// Parse 'gyr' metadata
|
|
628
|
+
if (gyr) {
|
|
629
|
+
const numAcc: number[] = gyr.trim().split(" ").map(Number);
|
|
630
|
+
this.setupGyrHandler(item.address, FaustSensors.convertToAxis(numAcc[0]), FaustSensors.convertToCurve(numAcc[1]), numAcc[2], numAcc[3], numAcc[4], item.min as number, item.init as number, item.max as number);
|
|
594
631
|
}
|
|
595
632
|
});
|
|
596
633
|
} else if (item.type === "soundfile") {
|
|
@@ -610,6 +647,8 @@ export class FaustBaseWebAudioDsp implements IFaustBaseWebAudioDsp {
|
|
|
610
647
|
this.fPtrSize = sampleSize; // Done on wast/wasm backend side
|
|
611
648
|
this.fSampleSize = sampleSize;
|
|
612
649
|
this.fSoundfileBuffers = soundfiles;
|
|
650
|
+
this.fAcc = { x: [], y: [], z: [] };
|
|
651
|
+
this.fGyr = { x: [], y: [], z: [] };
|
|
613
652
|
}
|
|
614
653
|
|
|
615
654
|
// Tools
|
|
@@ -647,6 +686,65 @@ export class FaustBaseWebAudioDsp implements IFaustBaseWebAudioDsp {
|
|
|
647
686
|
return trimmed.split(";").map(str => str.length <= 2 ? '' : str.substring(1, str.length - 1));
|
|
648
687
|
}
|
|
649
688
|
|
|
689
|
+
get hasAccInput() { return this.fAcc.x.length + this.fAcc.y.length + this.fAcc.z.length > 0; }
|
|
690
|
+
propagateAcc(accelerationIncludingGravity: NonNullable<DeviceMotionEvent["accelerationIncludingGravity"]>) {
|
|
691
|
+
|
|
692
|
+
// Get accelerometervalues
|
|
693
|
+
const { x, y, z } = accelerationIncludingGravity;
|
|
694
|
+
|
|
695
|
+
// Call the accelerometer handlers
|
|
696
|
+
if (x !== null) this.fAcc.x.forEach(handler => handler(x));
|
|
697
|
+
if (y !== null) this.fAcc.y.forEach(handler => handler(y));
|
|
698
|
+
if (z !== null) this.fAcc.z.forEach(handler => handler(z));
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
get hasGyrInput() { return this.fGyr.x.length + this.fGyr.y.length + this.fGyr.z.length > 0; }
|
|
702
|
+
propagateGyr(event: Pick<DeviceOrientationEvent, "alpha" | "beta" | "gamma">) {
|
|
703
|
+
|
|
704
|
+
// Get gyroscope values
|
|
705
|
+
const { alpha, beta, gamma } = event;
|
|
706
|
+
|
|
707
|
+
// Call the gyroscope handlers
|
|
708
|
+
if (alpha !== null) this.fGyr.x.forEach(handler => handler(alpha));
|
|
709
|
+
if (beta !== null) this.fGyr.y.forEach(handler => handler(beta));
|
|
710
|
+
if (gamma !== null) this.fGyr.z.forEach(handler => handler(gamma));
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
/** Build the accelerometer handler */
|
|
714
|
+
private setupAccHandler(path: string, axis: Axis, curve: Curve, amin: number, amid: number, amax: number, min: number, init: number, max: number) {
|
|
715
|
+
|
|
716
|
+
const handler: UpdatableValueConverter = FaustSensors.buildHandler(curve, amin, amid, amax, min, init, max);
|
|
717
|
+
switch (axis) {
|
|
718
|
+
case Axis.x:
|
|
719
|
+
this.fAcc.x.push((val) => this.setParamValue(path, handler.uiToFaust(val)));
|
|
720
|
+
break;
|
|
721
|
+
case Axis.y:
|
|
722
|
+
this.fAcc.y.push((val) => this.setParamValue(path, handler.uiToFaust(val)));
|
|
723
|
+
break;
|
|
724
|
+
case Axis.z:
|
|
725
|
+
this.fAcc.z.push((val) => this.setParamValue(path, handler.uiToFaust(val)));
|
|
726
|
+
break;
|
|
727
|
+
}
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
/** Build the gyroscope handler */
|
|
731
|
+
private setupGyrHandler(path: string, axis: Axis, curve: Curve, amin: number, amid: number, amax: number, min: number, init: number, max: number) {
|
|
732
|
+
|
|
733
|
+
const handler: UpdatableValueConverter = FaustSensors.buildHandler(curve, amin, amid, amax, min, init, max);
|
|
734
|
+
switch (axis) {
|
|
735
|
+
case Axis.x:
|
|
736
|
+
this.fGyr.x.push((val) => this.setParamValue(path, handler.uiToFaust(val)));
|
|
737
|
+
break;
|
|
738
|
+
case Axis.y:
|
|
739
|
+
this.fGyr.y.push((val) => this.setParamValue(path, handler.uiToFaust(val)));
|
|
740
|
+
break;
|
|
741
|
+
case Axis.z:
|
|
742
|
+
this.fGyr.z.push((val) => this.setParamValue(path, handler.uiToFaust(val)));
|
|
743
|
+
break;
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
|
|
650
748
|
static extractUrlsFromMeta(dspMeta: FaustDspMeta): string[] {
|
|
651
749
|
// Find the entry with the "soundfiles" key
|
|
652
750
|
const soundfilesEntry = dspMeta.meta.find(entry => entry.soundfiles !== undefined);
|
|
@@ -911,6 +1009,7 @@ export class FaustMonoWebAudioDsp extends FaustBaseWebAudioDsp implements IFaust
|
|
|
911
1009
|
// Init soundfiles memory
|
|
912
1010
|
this.initSoundfileMemory(allocator, this.fDSP);
|
|
913
1011
|
}
|
|
1012
|
+
|
|
914
1013
|
}
|
|
915
1014
|
|
|
916
1015
|
private initMemory(): number {
|