@grame/faustwasm 0.2.3 → 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.
@@ -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
+ }
@@ -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;
@@ -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
- if (!midi) return;
587
- const strMidi = midi.trim();
588
- if (strMidi === "pitchwheel") {
589
- this.fPitchwheelLabel.push({ path: item.address, min: item.min as number, max: item.max as number });
590
- } else {
591
- const matched = strMidi.match(/^ctrl\s(\d+)/);
592
- if (!matched) return;
593
- this.fCtrlLabel[parseInt(matched[1])].push({ path: item.address, min: item.min as number, max: item.max as number });
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 {
@@ -376,6 +376,12 @@ export type PlotHandler = (plotted: Float32Array[] | Float64Array[], index: numb
376
376
  }[]) => void;
377
377
  export type MetadataHandler = (key: string, value: string) => void;
378
378
  export type UIHandler = (item: FaustUIItem) => void;
379
+ export type SensorEventHandler = (val: number) => void;
380
+ export type SensorEventHandlers = {
381
+ x: SensorEventHandler[];
382
+ y: SensorEventHandler[];
383
+ z: SensorEventHandler[];
384
+ };
379
385
  /** Definition of the AudioBufferItem type */
380
386
  export interface AudioBufferItem {
381
387
  pathName: string;
@@ -626,6 +632,14 @@ export interface IFaustBaseWebAudioDsp {
626
632
  * Destroy the DSP.
627
633
  */
628
634
  destroy(): void;
635
+ /** Indicating if the DSP handles the accelerometer */
636
+ readonly hasAccInput: boolean;
637
+ /** Accelerometer handling */
638
+ propagateAcc(accelerationIncludingGravity: NonNullable<DeviceMotionEvent["accelerationIncludingGravity"]>): void;
639
+ /** Indicating if the DSP handles the gyroscope */
640
+ readonly hasGyrInput: boolean;
641
+ /** Gyroscope handling */
642
+ propagateGyr(event: Pick<DeviceOrientationEvent, "alpha" | "beta" | "gamma">): void;
629
643
  }
630
644
  export interface IFaustMonoWebAudioDsp extends IFaustBaseWebAudioDsp {
631
645
  }
@@ -676,6 +690,8 @@ export declare class FaustBaseWebAudioDsp implements IFaustBaseWebAudioDsp {
676
690
  protected fSoundfileBuffers: LooseFaustDspFactory["soundfiles"];
677
691
  /** Keep the end of memory offset before soundfiles */
678
692
  protected fEndMemory: number;
693
+ protected fAcc: SensorEventHandlers;
694
+ protected fGyr: SensorEventHandlers;
679
695
  protected fAudioInputs: number;
680
696
  protected fAudioOutputs: number;
681
697
  protected fBufferSize: number;
@@ -707,6 +723,14 @@ export declare class FaustBaseWebAudioDsp implements IFaustBaseWebAudioDsp {
707
723
  static parseItem(item: FaustUIItem, callback: (item: FaustUIItem) => any): void;
708
724
  /** Split the soundfile names and return an array of names */
709
725
  static splitSoundfileNames(input: string): string[];
726
+ get hasAccInput(): boolean;
727
+ propagateAcc(accelerationIncludingGravity: NonNullable<DeviceMotionEvent["accelerationIncludingGravity"]>): void;
728
+ get hasGyrInput(): boolean;
729
+ propagateGyr(event: Pick<DeviceOrientationEvent, "alpha" | "beta" | "gamma">): void;
730
+ /** Build the accelerometer handler */
731
+ private setupAccHandler;
732
+ /** Build the gyroscope handler */
733
+ private setupGyrHandler;
710
734
  static extractUrlsFromMeta(dspMeta: FaustDspMeta): string[];
711
735
  /**
712
736
  * Load a soundfile possibly containing several parts in the DSP struct.
@@ -1098,6 +1122,10 @@ export declare class FaustOfflineProcessor<Poly extends boolean = false> {
1098
1122
  start(): void;
1099
1123
  stop(): void;
1100
1124
  destroy(): void;
1125
+ get hasAccInput(): boolean;
1126
+ propagateAcc(accelerationIncludingGravity: NonNullable<DeviceMotionEvent["accelerationIncludingGravity"]>): void;
1127
+ get hasGyrInput(): boolean;
1128
+ propagateGyr(event: Pick<DeviceOrientationEvent, "alpha" | "beta" | "gamma">): void;
1101
1129
  /**
1102
1130
  * Render frames in an array.
1103
1131
  *
@@ -1239,6 +1267,7 @@ declare const FaustAudioWorkletNode_base: {
1239
1267
  * Base class for Monophonic and Polyphonic AudioWorkletNode
1240
1268
  */
1241
1269
  export declare class FaustAudioWorkletNode<Poly extends boolean = false> extends FaustAudioWorkletNode_base {
1270
+ #private;
1242
1271
  protected fJSONDsp: FaustDspMeta;
1243
1272
  protected fJSON: string;
1244
1273
  protected fInputsItems: string[];
@@ -1248,6 +1277,8 @@ export declare class FaustAudioWorkletNode<Poly extends boolean = false> extends
1248
1277
  protected fUICallback: UIHandler;
1249
1278
  protected fDescriptor: FaustUIInputItem[];
1250
1279
  constructor(context: BaseAudioContext, name: string, factory: LooseFaustDspFactory, options: FaustAudioWorkletNodeOptions<Poly>["processorOptions"], nodeOptions?: Partial<FaustAudioWorkletNodeOptions>);
1280
+ /** Setup accelerometer and gyroscope handlers */
1281
+ listenMotion(): Promise<void>;
1251
1282
  setOutputParamHandler(handler: OutputParamHandler | null): void;
1252
1283
  getOutputParamHandler(): OutputParamHandler | null;
1253
1284
  setComputeHandler(handler: ComputeHandler | null): void;
@@ -1261,6 +1292,10 @@ export declare class FaustAudioWorkletNode<Poly extends boolean = false> extends
1261
1292
  midiMessage(data: number[] | Uint8Array): void;
1262
1293
  ctrlChange(channel: number, ctrl: number, value: number): void;
1263
1294
  pitchWheel(channel: number, wheel: number): void;
1295
+ get hasAccInput(): boolean;
1296
+ propagateAcc(accelerationIncludingGravity: NonNullable<DeviceMotionEvent["accelerationIncludingGravity"]>): void;
1297
+ get hasGyrInput(): boolean;
1298
+ propagateGyr(event: Pick<DeviceOrientationEvent, "alpha" | "beta" | "gamma">): void;
1264
1299
  setParamValue(path: string, value: number): void;
1265
1300
  getParamValue(path: string): number;
1266
1301
  getParams(): string[];
@@ -1305,6 +1340,8 @@ export declare class FaustScriptProcessorNode<Poly extends boolean = false> exte
1305
1340
  protected fInputs: Float32Array[];
1306
1341
  protected fOutputs: Float32Array[];
1307
1342
  init(instance: Poly extends true ? FaustPolyWebAudioDsp : FaustMonoWebAudioDsp): void;
1343
+ /** Setup accelerometer and gyroscope handlers */
1344
+ listenMotion(): Promise<void>;
1308
1345
  compute(input: Float32Array[], output: Float32Array[]): boolean;
1309
1346
  setOutputParamHandler(handler: OutputParamHandler): void;
1310
1347
  getOutputParamHandler(): OutputParamHandler | null;
@@ -1328,6 +1365,10 @@ export declare class FaustScriptProcessorNode<Poly extends boolean = false> exte
1328
1365
  start(): void;
1329
1366
  stop(): void;
1330
1367
  destroy(): void;
1368
+ get hasAccInput(): boolean;
1369
+ propagateAcc(accelerationIncludingGravity: NonNullable<DeviceMotionEvent["accelerationIncludingGravity"]>): void;
1370
+ get hasGyrInput(): boolean;
1371
+ propagateGyr(event: Pick<DeviceOrientationEvent, "alpha" | "beta" | "gamma">): void;
1331
1372
  }
1332
1373
  export declare class FaustMonoScriptProcessorNode extends FaustScriptProcessorNode<false> implements IFaustMonoWebAudioDsp {
1333
1374
  }