@grame/faustwasm 0.6.4 → 0.7.3

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
- // To test the ScriptProcessorNode mode
35
- // const { faustNode, dspMeta: { name } } = await createFaustNode(audioContext, "osc", FAUST_DSP_VOICES, true);
36
34
  const { createFaustNode } = await import("./create-node.js");
35
+ // To test the ScriptProcessorNode mode
36
+ //const { faustNode, dspMeta: { name } } = await createFaustNode(audioContext, "osc", FAUST_DSP_VOICES, true, 512);
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,32 +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
+
72
91
  let sensorHandlersBound = false;
73
92
  let midiHandlersBound = false;
74
93
 
75
94
  // Function to resume AudioContext, activate MIDI and Sensors on user interaction
76
- function activateAudioMIDISensors() {
95
+ async function activateAudioMIDISensors() {
77
96
 
78
97
  // Resume the AudioContext
79
98
  if (audioContext.state === 'suspended') {
80
- audioContext.resume();
99
+ await audioContext.resume();
81
100
  }
82
101
 
83
102
  // Activate sensor listeners
84
103
  if (!sensorHandlersBound) {
85
- faustNode.listenSensors();
104
+ await faustNode.startSensors();
86
105
  sensorHandlersBound = true;
87
106
  }
88
107
 
89
108
  // Initialize the MIDI setup
90
109
  if (!midiHandlersBound && FAUST_DSP_VOICES > 0) {
91
- initMIDI();
110
+ startMIDI();
92
111
  midiHandlersBound = true;
93
112
  }
94
113
  }
95
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;
133
+ }
134
+ }
135
+
96
136
  // Add event listeners for user interactions
137
+
138
+ // Activate AudioContext, MIDI and Sensors on user interaction
97
139
  window.addEventListener('click', activateAudioMIDISensors);
98
140
  window.addEventListener('touchstart', activateAudioMIDISensors);
99
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
+
100
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
 
