@grame/faustwasm 0.6.3 → 0.7.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.
@@ -31,9 +31,9 @@ audioContext.suspend();
31
31
 
32
32
  (async () => {
33
33
 
34
+ const { createFaustNode } = await import("./create-node.js");
34
35
  // To test the ScriptProcessorNode mode
35
36
  // const { faustNode, dspMeta: { name } } = await createFaustNode(audioContext, "osc", FAUST_DSP_VOICES, true);
36
- const { createFaustNode } = await import("./create-node.js");
37
37
  const { faustNode, dspMeta: { name } } = await createFaustNode(audioContext, "osc", FAUST_DSP_VOICES);
38
38
  if (!faustNode) throw new Error("Faust DSP not compiled");
39
39
 
@@ -50,8 +50,8 @@ audioContext.suspend();
50
50
  await connectToAudioInput(audioContext, null, faustNode, null);
51
51
  }
52
52
 
53
- // Function to initialize MIDI
54
- function initMIDI() {
53
+ // Function to start MIDI
54
+ function startMIDI() {
55
55
  // Check if the browser supports the Web MIDI API
56
56
  if (navigator.requestMIDIAccess) {
57
57
  navigator.requestMIDIAccess().then(
@@ -69,25 +69,81 @@ audioContext.suspend();
69
69
  }
70
70
  }
71
71
 
72
+ // Function to stop MIDI
73
+ function stopMIDI() {
74
+ // Check if the browser supports the Web MIDI API
75
+ if (navigator.requestMIDIAccess) {
76
+ navigator.requestMIDIAccess().then(
77
+ midiAccess => {
78
+ console.log("MIDI Access obtained.");
79
+ for (let input of midiAccess.inputs.values()) {
80
+ input.onmidimessage = null;
81
+ console.log(`Disconnected from input: ${input.name}`);
82
+ }
83
+ },
84
+ () => console.error("Failed to access MIDI devices.")
85
+ );
86
+ } else {
87
+ console.log("Web MIDI API is not supported in this browser.");
88
+ }
89
+ }
90
+
91
+ let sensorHandlersBound = false;
92
+ let midiHandlersBound = false;
93
+
72
94
  // Function to resume AudioContext, activate MIDI and Sensors on user interaction
73
- function activateAudioMIDISensors() {
95
+ async function activateAudioMIDISensors() {
74
96
 
75
97
  // Resume the AudioContext
76
98
  if (audioContext.state === 'suspended') {
77
- audioContext.resume();
99
+ await audioContext.resume();
78
100
  }
79
101
 
80
102
  // Activate sensor listeners
81
- faustNode.listenSensors();
103
+ if (!sensorHandlersBound) {
104
+ await faustNode.startSensors();
105
+ sensorHandlersBound = true;
106
+ }
82
107
 
83
108
  // Initialize the MIDI setup
84
- if (FAUST_DSP_VOICES > 0) {
85
- initMIDI();
109
+ if (!midiHandlersBound && FAUST_DSP_VOICES > 0) {
110
+ startMIDI();
111
+ midiHandlersBound = true;
112
+ }
113
+ }
114
+
115
+ // Function to suspend AudioContext, deactivate MIDI and Sensors on user interaction
116
+ async function deactivateAudioMIDISensors() {
117
+
118
+ // Suspend the AudioContext
119
+ if (audioContext.state === 'running') {
120
+ await audioContext.suspend();
121
+ }
122
+
123
+ // Deactivate sensor listeners
124
+ if (sensorHandlersBound) {
125
+ faustNode.stopSensors();
126
+ sensorHandlersBound = false;
127
+ }
128
+
129
+ // Deactivate the MIDI setup
130
+ if (midiHandlersBound && FAUST_DSP_VOICES > 0) {
131
+ stopMIDI();
132
+ midiHandlersBound = false;
86
133
  }
87
134
  }
88
135
 
89
136
  // Add event listeners for user interactions
137
+
138
+ // Activate AudioContext, MIDI and Sensors on user interaction
90
139
  window.addEventListener('click', activateAudioMIDISensors);
91
140
  window.addEventListener('touchstart', activateAudioMIDISensors);
92
141
 
142
+ // Deactivate AudioContext, MIDI and Sensors on user interaction
143
+ window.addEventListener('visibilitychange', function () {
144
+ if (window.visibilityState === 'hidden') {
145
+ deactivateAudioMIDISensors();
146
+ }
147
+ });
148
+
93
149
  })();
@@ -22,13 +22,13 @@ const FAUST_DSP_VOICES = 0;
22
22
  }
23
23
  // Function to activate audio context
24
24
  $buttonDsp.disabled = true;
25
- $buttonDsp.onclick = () => {
25
+ $buttonDsp.onclick = async () => {
26
26
  if (audioContext.state === "running") {
27
27
  $buttonDsp.textContent = "Suspended";
28
- audioContext.suspend();
28
+ await audioContext.suspend();
29
29
  } else if (audioContext.state === "suspended") {
30
30
  $buttonDsp.textContent = "Running";
31
- audioContext.resume();
31
+ await audioContext.resume();
32
32
  if (FAUST_DSP_VOICES) play(faustNode);
33
33
  }
34
34
  }
@@ -109,9 +109,9 @@ const buildMidiDeviceMenu = async (faustNode) => {
109
109
 
110
110
  (async () => {
111
111
 
112
+ const { createFaustNode } = await import("./create-node.js");
112
113
  // To test the ScriptProcessorNode mode
113
114
  // const { faustNode, dspMeta: { name } } = await createFaustNode(audioContext, "FAUST_DSP_NAME", FAUST_DSP_VOICES, true);
114
- const { createFaustNode } = await import("./create-node.js");
115
115
  const { faustNode, dspMeta: { name } } = await createFaustNode(audioContext, "FAUST_DSP_NAME", FAUST_DSP_VOICES);
116
116
  if (!faustNode) throw new Error("Faust DSP not compiled");
117
117
 
@@ -133,19 +133,19 @@ const buildMidiDeviceMenu = async (faustNode) => {
133
133
  // Set the title and enable the DSP button
134
134
  $buttonDsp.disabled = false;
135
135
  document.title = name;
136
- let motionHandlersBound = false;
136
+ let sensorHandlersBound = false;
137
137
  $buttonDsp.onclick = async () => {
138
138
  // Activate sensor listeners
139
- if (!motionHandlersBound) {
140
- await faustNode.listenSensors();
141
- motionHandlersBound = true;
139
+ if (!sensorHandlersBound) {
140
+ await faustNode.startSensors();
141
+ sensorHandlersBound = true;
142
142
  }
143
143
  if (audioContext.state === "running") {
144
144
  $buttonDsp.textContent = "Suspended";
145
- audioContext.suspend();
145
+ await audioContext.suspend();
146
146
  } else if (audioContext.state === "suspended") {
147
147
  $buttonDsp.textContent = "Running";
148
- audioContext.resume();
148
+ await audioContext.resume();
149
149
  }
150
150
  }
151
151
  })();
@@ -1289,8 +1289,11 @@ export declare class FaustAudioWorkletNode<Poly extends boolean = false> extends
1289
1289
  protected fUICallback: UIHandler;
1290
1290
  protected fDescriptor: FaustUIInputItem[];
1291
1291
  constructor(context: BaseAudioContext, name: string, factory: LooseFaustDspFactory, options?: Partial<FaustAudioWorkletNodeOptions<Poly>>);
1292
+ private handleDeviceMotion;
1293
+ private handleDeviceOrientation;
1292
1294
  /** Setup accelerometer and gyroscope handlers */
1293
- listenSensors(): Promise<void>;
1295
+ startSensors(): Promise<void>;
1296
+ stopSensors(): void;
1294
1297
  setOutputParamHandler(handler: OutputParamHandler | null): void;
1295
1298
  getOutputParamHandler(): OutputParamHandler | null;
1296
1299
  setComputeHandler(handler: ComputeHandler | null): void;
@@ -1353,8 +1356,11 @@ export declare class FaustScriptProcessorNode<Poly extends boolean = false> exte
1353
1356
  protected fInputs: Float32Array[];
1354
1357
  protected fOutputs: Float32Array[];
1355
1358
  init(instance: Poly extends true ? FaustPolyWebAudioDsp : FaustMonoWebAudioDsp): void;
1359
+ private handleDeviceMotion;
1360
+ private handleDeviceOrientation;
1356
1361
  /** Setup accelerometer and gyroscope handlers */
1357
- listenSensors(): Promise<void>;
1362
+ startSensors(): Promise<void>;
1363
+ stopSensors(): void;
1358
1364
  compute(input: Float32Array[], output: Float32Array[]): boolean;
1359
1365
  setOutputParamHandler(handler: OutputParamHandler): void;
1360
1366
  getOutputParamHandler(): OutputParamHandler | null;
package/dist/cjs/index.js CHANGED
@@ -813,8 +813,8 @@ export default ${(_b = jsCode.match(jsCodeHead)) == null ? void 0 : _b[1]};
813
813
  if (t[0] & 1)
814
814
  throw t[1];
815
815
  return t[1];
816
- }, trys: [], ops: [] }, f, y, t, g;
817
- return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() {
816
+ }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
817
+ return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() {
818
818
  return this;
819
819
  }), g;
820
820
  function verb(n) {
@@ -3726,6 +3726,18 @@ export default ${(_b = jsCode.match(jsCodeHead)) == null ? void 0 : _b[1]};
3726
3726
  });
3727
3727
  __privateAdd(this, _hasAccInput, false);
3728
3728
  __privateAdd(this, _hasGyrInput, false);
3729
+ // Public API
3730
+ // Accelerometer and gyroscope handlers
3731
+ this.handleDeviceMotion = ({ accelerationIncludingGravity }) => {
3732
+ const isAndroid = /Android/i.test(navigator.userAgent);
3733
+ if (!accelerationIncludingGravity)
3734
+ return;
3735
+ const { x, y, z } = accelerationIncludingGravity;
3736
+ this.propagateAcc({ x, y, z }, isAndroid);
3737
+ };
3738
+ this.handleDeviceOrientation = ({ alpha, beta, gamma }) => {
3739
+ this.propagateGyr({ alpha, beta, gamma });
3740
+ };
3729
3741
  this.fJSONDsp = JSONObj;
3730
3742
  this.fJSON = factory.json;
3731
3743
  this.fOutputHandler = null;
@@ -3757,56 +3769,59 @@ export default ${(_b = jsCode.match(jsCodeHead)) == null ? void 0 : _b[1]};
3757
3769
  }
3758
3770
  };
