@grame/faustwasm 0.12.1 → 0.13.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/.prettierrc +5 -0
- package/README.md +21 -3
- package/assets/standalone/faustwasm/index.d.ts +39 -17
- package/assets/standalone/faustwasm/index.js +1580 -408
- package/assets/standalone/faustwasm/index.js.map +2 -2
- package/dist/cjs/index.d.ts +39 -17
- package/dist/cjs/index.js +1579 -408
- package/dist/cjs/index.js.map +2 -2
- package/dist/cjs-bundle/index.d.ts +39 -17
- package/dist/cjs-bundle/index.js +1582 -410
- package/dist/cjs-bundle/index.js.map +2 -2
- package/dist/esm/index.d.ts +39 -17
- package/dist/esm/index.js +1580 -408
- package/dist/esm/index.js.map +2 -2
- package/dist/esm-bundle/index.d.ts +39 -17
- package/dist/esm-bundle/index.js +1582 -410
- package/dist/esm-bundle/index.js.map +2 -2
- package/eslint.config.js +11 -0
- package/package.json +57 -51
- package/sound.cpp +163 -0
- package/sound.dsp +4 -0
- package/sound.json +1 -0
- package/sound.wasm +0 -0
- package/src/FaustAudioWorkletCommunicator.ts +150 -143
- package/src/FaustAudioWorkletNode.ts +173 -75
- package/src/FaustAudioWorkletProcessor.ts +218 -90
- package/src/FaustCmajor.ts +9 -3
- package/src/FaustCompiler.ts +112 -35
- package/src/FaustDspGenerator.ts +563 -118
- package/src/FaustDspInstance.ts +58 -24
- package/src/FaustFFTAudioWorkletProcessor.ts +822 -612
- package/src/FaustOfflineProcessor.ts +187 -56
- package/src/FaustScriptProcessorNode.ts +156 -49
- package/src/FaustSensors.ts +426 -96
- package/src/FaustSvgDiagrams.ts +18 -5
- package/src/FaustWasmInstantiator.ts +224 -70
- package/src/FaustWebAudioDsp.ts +1062 -351
- package/src/LibFaust.ts +13 -4
- package/src/SoundfileReader.ts +175 -131
- package/src/WavDecoder.ts +42 -20
- package/src/WavEncoder.ts +35 -21
- package/src/copyWebStandaloneAssets.d.ts +20 -5
- package/src/copyWebStandaloneAssets.js +203 -75
- package/src/exports-bundle.ts +5 -5
- package/src/exports.ts +24 -24
- package/src/faust2CmajorFiles.d.ts +7 -3
- package/src/faust2cmajorFiles.js +10 -8
- package/src/faust2svgFiles.d.ts +7 -3
- package/src/faust2svgFiles.js +9 -7
- package/src/faust2wasmFiles.d.ts +10 -5
- package/src/faust2wasmFiles.js +34 -17
- package/src/faust2wavFiles.d.ts +12 -3
- package/src/faust2wavFiles.js +25 -12
- package/src/index-bundle-iife.ts +2 -2
- package/src/index-bundle.ts +1 -1
- package/src/index.ts +1 -1
- package/src/instantiateFaustModule.ts +43 -36
- package/src/instantiateFaustModuleFromFile.ts +30 -14
- package/src/types.ts +102 -26
- package/test/faustlive-wasm/faustwasm/index.d.ts +39 -17
- package/test/faustlive-wasm/faustwasm/index.js +1580 -408
- package/test/faustlive-wasm/faustwasm/index.js.map +2 -2
- package/test/web/create-faust-node.html +53 -0
- package/test/web/create-faust-node.js +186 -0
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
+
<title>createFaustNode Test</title>
|
|
7
|
+
<!-- Ensure root-relative resolution for libfaust assets -->
|
|
8
|
+
<base href="/" />
|
|
9
|
+
<style>
|
|
10
|
+
body { font-family: sans-serif; margin: 1.5rem; }
|
|
11
|
+
button { padding: 0.5rem 1rem; margin-top: 1rem; }
|
|
12
|
+
pre { background: #f6f6f6; padding: 1rem; border-radius: 4px; }
|
|
13
|
+
</style>
|
|
14
|
+
</head>
|
|
15
|
+
<body>
|
|
16
|
+
<h1>createFaustNode Test</h1>
|
|
17
|
+
<p>This page exercises <code>createFaustNode</code> for mono and poly DSP snippets. Serve the repo root (so <code>dist/</code> and <code>libfaust-wasm/</code> are reachable) and run <code>npm run build</code> first.</p>
|
|
18
|
+
<button id="run">Run tests</button>
|
|
19
|
+
<pre id="log"></pre>
|
|
20
|
+
|
|
21
|
+
<script type="module">
|
|
22
|
+
import { runTests } from '/test/web/create-faust-node.js';
|
|
23
|
+
|
|
24
|
+
const logEl = document.getElementById('log');
|
|
25
|
+
const runBtn = document.getElementById('run');
|
|
26
|
+
|
|
27
|
+
const originalLog = console.log.bind(console);
|
|
28
|
+
const originalErr = console.error.bind(console);
|
|
29
|
+
const append = (label, msg) => {
|
|
30
|
+
logEl.textContent += `${label}: ${msg}\n`;
|
|
31
|
+
logEl.scrollTop = logEl.scrollHeight;
|
|
32
|
+
};
|
|
33
|
+
console.log = (...args) => {
|
|
34
|
+
append('LOG', args.join(' '));
|
|
35
|
+
originalLog(...args);
|
|
36
|
+
};
|
|
37
|
+
console.error = (...args) => {
|
|
38
|
+
append('ERR', args.join(' '));
|
|
39
|
+
originalErr(...args);
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
runBtn.addEventListener('click', async () => {
|
|
43
|
+
append('INFO', 'Starting tests…');
|
|
44
|
+
try {
|
|
45
|
+
await runTests();
|
|
46
|
+
append('INFO', 'Tests triggered (check audio/console logs).');
|
|
47
|
+
} catch (e) {
|
|
48
|
+
append('ERR', `Failed to start tests: ${e.message || e}`);
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
</script>
|
|
52
|
+
</body>
|
|
53
|
+
</html>
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
// Simple browser-side sanity test for `createFaustNode` in `FaustDspGenerator`.
|
|
2
|
+
// Serve the repository root (e.g. `python -m http.server` from repo root) so that
|
|
3
|
+
// `dist/` and `libfaust-wasm/` are reachable. Then open `test/web/create-faust-node.html`.
|
|
4
|
+
|
|
5
|
+
const monoCode = `
|
|
6
|
+
import("stdfaust.lib");
|
|
7
|
+
process = os.osc(220) * 0.05;
|
|
8
|
+
`;
|
|
9
|
+
|
|
10
|
+
const polyCode = `
|
|
11
|
+
declare options "[nvoices:4][midi:on]";
|
|
12
|
+
import("stdfaust.lib");
|
|
13
|
+
freq = hslider("freq", 440, 50, 2000, 1);
|
|
14
|
+
gain = hslider("gain", 0.5, 0, 1, 0.01);
|
|
15
|
+
gate = button("gate");
|
|
16
|
+
process = gain * os.osc(freq) * gate;
|
|
17
|
+
`;
|
|
18
|
+
|
|
19
|
+
const polyEffectCode = `
|
|
20
|
+
declare options "[nvoices:4][midi:on]";
|
|
21
|
+
import("stdfaust.lib");
|
|
22
|
+
freq = hslider("freq", 440, 50, 2000, 1);
|
|
23
|
+
gain = hslider("gain", 0.5, 0, 1, 0.01);
|
|
24
|
+
gate = button("gate");
|
|
25
|
+
synth = gain * os.osc(freq) * gate;
|
|
26
|
+
process = synth, synth : dm.zita_light;
|
|
27
|
+
`;
|
|
28
|
+
|
|
29
|
+
const audioContext = new AudioContext({ latencyHint: 'interactive' });
|
|
30
|
+
const wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
31
|
+
|
|
32
|
+
async function runMonoPolyTest(modeLabel, sp = false, bufferSize) {
|
|
33
|
+
const { FaustDspGenerator } = await import(
|
|
34
|
+
new URL('../../dist/esm/index.js', import.meta.url)
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
if (sp && typeof audioContext.createScriptProcessor !== 'function') {
|
|
38
|
+
console.warn('[test]', 'ScriptProcessor not supported; skipping test');
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const log = (...args) => console.log('[test]', ...args);
|
|
43
|
+
const error = (...args) => console.error('[test]', ...args);
|
|
44
|
+
|
|
45
|
+
try {
|
|
46
|
+
log(`Starting ${modeLabel} mono test for 5 seconds…`);
|
|
47
|
+
const monoGenerator = new FaustDspGenerator();
|
|
48
|
+
const monoNode = await monoGenerator.createFaustNode(
|
|
49
|
+
audioContext,
|
|
50
|
+
`${modeLabel}_mono_test`,
|
|
51
|
+
monoCode,
|
|
52
|
+
sp,
|
|
53
|
+
bufferSize
|
|
54
|
+
);
|
|
55
|
+
if (!monoNode) {
|
|
56
|
+
error(`${modeLabel} mono createFaustNode failed`);
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
monoNode.connect(audioContext.destination);
|
|
60
|
+
log(
|
|
61
|
+
`${modeLabel} mono running; inputs/outputs =`,
|
|
62
|
+
monoNode.numberOfInputs,
|
|
63
|
+
monoNode.numberOfOutputs
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
await wait(5000);
|
|
67
|
+
monoNode.disconnect();
|
|
68
|
+
log(`${modeLabel} mono stopped after 5 seconds; starting poly test…`);
|
|
69
|
+
|
|
70
|
+
const polyGenerator = new FaustDspGenerator();
|
|
71
|
+
const polyNode = await polyGenerator.createFaustNode(
|
|
72
|
+
audioContext,
|
|
73
|
+
`${modeLabel}_poly_test`,
|
|
74
|
+
polyCode,
|
|
75
|
+
sp,
|
|
76
|
+
bufferSize
|
|
77
|
+
);
|
|
78
|
+
if (!polyNode) {
|
|
79
|
+
error(`${modeLabel} poly createFaustNode failed`);
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
polyNode.connect(audioContext.destination);
|
|
83
|
+
log(
|
|
84
|
+
`${modeLabel} poly running; inputs/outputs =`,
|
|
85
|
+
polyNode.numberOfInputs,
|
|
86
|
+
polyNode.numberOfOutputs
|
|
87
|
+
);
|
|
88
|
+
|
|
89
|
+
// Play a short sequence: three consecutive notes, then a triad chord.
|
|
90
|
+
const noteSeq = [
|
|
91
|
+
{ note: 60, vel: 100, dur: 500 },
|
|
92
|
+
{ note: 64, vel: 100, dur: 500 },
|
|
93
|
+
{ note: 67, vel: 100, dur: 500 }
|
|
94
|
+
];
|
|
95
|
+
for (const { note, vel, dur } of noteSeq) {
|
|
96
|
+
log(`${modeLabel} poly keyOn note ${note}`);
|
|
97
|
+
polyNode.keyOn(0, note, vel);
|
|
98
|
+
await wait(dur);
|
|
99
|
+
polyNode.keyOff(0, note, 0);
|
|
100
|
+
log(`${modeLabel} poly keyOff note ${note}`);
|
|
101
|
+
await wait(100);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const chord = [60, 64, 67];
|
|
105
|
+
log(`${modeLabel} poly chord on (C major)`);
|
|
106
|
+
chord.forEach((n) => polyNode.keyOn(0, n, 100));
|
|
107
|
+
await wait(2000);
|
|
108
|
+
chord.forEach((n) => polyNode.keyOff(0, n, 0));
|
|
109
|
+
log(`${modeLabel} poly chord off`);
|
|
110
|
+
polyNode.disconnect();
|
|
111
|
+
log(`${modeLabel} poly stopped`);
|
|
112
|
+
} catch (e) {
|
|
113
|
+
error(`${modeLabel} test error:`, e);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
async function runPolyEffectTest(modeLabel, sp = false, bufferSize) {
|
|
118
|
+
const { FaustDspGenerator } = await import(
|
|
119
|
+
new URL('../../dist/esm/index.js', import.meta.url)
|
|
120
|
+
);
|
|
121
|
+
|
|
122
|
+
if (sp && typeof audioContext.createScriptProcessor !== 'function') {
|
|
123
|
+
console.warn('[test]', 'ScriptProcessor not supported; skipping test');
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
const log = (...args) => console.log('[test]', ...args);
|
|
128
|
+
const error = (...args) => console.error('[test]', ...args);
|
|
129
|
+
|
|
130
|
+
try {
|
|
131
|
+
log(`Starting ${modeLabel} poly+effect test…`);
|
|
132
|
+
const generator = new FaustDspGenerator();
|
|
133
|
+
const node = await generator.createFaustNode(
|
|
134
|
+
audioContext,
|
|
135
|
+
`${modeLabel}_poly_effect_test`,
|
|
136
|
+
polyEffectCode,
|
|
137
|
+
sp,
|
|
138
|
+
bufferSize
|
|
139
|
+
);
|
|
140
|
+
if (!node) {
|
|
141
|
+
error(`${modeLabel} poly+effect createFaustNode failed`);
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
node.connect(audioContext.destination);
|
|
145
|
+
log(
|
|
146
|
+
`${modeLabel} poly+effect running; inputs/outputs =`,
|
|
147
|
+
node.numberOfInputs,
|
|
148
|
+
node.numberOfOutputs
|
|
149
|
+
);
|
|
150
|
+
|
|
151
|
+
const noteSeq = [
|
|
152
|
+
{ note: 60, vel: 100, dur: 600 },
|
|
153
|
+
{ note: 64, vel: 100, dur: 600 },
|
|
154
|
+
{ note: 67, vel: 100, dur: 600 }
|
|
155
|
+
];
|
|
156
|
+
for (const { note, vel, dur } of noteSeq) {
|
|
157
|
+
log(`${modeLabel} poly+effect keyOn note ${note}`);
|
|
158
|
+
node.keyOn(0, note, vel);
|
|
159
|
+
await wait(dur);
|
|
160
|
+
node.keyOff(0, note, 0);
|
|
161
|
+
log(`${modeLabel} poly+effect keyOff note ${note}`);
|
|
162
|
+
await wait(150);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
const chord = [60, 64, 67];
|
|
166
|
+
log(`${modeLabel} poly+effect chord on (C major)`);
|
|
167
|
+
chord.forEach((n) => node.keyOn(0, n, 100));
|
|
168
|
+
await wait(2500);
|
|
169
|
+
chord.forEach((n) => node.keyOff(0, n, 0));
|
|
170
|
+
log(`${modeLabel} poly+effect chord off`);
|
|
171
|
+
node.disconnect();
|
|
172
|
+
log(`${modeLabel} poly+effect stopped`);
|
|
173
|
+
} catch (e) {
|
|
174
|
+
error(`${modeLabel} poly+effect test error:`, e);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
export async function runTests() {
|
|
179
|
+
await audioContext.resume();
|
|
180
|
+
|
|
181
|
+
// AudioWorklet (default) + ScriptProcessor fallback
|
|
182
|
+
await runMonoPolyTest('AudioWorklet');
|
|
183
|
+
await runPolyEffectTest('AudioWorklet');
|
|
184
|
+
await runMonoPolyTest('ScriptProcessor', true, 1024);
|
|
185
|
+
await runPolyEffectTest('ScriptProcessor', true, 1024);
|
|
186
|
+
}
|