@@ -137,15 +137,15 @@ const buildMidiDeviceMenu = async (faustNode) => {
137
137
  $buttonDsp.onclick = async () => {
138
138
  // Activate sensor listeners
139
139
  if (!sensorHandlersBound) {
140
- await faustNode.listenSensors();
140
+ await faustNode.startSensors();
141
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
  })();
@@ -621,11 +621,11 @@ export interface IFaustBaseWebAudioDsp {
621
621
  */
622
622
  getJSON(): string;
623
623
  /**
624
- * Start the DSP.
624
+ * Start the DSP audio processing.
625
625
  */
626
626
  start(): void;
627
627
  /**
628
- * Stop the DSP.
628
+ * Stop the DSP audio processing.
629
629
  */
630
630
  stop(): void;
631
631
  /**
@@ -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;
@@ -1352,9 +1355,12 @@ export declare class FaustScriptProcessorNode<Poly extends boolean = false> exte
1352
1355
  protected fDSPCode: Poly extends true ? FaustPolyWebAudioDsp : FaustMonoWebAudioDsp;
1353
1356
  protected fInputs: Float32Array[];
1354
1357
  protected fOutputs: Float32Array[];
1358
+ protected handleDeviceMotion: any;
1359
+ protected handleDeviceOrientation: any;
1355
1360
  init(instance: Poly extends true ? FaustPolyWebAudioDsp : FaustMonoWebAudioDsp): void;
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
@@ -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,10 +4011,25 @@ 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
+ this.handleDeviceMotion = void 0;
4017
+ this.handleDeviceOrientation = void 0;
4018
+ }
3999
4019
  init(instance) {
4000
4020
  this.fDSPCode = instance;
4001
4021
  this.fInputs = new Array(this.fDSPCode.getNumInputs());
4002
4022
  this.fOutputs = new Array(this.fDSPCode.getNumOutputs());
4023
+ this.handleDeviceMotion = ({ accelerationIncludingGravity }) => {
4024
+ const isAndroid = /Android/i.test(navigator.userAgent);
4025
+ if (!accelerationIncludingGravity)
4026
+ return;
4027
+ const { x, y, z } = accelerationIncludingGravity;
4028
+ this.propagateAcc({ x, y, z }, isAndroid);
4029
+ };
4030
+ this.handleDeviceOrientation = ({ alpha, beta, gamma }) => {
4031
+ this.propagateGyr({ alpha, beta, gamma });
4032
+ };
4003
4033
  this.onaudioprocess = (e) => {
4004
4034
  for (let chan = 0; chan < this.fDSPCode.getNumInputs(); chan++) {
4005
4035
  this.fInputs[chan] = e.inputBuffer.getChannelData(chan);
@@ -4013,54 +4043,58 @@ export default ${(_b = jsCode.match(jsCodeHead)) == null ? void 0 : _b[1]};
4013
4043
  }
4014
4044
  // Public API
4015
4045
  /** Setup accelerometer and gyroscope handlers */
4016
- async listenSensors() {
4046
+ async startSensors() {
4017
4047
  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
4048
  if (window.DeviceMotionEvent) {
4026
4049
  if (typeof window.DeviceMotionEvent.requestPermission === "function") {
4027
4050
  try {
4028
4051
  const response = await window.DeviceMotionEvent.requestPermission();
4029
- if (response !== "granted")
4052
+ if (response === "granted") {
4053
+ window.addEventListener("devicemotion", this.handleDeviceMotion, true);
4054
+ } else if (response === "denied") {
4055
+ alert("You have denied access to motion and orientation data. To enable it, go to Settings > Safari > Motion & Orientation Access.");
4030
4056
  throw new Error("Unable to access the accelerometer.");
4031
- window.addEventListener("devicemotion", handleDeviceMotion, true);
4057
+ }
4032
4058
  } catch (error) {
4033
4059
  console.error(error);
4034
4060
  }
4035
4061
  } else {
4036
- window.addEventListener("devicemotion", handleDeviceMotion, true);
4062
+ window.addEventListener("devicemotion", this.handleDeviceMotion, true);
4037
4063
  }
4038
4064
  } else {
4039
4065
  console.log("Cannot set the accelerometer handler.");
4040
4066
  }
4041
4067
  }
4042
4068
  if (this.hasGyrInput) {
4043
- const handleDeviceOrientation = ({ alpha, beta, gamma }) => {
4044
- this.propagateGyr({ alpha, beta, gamma });
4045
- };
4046
4069
  if (window.DeviceMotionEvent) {
4047
4070
  if (typeof window.DeviceOrientationEvent.requestPermission === "function") {
4048
4071
  try {
4049
4072
  const response = await window.DeviceOrientationEvent.requestPermission();
4050
- if (response !== "granted")
4073
+ if (response === "granted") {
4074
+ window.addEventListener("deviceorientation", this.handleDeviceOrientation, true);
4075
+ } else if (response === "denied") {
4076
+ alert("You have denied access to motion and orientation data. To enable it, go to Settings > Safari > Motion & Orientation Access.");
4051
4077
  throw new Error("Unable to access the gyroscope.");
4052
- window.addEventListener("deviceorientation", handleDeviceOrientation, true);
4078
+ }
4053
4079
  } catch (error) {
4054
4080
  console.error(error);
4055
4081
  }
4056
4082
  } else {
4057
- window.addEventListener("deviceorientation", handleDeviceOrientation, true);
4083
+ window.addEventListener("deviceorientation", this.handleDeviceOrientation, true);
4058
4084
  }
4059
4085
  } else {
4060
4086
  console.log("Cannot set the gyroscope handler.");
4061
4087
  }
4062
4088
  }
4063
4089
  }
4090
+ stopSensors() {
4091
+ if (this.hasAccInput) {
4092
+ window.removeEventListener("devicemotion", this.handleDeviceMotion, true);
4093
+ }
4094
+ if (this.hasGyrInput) {
4095
+ window.removeEventListener("deviceorientation", this.handleDeviceOrientation, true);
4096
+ }
4097
+ }
4064
4098
  compute(input, output) {
4065
4099
  return this.fDSPCode.compute(input, output);
4066
4100
  }