3759
3771
  }
3760
- // Public API
3761
3772
  /** Setup accelerometer and gyroscope handlers */
3762
- async listenSensors() {
3773
+ async startSensors() {
3763
3774
  if (this.hasAccInput) {
3764
- const isAndroid = /Android/i.test(navigator.userAgent);
3765
- const handleDeviceMotion = ({ accelerationIncludingGravity }) => {
3766
- if (!accelerationIncludingGravity)
3767
- return;
3768
- const { x, y, z } = accelerationIncludingGravity;
3769
- this.propagateAcc({ x, y, z }, isAndroid);
3770
- };
3771
3775
  if (window.DeviceMotionEvent) {
3772
3776
  if (typeof window.DeviceMotionEvent.requestPermission === "function") {
3773
3777
  try {
3774
3778
  const response = await window.DeviceMotionEvent.requestPermission();
3775
- if (response !== "granted")
3779
+ if (response === "granted") {
3780
+ window.addEventListener("devicemotion", this.handleDeviceMotion, true);
3781
+ } else if (response === "denied") {
3782
+ alert("You have denied access to motion and orientation data. To enable it, go to Settings > Safari > Motion & Orientation Access.");
3776
3783
  throw new Error("Unable to access the accelerometer.");
3777
- window.addEventListener("devicemotion", handleDeviceMotion, true);
3784
+ }
3778
3785
  } catch (error) {
3779
3786
  console.error(error);
3780
3787
  }
3781
3788
  } else {
3782
- window.addEventListener("devicemotion", handleDeviceMotion, true);
3789
+ window.addEventListener("devicemotion", this.handleDeviceMotion, true);
3783
3790
  }
3784
3791
  } else {
3785
3792
  console.log("Cannot set the accelerometer handler.");
3786
3793
  }
3787
3794
  }
3788
3795
  if (this.hasGyrInput) {
3789
- const handleDeviceOrientation = ({ alpha, beta, gamma }) => {
3790
- this.propagateGyr({ alpha, beta, gamma });
3791
- };
3792
3796
  if (window.DeviceMotionEvent) {
3793
3797
  if (typeof window.DeviceOrientationEvent.requestPermission === "function") {
3794
3798
  try {
3795
3799
  const response = await window.DeviceOrientationEvent.requestPermission();
3796
- if (response !== "granted")
3800
+ if (response === "granted") {
3801
+ window.addEventListener("deviceorientation", this.handleDeviceOrientation, true);
3802
+ } else if (response === "denied") {
3803
+ alert("You have denied access to motion and orientation data. To enable it, go to Settings > Safari > Motion & Orientation Access.");
3797
3804
  throw new Error("Unable to access the gyroscope.");
3798
- window.addEventListener("deviceorientation", handleDeviceOrientation, true);
3805
+ }
3799
3806
  } catch (error) {
3800
3807
  console.error(error);
3801
3808
  }
3802
3809
  } else {
3803
- window.addEventListener("deviceorientation", handleDeviceOrientation, true);
3810
+ window.addEventListener("deviceorientation", this.handleDeviceOrientation, true);
3804
3811
  }
3805
3812
  } else {
3806
3813
  console.log("Cannot set the gyroscope handler.");
3807
3814
  }
3808
3815
  }
3809
3816
  }
3817
+ stopSensors() {
3818
+ if (this.hasAccInput) {
3819
+ window.removeEventListener("devicemotion", this.handleDeviceMotion, true);
3820
+ }
3821
+ if (this.hasGyrInput) {
3822
+ window.removeEventListener("deviceorientation", this.handleDeviceOrientation, true);
3823
+ }
3824
+ }
3810
3825
  setOutputParamHandler(handler) {
3811
3826
  this.fOutputHandler = handler;
3812
3827
  }
@@ -3996,6 +4011,21 @@ export default ${(_b = jsCode.match(jsCodeHead)) == null ? void 0 : _b[1]};
3996
4011
 
3997
4012
  // src/FaustScriptProcessorNode.ts
3998
4013
  var FaustScriptProcessorNode = class extends (globalThis.ScriptProcessorNode || null) {
4014
+ constructor() {
4015
+ super(...arguments);
4016
+ // Public API
4017
+ // Accelerometer and gyroscope handlers
4018
+ this.handleDeviceMotion = ({ accelerationIncludingGravity }) => {
4019
+ const isAndroid = /Android/i.test(navigator.userAgent);
4020
+ if (!accelerationIncludingGravity)
4021
+ return;
4022
+ const { x, y, z } = accelerationIncludingGravity;
4023
+ this.propagateAcc({ x, y, z }, isAndroid);
4024
+ };
4025
+ this.handleDeviceOrientation = ({ alpha, beta, gamma }) => {
4026
+ this.propagateGyr({ alpha, beta, gamma });
4027
+ };
4028
+ }
3999
4029
  init(instance) {
4000
4030
  this.fDSPCode = instance;
4001
4031
  this.fInputs = new Array(this.fDSPCode.getNumInputs());
@@ -4011,56 +4041,53 @@ export default ${(_b = jsCode.match(jsCodeHead)) == null ? void 0 : _b[1]};
4011
4041
  };
4012
4042
  this.start();
4013
4043
  }
4014
- // Public API
4015
4044
  /** Setup accelerometer and gyroscope handlers */
4016
- async listenSensors() {
4045
+ async startSensors() {
4017
4046
  if (this.hasAccInput) {
4018
- const isAndroid = /Android/i.test(navigator.userAgent);
4019
- const handleDeviceMotion = ({ accelerationIncludingGravity }) => {
4020
- if (!accelerationIncludingGravity)
4021
- return;
4022
- const { x, y, z } = accelerationIncludingGravity;
4023
- this.propagateAcc({ x, y, z }, isAndroid);
4024
- };
4025
4047
  if (window.DeviceMotionEvent) {
4026
4048
  if (typeof window.DeviceMotionEvent.requestPermission === "function") {
4027
4049
  try {
4028
4050
  const response = await window.DeviceMotionEvent.requestPermission();
4029
4051
  if (response !== "granted")
4030
4052
  throw new Error("Unable to access the accelerometer.");
4031
- window.addEventListener("devicemotion", handleDeviceMotion, true);
4053
+ window.addEventListener("devicemotion", this.handleDeviceMotion, true);
4032
4054
  } catch (error) {
4033
4055
  console.error(error);
4034
4056
  }
4035
4057
  } else {
4036
- window.addEventListener("devicemotion", handleDeviceMotion, true);
4058
+ window.addEventListener("devicemotion", this.handleDeviceMotion, true);
4037
4059
  }
4038
4060
  } else {
4039
4061
  console.log("Cannot set the accelerometer handler.");
4040
4062
  }
4041
4063
  }
4042
4064
  if (this.hasGyrInput) {
4043
- const handleDeviceOrientation = ({ alpha, beta, gamma }) => {
4044
- this.propagateGyr({ alpha, beta, gamma });
4045
- };
4046
4065
  if (window.DeviceMotionEvent) {
4047
4066
  if (typeof window.DeviceOrientationEvent.requestPermission === "function") {
4048
4067
  try {
4049
4068
  const response = await window.DeviceOrientationEvent.requestPermission();
4050
4069
  if (response !== "granted")
4051
4070
  throw new Error("Unable to access the gyroscope.");
4052
- window.addEventListener("deviceorientation", handleDeviceOrientation, true);
4071
+ window.addEventListener("deviceorientation", this.handleDeviceOrientation, true);
4053
4072
  } catch (error) {
4054
4073
  console.error(error);
4055
4074
  }
4056
4075
  } else {
4057
- window.addEventListener("deviceorientation", handleDeviceOrientation, true);
4076
+ window.addEventListener("deviceorientation", this.handleDeviceOrientation, true);
4058
4077
  }
4059
4078
  } else {
4060
4079
  console.log("Cannot set the gyroscope handler.");
4061
4080
  }
4062
4081
  }
4063
4082
  }
4083
+ stopSensors() {
4084
+ if (this.hasAccInput) {
4085
+ window.removeEventListener("devicemotion", this.handleDeviceMotion, true);
4086
+ }
4087
+ if (this.hasGyrInput) {
4088
+ window.removeEventListener("deviceorientation", this.handleDeviceOrientation, true);
4089
+ }
4090
+ }
4064
4091
  compute(input, output) {
4065
4092
  return this.fDSPCode.compute(input, output);
4066
4093
  }