@grame/faustwasm 0.4.9 → 0.5.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 CHANGED
@@ -59,17 +59,34 @@ node scripts/faust2wasm.js test/poly.dsp test/out -poly
59
59
  ```
60
60
  will create a set of files: `index.js`, `dsp-module.wasm`, `dsp-meta.json`, `index.html` (and possibly `effect-module.wasm`, `effect-meta.json`) in the `out` folder.
61
61
 
62
-
63
- #### Creating a Progressive Web Application of a Faust DSP
62
+ #### Creating a Progressive Web Application (PWA) of a Faust DSP
64
63
 
65
64
  You can create a standalone Progressive Web Application using the same command line:
66
65
 
66
+ ```bash
67
+ node scripts/faust2wasm.js test/rev.dsp test/rev -pwa
68
+ ```
69
+ will create a set of files: `icon.png`, `service-worker.js`, `manifest.json`, `index.js`, `dsp-module.wasm`, `dsp-meta.json`, `index.html`, and the `faustwasm`, `faust-ui` folders in the `rev` folder.
70
+
71
+ The folder contains the necessary ressources to deploy the Faust application as a PWA on a server, to be installed and used offline. Note that audio files used by the `soundfile` primitives in the DSP code will have to be mannually added in the folder.
72
+
73
+ A standalone polyphonic and MIDI standalone Progressive Web Application can be created with:
74
+
75
+ ```bash
76
+ node scripts/faust2wasm.js test/organ1.dsp test/organ1 -poly -pwa
77
+ ```
78
+ will create a set of files: `icon.png`, `service-worker.js`, `manifest.json`, `index.js`, `dsp-module.wasm`, `dsp-meta.json`, `effect-module.wasm`, `effect-meta.json`, `index.html`, and the `faustwasm`, `faust-ui` folders in the `organ1` folder.
79
+
80
+ #### Creating a standalone version of a Faust DSP, with audio and MIDI devices selector
81
+
82
+ You can create a standalone using the same command line:
83
+
67
84
  ```bash
68
85
  node scripts/faust2wasm.js test/rev.dsp test/rev -standalone
69
86
  ```
70
87
  will create a set of files: `icon.png`, `service-worker.js`, `manifest.json`, `index.js`, `dsp-module.wasm`, `dsp-meta.json`, `index.html`, and the `faustwasm`, `faust-ui` folders in the `rev` folder.
71
88
 
72
- The folder contains the necessary ressources to deploy the Faust application as a PWA on a server, to be installed and used offline. Note that audio files used by the `soundfile` primitives in the DSP code will have to be mannually added in the folder. To test, be sure to launch a local web server at the `test` folder level, then go inside `test\rev` folder.
89
+ The folder contains the necessary ressources to deploy the Faust application as a PWA on a server, to be installed and used offline. Note that audio files used by the `soundfile` primitives in the DSP code will have to be mannually added in the folder.
73
90
 
74
91
  A standalone polyphonic and MIDI standalone Progressive Web Application can be created with:
75
92
 
@@ -78,8 +95,6 @@ node scripts/faust2wasm.js test/organ1.dsp test/organ1 -poly -standalone
78
95
  ```
79
96
  will create a set of files: `icon.png`, `service-worker.js`, `manifest.json`, `index.js`, `dsp-module.wasm`, `dsp-meta.json`, `effect-module.wasm`, `effect-meta.json`, `index.html`, and the `faustwasm`, `faust-ui` folders in the `organ1` folder.
80
97
 
81
- To test, be sure to launch a local web server at the `test` folder level, then go inside `test\organ1` folder.
82
-
83
98
  #### Generate SVG Diagrams of a Faust DSP
84
99
 
85
100
  For example:
