@grame/faustwasm 0.8.0 → 0.8.2

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.
@@ -29,120 +29,155 @@ const audioContext = new AudioCtx({ latencyHint: 0.00001 });
29
29
  audioContext.destination.channelInterpretation = "discrete";
30
30
  audioContext.suspend();
31
31
 
32
+ // Declare faustNode as a global variable
33
+ let faustNode;
34
+
35
+ // Called at load time
32
36
  (async () => {
33
37
 
34
- const { createFaustNode, createFaustUI, connectToAudioInput } = await import("./create-node.js");
38
+ // Import the create-node module
39
+ const { createFaustNode, createFaustUI } = await import("./create-node.js");
35
40
 
36
41
  // To test the ScriptProcessorNode mode
37
- //const { faustNode, dspMeta: { name } } = await createFaustNode(audioContext, "osc", FAUST_DSP_VOICES, true, 512);
38
- const { faustNode, dspMeta: { name } } = await createFaustNode(audioContext, "osc", FAUST_DSP_VOICES);
42
+ // const result = await createFaustNode(audioContext, "osc", FAUST_DSP_VOICES, true, 512);
43
+ const result = await createFaustNode(audioContext, "osc", FAUST_DSP_VOICES);
44
+ faustNode = result.faustNode; // Assign to the global variable
39
45
  if (!faustNode) throw new Error("Faust DSP not compiled");
40
46
 
41
47
  // Create the Faust UI
42
48
  await createFaustUI($divFaustUI, faustNode);
43
49
 
44
- // Function to start MIDI
45
- function startMIDI() {
46
- // Check if the browser supports the Web MIDI API
47
- if (navigator.requestMIDIAccess) {
48
- navigator.requestMIDIAccess().then(
49
- midiAccess => {
50
- console.log("MIDI Access obtained.");
51
- for (let input of midiAccess.inputs.values()) {
52
- input.onmidimessage = (event) => faustNode.midiMessage(event.data);
53
- console.log(`Connected to input: ${input.name}`);
54
- }
55
- },
56
- () => console.error("Failed to access MIDI devices.")
57
- );
58
- } else {
59
- console.log("Web MIDI API is not supported in this browser.");
60
- }
50
+ })();
51
+
52
+ // Synchronous function to resume AudioContext, to be called first in the synchronous event listener
53
+ function resumeAudioContext() {
54
+ if (audioContext.state === 'suspended') {
55
+ audioContext.resume().then(() => {
56
+ console.log('AudioContext resumed successfully');
57
+ }).catch(error => {
58
+ console.error('Error when resuming AudioContext:', error);
59
+ });
61
60
  }
61
+ }
62
+
63
+ // Function to start MIDI
64
+ function startMIDI() {
65
+ // Check if the browser supports the Web MIDI API
66
+ if (navigator.requestMIDIAccess) {
67
+ navigator.requestMIDIAccess().then(
68
+ midiAccess => {
69
+ console.log("MIDI Access obtained.");
70
+ for (let input of midiAccess.inputs.values()) {
71
+ input.onmidimessage = (event) => faustNode.midiMessage(event.data);
72
+ console.log(`Connected to input: ${input.name}`);
73
+ }
74
+ },
75
+ () => console.error("Failed to access MIDI devices.")
76
+ );
77
+ } else {
78
+ console.log("Web MIDI API is not supported in this browser.");
79
+ }
80
+ }
81
+
82
+ // Function to stop MIDI
83
+ function stopMIDI() {
84
+ // Check if the browser supports the Web MIDI API
85
+ if (navigator.requestMIDIAccess) {
86
+ navigator.requestMIDIAccess().then(
87
+ midiAccess => {
88
+ console.log("MIDI Access obtained.");
89
+ for (let input of midiAccess.inputs.values()) {
90
+ input.onmidimessage = null;
91
+ console.log(`Disconnected from input: ${input.name}`);
92
+ }
93
+ },
94
+ () => console.error("Failed to access MIDI devices.")
95
+ );
96
+ } else {
97
+ console.log("Web MIDI API is not supported in this browser.");
98
+ }
99
+ }
100
+
101
+ let sensorHandlersBound = false;
102
+ let midiHandlersBound = false;
103
+
104
+ // Function to activate MIDI and Sensors on user interaction
105
+ async function activateMIDISensors() {
106
+
107
+ // Import the create-node module
108
+ const { connectToAudioInput, requestPermissions } = await import("./create-node.js");
62
109
 
63
- // Function to stop MIDI
64
- function stopMIDI() {
65
- // Check if the browser supports the Web MIDI API
66
- if (navigator.requestMIDIAccess) {
67
- navigator.requestMIDIAccess().then(
68
- midiAccess => {
69
- console.log("MIDI Access obtained.");
70
- for (let input of midiAccess.inputs.values()) {
71
- input.onmidimessage = null;
72
- console.log(`Disconnected from input: ${input.name}`);
73
- }
74
- },
75
- () => console.error("Failed to access MIDI devices.")
76
- );
77
- } else {
78
- console.log("Web MIDI API is not supported in this browser.");
79
- }
110
+ // Request permission for sensors
111
+ await requestPermissions();
112
+
113
+ // Activate sensor listeners
114
+ if (!sensorHandlersBound) {
115
+ await faustNode.startSensors();
116
+ sensorHandlersBound = true;
80
117
  }
81
118
 
82
- let sensorHandlersBound = false;
83
- let midiHandlersBound = false;
119
+ // Initialize the MIDI setup
120
+ if (!midiHandlersBound && FAUST_DSP_VOICES > 0) {
121
+ startMIDI();
122
+ midiHandlersBound = true;
123
+ }
84
124
 
85
- // Function to resume AudioContext, activate MIDI and Sensors on user interaction
86
- async function activateAudioMIDISensors() {
125
+ // Connect the Faust node to the audio output
126
+ faustNode.connect(audioContext.destination);
87
127
 
88
- // Activate sensor listeners
89
- if (!sensorHandlersBound) {
90
- await faustNode.startSensors();
91
- sensorHandlersBound = true;
92
- }
128
+ // Connect the Faust node to the audio input
129
+ if (faustNode.numberOfInputs > 0) {
130
+ await connectToAudioInput(audioContext, null, faustNode, null);
131
+ }
93
132
 
94
- // Initialize the MIDI setup
95
- if (!midiHandlersBound && FAUST_DSP_VOICES > 0) {
96
- startMIDI();
97
- midiHandlersBound = true;
98
- }
133
+ // Resume the AudioContext
134
+ if (audioContext.state === 'suspended') {
135
+ await audioContext.resume();
136
+ }
137
+ }
99
138
 
100
- // Connect the Faust node to the audio output
101
- faustNode.connect(audioContext.destination);
139
+ // Function to suspend AudioContext, deactivate MIDI and Sensors on user interaction
140
+ async function deactivateAudioMIDISensors() {
102
141
 
103
- // Connect the Faust node to the audio input
104
- if (faustNode.numberOfInputs > 0) {
105
- await connectToAudioInput(audioContext, null, faustNode, null);
106
- }
142
+ // Suspend the AudioContext
143
+ if (audioContext.state === 'running') {
144
+ await audioContext.suspend();
145
+ }
107
146
 
108
- // Resume the AudioContext
109
- if (audioContext.state === 'suspended') {
110
- await audioContext.resume();
111
- }
147
+ // Deactivate sensor listeners
148
+ if (sensorHandlersBound) {
149
+ faustNode.stopSensors();
150
+ sensorHandlersBound = false;
112
151
  }
113
152
 
114
- // Function to suspend AudioContext, deactivate MIDI and Sensors on user interaction
115
- async function deactivateAudioMIDISensors() {
116
-
117
- // Suspend the AudioContext
118
- if (audioContext.state === 'running') {
119
- await audioContext.suspend();
120
- }
121
-
122
- // Deactivate sensor listeners
123
- if (sensorHandlersBound) {
124
- faustNode.stopSensors();
125
- sensorHandlersBound = false;
126
- }
127
-
128
- // Deactivate the MIDI setup
129
- if (midiHandlersBound && FAUST_DSP_VOICES > 0) {
130
- stopMIDI();
131
- midiHandlersBound = false;
132
- }
153
+ // Deactivate the MIDI setup
154
+ if (midiHandlersBound && FAUST_DSP_VOICES > 0) {
155
+ stopMIDI();
156
+ midiHandlersBound = false;
133
157
  }
158
+ }
134
159
 
135
- // Add event listeners for user interactions
160
+ // Event listener to handle user interaction
161
+ function handleUserInteraction() {
136
162
 
137
- // Activate AudioContext, MIDI and Sensors on user interaction
138
- window.addEventListener('click', activateAudioMIDISensors);
139
- window.addEventListener('touchstart', activateAudioMIDISensors);
163
+ // Resume AudioContext synchronously
164
+ resumeAudioContext();
140
165
 
141
- // Deactivate AudioContext, MIDI and Sensors on user interaction
142
- window.addEventListener('visibilitychange', function () {
143
- if (window.visibilityState === 'hidden') {
144
- deactivateAudioMIDISensors();
145
- }
166
+ // Launch the activation of MIDI and Sensors
167
+ activateMIDISensors().catch(error => {
168
+ console.error('Error when activating audio, MIDI and sensors:', error);
146
169
  });
170
+ }
171
+
172
+ // Activate AudioContext, MIDI and Sensors on user interaction
173
+ window.addEventListener('click', handleUserInteraction);
174
+ window.addEventListener('touchstart', handleUserInteraction);
175
+
176
+ // Deactivate AudioContext, MIDI and Sensors on user interaction
177
+ window.addEventListener('visibilitychange', function () {
178
+ if (window.visibilityState === 'hidden') {
179
+ deactivateAudioMIDISensors();
180
+ }
181
+ });
182
+
147
183
 
148
- })();
@@ -1,18 +1,49 @@
1
1
  // Set to > 0 if the DSP is polyphonic
2
2
  const FAUST_DSP_VOICES = 0;
3
3
 
4
- (async () => {
4
+ // Declare faustNode as a global variable
5
+ let faustNode;
5
6
 
6
- const { createFaustNode, connectToAudioInput } = await import("./create-node.js");
7
+ // Create audio context activation button
8
+ /** @type {HTMLButtonElement} */
9
+ const $buttonDsp = document.getElementById("button-dsp");
10
+
11
+ // Create audio context
12
+ const AudioCtx = window.AudioContext || window.webkitAudioContext;
13
+ const audioContext = new AudioCtx({ latencyHint: 0.00001 });
14
+
15
+ // Activate AudioContext and Sensors on user interaction
16
+ $buttonDsp.disabled = true;
17
+ let sensorHandlersBound = false;
18
+ $buttonDsp.onclick = async () => {
19
+
20
+ // Import the requestPermissions function
21
+ const { requestPermissions } = await import("./create-node.js");
22
+
23
+ // Request permission for sensors
24
+ await requestPermissions();
25
+
26
+ // Activate sensor listeners
27
+ if (!sensorHandlersBound) {
28
+ await faustNode.startSensors();
29
+ sensorHandlersBound = true;
30
+ }
7
31
 
8
- // Create audio context
9
- const AudioCtx = window.AudioContext || window.webkitAudioContext;
10
- const audioContext = new AudioCtx({ latencyHint: 0.00001 });
11
- audioContext.suspend();
32
+ // Activate or suspend the AudioContext
33
+ if (audioContext.state === "running") {
34
+ $buttonDsp.textContent = "Suspended";
35
+ await audioContext.suspend();
36
+ } else if (audioContext.state === "suspended") {
37
+ $buttonDsp.textContent = "Running";
38
+ await audioContext.resume();
39
+ if (FAUST_DSP_VOICES) play(faustNode);
40
+ }
41
+ }
12
42
 
13
- // Create audio context activation button
14
- /** @type {HTMLButtonElement} */
15
- const $buttonDsp = document.getElementById("button-dsp");
43
+ // Called at load time
44
+ (async () => {
45
+
46
+ const { createFaustNode, connectToAudioInput } = await import("./create-node.js");
16
47
 
17
48
  const play = (node) => {
18
49
  node.keyOn(0, 60, 100);
@@ -21,21 +52,10 @@ const FAUST_DSP_VOICES = 0;
21
52
  setTimeout(() => node.allNotesOff(), 5000);
22
53
  setTimeout(() => play(node), 7000);
23
54
  }
24
- // Function to activate audio context
25
- $buttonDsp.disabled = true;
26
- $buttonDsp.onclick = async () => {
27
- if (audioContext.state === "running") {
28
- $buttonDsp.textContent = "Suspended";
29
- await audioContext.suspend();
30
- } else if (audioContext.state === "suspended") {
31
- $buttonDsp.textContent = "Running";
32
- await audioContext.resume();
33
- if (FAUST_DSP_VOICES) play(faustNode);
34
- }
35
- }
36
55
 
37
56
  // Create Faust node
38
- const { faustNode, dspMeta: { name } } = await createFaustNode(audioContext, "FAUST_DSP_NAME", FAUST_DSP_VOICES);
57
+ const result = await createFaustNode(audioContext, "FAUST_DSP_NAME", FAUST_DSP_VOICES);
58
+ faustNode = result.faustNode; // Assign to the global variable
39
59
  if (!faustNode) throw new Error("Faust DSP not compiled");
40
60
 
41
61
  // Connect the Faust node to the audio output
@@ -51,4 +71,5 @@ const FAUST_DSP_VOICES = 0;
51
71
 
52
72
  // Set page title to the DSP name
53
73
  document.title = name;
74
+
54
75
  })();
@@ -41,6 +41,10 @@ audioContext.suspend();
41
41
 
42
42
  $buttonDsp.disabled = true;
43
43
 
44
+ // Declare faustNode as a global variable
45
+ let faustNode;
46
+
47
+ // Called at load time
44
48
  (async () => {
45
49
 
46
50
  const { createFaustNode, connectToAudioInput, createFaustUI } = await import("./create-node.js");
@@ -111,7 +115,8 @@ $buttonDsp.disabled = true;
111
115
 
112
116
  // To test the ScriptProcessorNode mode
113
117
  // const { faustNode, dspMeta: { name } } = await createFaustNode(audioContext, "FAUST_DSP_NAME", FAUST_DSP_VOICES, true);
114
- const { faustNode, dspMeta: { name } } = await createFaustNode(audioContext, "FAUST_DSP_NAME", FAUST_DSP_VOICES);
118
+ const result = await createFaustNode(audioContext, "FAUST_DSP_NAME", FAUST_DSP_VOICES);
119
+ faustNode = result.faustNode; // Assign to the global variable
115
120
  if (!faustNode) throw new Error("Faust DSP not compiled");
116
121
 
117
122
  // Create the Faust UI
@@ -128,22 +133,34 @@ $buttonDsp.disabled = true;
128
133
  if (navigator.requestMIDIAccess) await buildMidiDeviceMenu(faustNode);
129
134
  else $spanMidiInput.hidden = true;
130
135
 
131
- // Set the title and enable the DSP button
132
- $buttonDsp.disabled = false;
133
- document.title = name;
134
- let sensorHandlersBound = false;
135
- $buttonDsp.onclick = async () => {
136
- // Activate sensor listeners
137
- if (!sensorHandlersBound) {
138
- await faustNode.startSensors();
139
- sensorHandlersBound = true;
140
- }
141
- if (audioContext.state === "running") {
142
- $buttonDsp.textContent = "Suspended";
143
- await audioContext.suspend();
144
- } else if (audioContext.state === "suspended") {
145
- $buttonDsp.textContent = "Running";
146
- await audioContext.resume();
147
- }
148
- }
149
136
  })();
137
+
138
+ // Set the title and enable the DSP button
139
+ $buttonDsp.disabled = false;
140
+ document.title = name;
141
+ let sensorHandlersBound = false;
142
+
143
+ // Activate AudioContext and Sensors on user interaction
144
+ $buttonDsp.onclick = async () => {
145
+
146
+ // Import the requestPermissions function
147
+ const { requestPermissions } = await import("./create-node.js");
148
+
149
+ // Request permission for sensors
150
+ await requestPermissions();
151
+
152
+ // Activate sensor listeners
153
+ if (!sensorHandlersBound) {
154
+ await faustNode.startSensors();
155
+ sensorHandlersBound = true;
156
+ }
157
+
158
+ // Activate or suspend the AudioContext
159
+ if (audioContext.state === "running") {
160
+ $buttonDsp.textContent = "Suspended";
161
+ await audioContext.suspend();
162
+ } else if (audioContext.state === "suspended") {
163
+ $buttonDsp.textContent = "Running";
164
+ await audioContext.resume();
165
+ }
166
+ }
@@ -835,11 +835,11 @@ export declare class FaustBaseWebAudioDsp implements IFaustBaseWebAudioDsp {
835
835
  getUI(): FaustUIDescriptor;
836
836
  getDescriptors(): FaustUIInputItem[];
837
837
  hasSoundfiles(): boolean;
838
+ startSensors(): void;
839
+ stopSensors(): void;
838
840
  start(): void;
839
841
  stop(): void;
840
842
  destroy(): void;
841
- startSensors(): void;
842
- stopSensors(): void;
843
843
  }
844
844
  export declare class FaustMonoWebAudioDsp extends FaustBaseWebAudioDsp implements IFaustMonoWebAudioDsp {
845
845
  private fInstance;
package/dist/cjs/index.js CHANGED
@@ -2482,6 +2482,12 @@ export default ${(_b = jsCode.match(jsCodeHead)) == null ? void 0 : _b[1]};
2482
2482
  hasSoundfiles() {
2483
2483
  return this.fSoundfiles.length > 0;
2484
2484
  }
2485
+ startSensors() {
2486
+ this.startSensors();
2487
+ }
2488
+ stopSensors() {
2489
+ this.stopSensors();
2490
+ }
2485
2491
  start() {
2486
2492
  this.fProcessing = true;
2487
2493
  }
@@ -2494,12 +2500,6 @@ export default ${(_b = jsCode.match(jsCodeHead)) == null ? void 0 : _b[1]};
2494
2500
  this.fComputeHandler = null;
2495
2501
  this.fPlotHandler = null;
2496
2502
  }
2497
- startSensors() {
2498
- this.startSensors();
2499
- }
2500
- stopSensors() {
2501
- this.stopSensors();
2502
- }
2503
2503
  };
2504
2504
  var FaustMonoWebAudioDsp = class extends FaustBaseWebAudioDsp {
2505
2505
  constructor(instance, sampleRate, sampleSize, bufferSize, soundfiles) {
@@ -3948,42 +3948,14 @@ export default ${(_b = jsCode.match(jsCodeHead)) == null ? void 0 : _b[1]};
3948
3948
  async startSensors() {
3949
3949
  if (this.hasAccInput) {
3950
3950
  if (window.DeviceMotionEvent) {
3951
- if (typeof window.DeviceMotionEvent.requestPermission === "function") {
3952
- try {
3953
- const response = await window.DeviceMotionEvent.requestPermission();
3954
- if (response === "granted") {
3955
- window.addEventListener("devicemotion", this.handleDeviceMotion, true);
3956
- } else if (response === "denied") {
3957
- alert("You have denied access to motion and orientation data. To enable it, go to Settings > Safari > Motion & Orientation Access.");
3958
- throw new Error("Unable to access the accelerometer.");
3959
- }
3960
- } catch (error) {
3961
- console.error(error);
3962
- }
3963
- } else {
3964
- window.addEventListener("devicemotion", this.handleDeviceMotion, true);
3965
- }
3951
+ window.addEventListener("devicemotion", this.handleDeviceMotion, true);
3966
3952
  } else {
3967
3953
  console.log("Cannot set the accelerometer handler.");
3968
3954
  }
3969
3955
  }
3970
3956
  if (this.hasGyrInput) {
3971
3957
  if (window.DeviceMotionEvent) {
3972
- if (typeof window.DeviceOrientationEvent.requestPermission === "function") {
3973
- try {
3974
- const response = await window.DeviceOrientationEvent.requestPermission();
3975
- if (response === "granted") {
3976
- window.addEventListener("deviceorientation", this.handleDeviceOrientation, true);
3977
- } else if (response === "denied") {
3978
- alert("You have denied access to motion and orientation data. To enable it, go to Settings > Safari > Motion & Orientation Access.");
3979
- throw new Error("Unable to access the gyroscope.");
3980
- }
3981
- } catch (error) {
3982
- console.error(error);
3983
- }
3984
- } else {
3985
- window.addEventListener("deviceorientation", this.handleDeviceOrientation, true);
3986
- }
3958
+ window.addEventListener("deviceorientation", this.handleDeviceOrientation, true);
3987
3959
  } else {
3988
3960
  console.log("Cannot set the gyroscope handler.");
3989
3961
  }