@@ -0,0 +1,76 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+
4
+ <link rel="manifest" href="./manifest.json">
5
+
6
+ <head>
7
+ <meta charset="UTF-8">
8
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
9
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
10
+ <title>Faust DSP</title>
11
+ <style>
12
+ body {
13
+ color: #b0b0b0;
14
+ background-color: #1f1f1f;
15
+ display: flex;
16
+ top: 0;
17
+ left: 0;
18
+ width: 100%;
19
+ height: 100%;
20
+ margin: 0;
21
+ position: absolute;
22
+ }
23
+
24
+ main {
25
+ margin: 20px;
26
+ display: flex;
27
+ flex-direction: column;
28
+ flex: 1 1 100%;
29
+ }
30
+
31
+ main span {
32
+ position: relative;
33
+ display: flex;
34
+ }
35
+
36
+ main span[hidden] {
37
+ display: none;
38
+ }
39
+
40
+ main span span {
41
+ margin: 0px 10px;
42
+ flex: 1;
43
+ }
44
+
45
+ main span select {
46
+ flex: 2;
47
+ }
48
+
49
+ #dsp-switch {
50
+ margin: 20px auto;
51
+ }
52
+
53
+ #button-dsp {
54
+ padding: 10px;
55
+ }
56
+
57
+ #div-faust-ui {
58
+ flex: 1 1 auto;
59
+ display: flex;
60
+ position: relative;
61
+ flex-direction: column;
62
+ color: black;
63
+ }
64
+ </style>
65
+ <link rel="stylesheet" href="./faust-ui/index.css">
66
+ </head>
67
+
68
+ <body>
69
+ <main>
70
+ <div id="div-faust-ui">
71
+ </div>
72
+ </main>
73
+ <script src="./index.js"></script>
74
+ </body>
75
+
76
+ </html>
@@ -0,0 +1,133 @@
1
+ // Set to > 0 if the DSP is polyphonic
2
+ const FAUST_DSP_VOICES = 0;
3
+
4
+ /**
5
+ * @typedef {import("./faustwasm").FaustAudioWorkletNode} FaustAudioWorkletNode
6
+ * @typedef {import("./faustwasm").FaustDspMeta} FaustDspMeta
7
+ * @typedef {import("./faustwasm").FaustUIDescriptor} FaustUIDescriptor
8
+ * @typedef {import("./faustwasm").FaustUIGroup} FaustUIGroup
9
+ * @typedef {import("./faustwasm").FaustUIItem} FaustUIItem
10
+ */
11
+
12
+ /**
13
+ * Registers the service worker.
14
+ */
15
+ if ("serviceWorker" in navigator) {
16
+ window.addEventListener("load", () => {
17
+ navigator.serviceWorker.register("./service-worker.js")
18
+ .then(reg => console.log("Service Worker registered", reg))
19
+ .catch(err => console.log("Service Worker registration failed", err));
20
+ });
21
+ }
22
+
23
+ /** @type {HTMLDivElement} */
24
+ const $divFaustUI = document.getElementById("div-faust-ui");
25
+
26
+ /** @type {typeof AudioContext} */
27
+ const AudioCtx = window.AudioContext || window.webkitAudioContext;
28
+ const audioContext = new AudioCtx({ latencyHint: 0.00001 });
29
+ audioContext.destination.channelInterpretation = "discrete";
30
+ audioContext.suspend();
31
+
32
+ /**
33
+ * @param {FaustAudioWorkletNode} faustNode
34
+ */
35
+ const createFaustUI = async (faustNode) => {
36
+ const { FaustUI } = await import("./faust-ui/index.js");
37
+ const $container = document.createElement("div");
38
+ $container.style.margin = "0";
39
+ $container.style.position = "absolute";
40
+ $container.style.overflow = "auto";
41
+ $container.style.display = "flex";
42
+ $container.style.flexDirection = "column";
43
+ $container.style.width = "100%";
44
+ $container.style.height = "100%";
45
+ $divFaustUI.appendChild($container);
46
+ const faustUI = new FaustUI({
47
+ ui: faustNode.getUI(),
48
+ root: $container,
49
+ listenWindowMessage: false,
50
+ listenWindowResize: true,
51
+ });
52
+ faustUI.paramChangeByUI = (path, value) => faustNode.setParamValue(path, value);
53
+ faustNode.setOutputParamHandler((path, value) => faustUI.paramChangeByDSP(path, value));
54
+ $container.style.minWidth = `${faustUI.minWidth}px`;
55
+ $container.style.minHeight = `${faustUI.minHeight}px`;
56
+ faustUI.resize();
57
+ };
58
+
59
+ (async () => {
60
+
61
+ const { default: createFaustNode } = await import("./create-node.js");
62
+
63
+ // To test the ScriptProcessorNode mode
64
+ // const { faustNode, dspMeta: { name } } = await createFaustNode(audioContext, "osc", FAUST_DSP_VOICES, true);
65
+ const { faustNode, dspMeta: { name } } = await createFaustNode(audioContext, "osc", FAUST_DSP_VOICES);
66
+ if (!faustNode) throw new Error("Faust DSP not compiled");
67
+
68
+ // Create the Faust UI
69
+ await createFaustUI(faustNode);
70
+
71
+ // Connect the Faust node to the audio context
72
+ faustNode.connect(audioContext.destination);
73
+
74
+ // Activate sensor listeners
75
+ await faustNode.listenSensors();
76
+
77
+ // Function to initialize MIDI
78
+ function initMIDI() {
79
+ // Check if the browser supports the Web MIDI API
80
+ if (navigator.requestMIDIAccess) {
81
+ navigator.requestMIDIAccess()
82
+ .then(onMIDISuccess, onMIDIFailure);
83
+ } else {
84
+ console.log("Web MIDI API is not supported in this browser.");
85
+ }
86
+ }
87
+
88
+ // Success callback for requesting MIDI access
89
+ function onMIDISuccess(midiAccess) {
90
+ console.log("MIDI Access obtained.");
91
+ // Iterate through all available MIDI inputs
92
+ for (let input of midiAccess.inputs.values()) {
93
+ // Attach the event listener to each input
94
+ input.onmidimessage = handleMIDIMessage;
95
+ console.log(`Connected to input: ${input.name}`);
96
+ }
97
+ }
98
+
99
+ // Failure callback for requesting MIDI access
100
+ function onMIDIFailure() {
101
+ console.error("Failed to access MIDI devices.");
102
+ }
103
+
104
+ // Dummy event handler for MIDI messages
105
+ function handleMIDIMessage(event) {
106
+ faustNode.midiMessage(event.data);
107
+ }
108
+
109
+ // Initialize the MIDI setup
110
+ if (FAUST_DSP_VOICES > 0) {
111
+ initMIDI();
112
+ }
113
+
114
+ })();
115
+
116
+ // Function to resume AudioContext on user interaction
117
+ function resumeAudioContext() {
118
+ if (audioContext.state === 'suspended') {
119
+ audioContext.resume();
120
+ }
121
+ }
122
+
123
+ // Add event listeners for user interactions
124
+ window.addEventListener('click', resumeAudioContext);
125
+ window.addEventListener('touchstart', resumeAudioContext);
126
+
127
+ // Optional: Remove event listeners once the context is resumed
128
+ audioContext.onstatechange = function () {
129
+ if (audioContext.state === 'running') {
130
+ window.removeEventListener('click', resumeAudioContext);
131
+ window.removeEventListener('touchstart', resumeAudioContext);
132
+ }
133
+ };
package/build ADDED
@@ -0,0 +1,25 @@
1
+ node scripts/faust2wasm.js /Users/letz/Developpements/GameLAN/atomicro/atomicro.dsp /Users/letz/Developpements/sletz.github.io/atomicro -pwa
2
+
3
+ node scripts/faust2wasm.js /Users/letz/Developpements/GameLAN/attackey/attackey.dsp /Users/letz/Developpements/sletz.github.io/attackey -pwa
4
+
5
+ node scripts/faust2wasm.js /Users/letz/Developpements/GameLAN/baliphone/baliphone.dsp /Users/letz/Developpements/sletz.github.io/baliphone -pwa
6
+
7
+ node scripts/faust2wasm.js /Users/letz/Developpements/GameLAN/drone/drone.dsp /Users/letz/Developpements/sletz.github.io/drone -pwa
8
+
9
+ node scripts/faust2wasm.js /Users/letz/Developpements/GameLAN/sequenceur/sequenceur.dsp /Users/letz/Developpements/sletz.github.io/sequenceur -pwa
10
+
11
+ node scripts/faust2wasm.js /Users/letz/Developpements/GameLAN/shakerxy/shakerxy.dsp /Users/letz/Developpements/sletz.github.io/shakerxy -pwa
12
+
13
+ node scripts/faust2wasm.js /Users/letz/Developpements/GameLAN/sinusoide/sinusoide.dsp /Users/letz/Developpements/sletz.github.io/sinusoide -pwa
14
+
15
+
16
+ #node scripts/faust2wasm.js /Users/letz/Developpements/GameLAN/test.dsp /Users/letz/Developpements/sletz.github.io/out -standalone
17
+ #node scripts/faust2wasm.js test/organ.dsp /Users/letz/Developpements/sletz.github.io/organ -poly -standalone
18
+
19
+ #node scripts/faust2wasm.js test/organ1.dsp /Users/letz/Developpements/sletz.github.io/organ1 -poly -standalone
20
+
21
+ #node scripts/faust2wasm.js test/osc2.dsp /Users/letz/Developpements/sletz.github.io/osc2 -standalone
22
+
23
+ #node scripts/faust2wasm.js /Users/letz/Developpements/faust-sampler/sampler.dsp /Users/letz/Developpements/sletz.github.io/sampler -poly -standalone
24
+
25
+ #node scripts/faust2wasm.js /Users/letz/Developpements/faust-sampler/piano.dsp /Users/letz/Developpements/sletz.github.io/piano -poly -standalone