@grame/faustwasm 0.2.0 → 0.2.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@grame/faustwasm",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "WebAssembly version of Faust Compiler",
5
5
  "main": "dist/cjs/index.js",
6
6
  "types": "dist/esm/index.d.ts",
@@ -7,10 +7,24 @@ import { FaustMonoOfflineProcessor, FaustPolyOfflineProcessor, IFaustMonoOffline
7
7
  import { FaustMonoScriptProcessorNode, FaustPolyScriptProcessorNode } from "./FaustScriptProcessorNode";
8
8
  import { FaustBaseWebAudioDsp, FaustMonoWebAudioDsp, FaustPolyWebAudioDsp, FaustWebAudioDspVoice, IFaustMonoWebAudioNode, IFaustPolyWebAudioNode, Soundfile, WasmAllocator } from "./FaustWebAudioDsp";
9
9
  import type { IFaustCompiler } from "./FaustCompiler";
10
- import type { FaustDspFactory, FaustUIDescriptor, FaustDspMeta, FFTUtils, LooseFaustDspFactory } from "./types";
10
+ import type { FaustDspFactory, FaustUIDescriptor, FaustDspMeta, FFTUtils, LooseFaustDspFactory, AudioData } from "./types";
11
11
  import SoundfileReader from "./SoundfileReader";
12
12
 
13
- export interface IFaustMonoDspGenerator {
13
+ export interface GeneratorSupportingSoundfiles {
14
+ /**
15
+ * Attach a map of id - audio data, call after `compile()` before `createNode()`
16
+ *
17
+ * @param soundfileMap a map of id - `AudioData` as an object where `AudioData` contains channel data as `audioBuffer: Float32Array[]` and `sampleRate: number`
18
+ */
19
+ addSoundfiles(soundfileMap: Record<string, AudioData>): void;
20
+
21
+ /**
22
+ * Get a list of soundfiles needed, call after `compile()`
23
+ */
24
+ getSoundfileList(): string[];
25
+ }
26
+
27
+ export interface IFaustMonoDspGenerator extends GeneratorSupportingSoundfiles {
14
28
  /**
15
29
  * Compile a monophonic DSP factory from given code.
16
30
  *
@@ -26,6 +40,7 @@ export interface IFaustMonoDspGenerator {
26
40
  meta?: FaustDspMeta;
27
41
  } | null>;
28
42
 
43
+
29
44
  /**
30
45
  * Create a monophonic WebAudio node (either ScriptProcessorNode or AudioWorkletNode).
31
46
  *
@@ -102,7 +117,7 @@ export interface IFaustMonoDspGenerator {
102
117
  getUI(): FaustUIDescriptor;
103
118
  }
104
119
 
105
- export interface IFaustPolyDspGenerator {
120
+ export interface IFaustPolyDspGenerator extends GeneratorSupportingSoundfiles {
106
121
  /**
107
122
  * Compile a monophonic DSP factory from given code.
108
123
  *
@@ -205,6 +220,19 @@ export class FaustMonoDspGenerator implements IFaustMonoDspGenerator {
205
220
  }
206
221
  }
207
222
 
223
+ addSoundfiles(soundfileMap: Record<string, AudioData>) {
224
+ if (!this.factory) throw new Error("Code is not compiled, please define the factory or call `await this.compile()` first.");
225
+ for (const id in soundfileMap) {
226
+ this.factory.soundfiles[id] = soundfileMap[id];
227
+ }
228
+ }
229
+ getSoundfileList() {
230
+ if (!this.factory) throw new Error("Code is not compiled, please define the factory or call `await this.compile()` first.");
231
+ const meta = JSON.parse(this.factory.json);
232
+ const map = SoundfileReader.findSoundfilesFromMeta(meta);
233
+ return Object.keys(map);
234
+ }
235
+
208
236
  async createNode<SP extends boolean = false>(
209
237
  context: BaseAudioContext,
210
238
  name = this.name,
@@ -507,6 +535,22 @@ process = adaptorIns(dsp_code.process) : dsp_code.effect : adaptorOuts;
507
535
  }
508
536
  }
509
537
 
538
+ addSoundfiles(soundfileMap: Record<string, AudioData>) {
539
+ if (!this.voiceFactory) throw new Error("Code is not compiled, please define the factory or call `await this.compile()` first.");
540
+ for (const id in soundfileMap) {
541
+ this.voiceFactory.soundfiles[id] = soundfileMap[id];
542
+ }
543
+ }
544
+ getSoundfileList() {
545
+ if (!this.voiceFactory) throw new Error("Code is not compiled, please define the factory or call `await this.compile()` first.");
546
+ const meta = JSON.parse(this.voiceFactory.json);
547
+ const map = SoundfileReader.findSoundfilesFromMeta(meta);
548
+ if (!this.effectFactory) return Object.keys(map);
549
+ const effectMeta = JSON.parse(this.effectFactory.json);
550
+ const effectMap = SoundfileReader.findSoundfilesFromMeta(effectMeta);
551
+ return Object.keys({ ...effectMap, ...map });
552
+ }
553
+
510
554
  async createNode<SP extends boolean = false>(
511
555
  context: BaseAudioContext,
512
556
  voices: number,
@@ -3,7 +3,7 @@ import type { AudioData, FaustDspMeta, FaustUIItem, LooseFaustDspFactory } from
3
3
 
4
4
  /** Read metadata and fetch soundfiles */
5
5
  class SoundfileReader {
6
- static get fallbackPaths() { return [location.href, location.origin, "http://127.0.0.1:8000"]; }
6
+ static get fallbackPaths() { return [location.href, location.origin]; }
7
7
 
8
8
  /**
9
9
  * Convert an audio buffer to audio data.
@@ -25,7 +25,7 @@ class SoundfileReader {
25
25
  * @param dspMeta : the metadata
26
26
  * @returns : the URLs
27
27
  */
28
- private static findSoundfilesFromMeta(dspMeta: FaustDspMeta): LooseFaustDspFactory["soundfiles"] {
28
+ static findSoundfilesFromMeta(dspMeta: FaustDspMeta): LooseFaustDspFactory["soundfiles"] {
29
29
  const soundfiles: LooseFaustDspFactory["soundfiles"] = {};
30
30
  const callback = (item: FaustUIItem) => {
31
31
  if (item.type === "soundfile") {
@@ -1196,7 +1196,7 @@ export declare class SoundfileReader {
1196
1196
  * @param dspMeta : the metadata
1197
1197
  * @returns : the URLs
1198
1198
  */
1199
- private static findSoundfilesFromMeta;
1199
+ static findSoundfilesFromMeta(dspMeta: FaustDspMeta): LooseFaustDspFactory["soundfiles"];
1200
1200
  /**
1201
1201
  * Check if the file exists.
1202
1202
  *
@@ -1336,7 +1336,19 @@ export declare class FaustPolyScriptProcessorNode extends FaustScriptProcessorNo
1336
1336
  keyOff(channel: number, pitch: number, velocity: number): void;
1337
1337
  allNotesOff(hard: boolean): void;
1338
1338
  }
1339
- export interface IFaustMonoDspGenerator {
1339
+ export interface GeneratorSupportingSoundfiles {
1340
+ /**
1341
+ * Attach a map of id - audio data, call after `compile()` before `createNode()`
1342
+ *
1343
+ * @param soundfileMap a map of id - `AudioData` as an object where `AudioData` contains channel data as `audioBuffer: Float32Array[]` and `sampleRate: number`
1344
+ */
1345
+ addSoundfiles(soundfileMap: Record<string, AudioData>): void;
1346
+ /**
1347
+ * Get a list of soundfiles needed, call after `compile()`
1348
+ */
1349
+ getSoundfileList(): string[];
1350
+ }
1351
+ export interface IFaustMonoDspGenerator extends GeneratorSupportingSoundfiles {
1340
1352
  /**
1341
1353
  * Compile a monophonic DSP factory from given code.
1342
1354
  *
@@ -1403,7 +1415,7 @@ export interface IFaustMonoDspGenerator {
1403
1415
  */
1404
1416
  getUI(): FaustUIDescriptor;
1405
1417
  }
1406
- export interface IFaustPolyDspGenerator {
1418
+ export interface IFaustPolyDspGenerator extends GeneratorSupportingSoundfiles {
1407
1419
  /**
1408
1420
  * Compile a monophonic DSP factory from given code.
1409
1421
  *
@@ -1468,6 +1480,8 @@ export declare class FaustMonoDspGenerator implements IFaustMonoDspGenerator {
1468
1480
  factory: FaustDspFactory | null;
1469
1481
  constructor();
1470
1482
  compile(compiler: IFaustCompiler, name: string, code: string, args: string): Promise<this | null>;
1483
+ addSoundfiles(soundfileMap: Record<string, AudioData>): void;
1484
+ getSoundfileList(): string[];
1471
1485
  createNode<SP extends boolean = false>(context: BaseAudioContext, name?: string, factory?: LooseFaustDspFactory, sp?: SP, bufferSize?: number, processorName?: string): Promise<SP extends true ? FaustMonoScriptProcessorNode | null : FaustMonoAudioWorkletNode | null>;
1472
1486
  createFFTNode(context: BaseAudioContext, fftUtils: typeof FFTUtils, name?: string, factory?: LooseFaustDspFactory, fftOptions?: Partial<FaustFFTOptionsData>, processorName?: string): Promise<FaustMonoAudioWorkletNode | null>;
1473
1487
  createAudioWorkletProcessor(name?: string, factory?: LooseFaustDspFactory, processorName?: string): Promise<{
@@ -1489,6 +1503,8 @@ export declare class FaustPolyDspGenerator implements IFaustPolyDspGenerator {
1489
1503
  mixerModule: WebAssembly.Module;
1490
1504
  constructor();
1491
1505
  compile(compiler: IFaustCompiler, name: string, dspCodeAux: string, args: string, effectCodeAux?: string): Promise<this | null>;
1506
+ addSoundfiles(soundfileMap: Record<string, AudioData>): void;
1507
+ getSoundfileList(): string[];
1492
1508
  createNode<SP extends boolean = false>(context: BaseAudioContext, voices: number, name?: string, voiceFactory?: LooseFaustDspFactory, mixerModule?: WebAssembly.Module, effectFactory?: LooseFaustDspFactory | null, sp?: SP, bufferSize?: number, processorName?: string): Promise<SP extends true ? FaustPolyScriptProcessorNode | null : FaustPolyAudioWorkletNode | null>;
1493
1509
  createAudioWorkletProcessor(name?: string, voiceFactory?: LooseFaustDspFactory, effectFactory?: LooseFaustDspFactory | null, processorName?: string): Promise<{
1494
1510
  new (options: AudioWorkletNodeOptions): AudioWorkletProcessor;
@@ -3111,7 +3111,7 @@ var WavDecoder_default = WavDecoder;
3111
3111
  // src/SoundfileReader.ts
3112
3112
  var SoundfileReader = class {
3113
3113
  static get fallbackPaths() {
3114
- return [location.href, location.origin, "http://127.0.0.1:8000"];
3114
+ return [location.href, location.origin];
3115
3115
  }
3116
3116
  /**
3117
3117
  * Convert an audio buffer to audio data.
@@ -3544,6 +3544,20 @@ var _FaustMonoDspGenerator = class _FaustMonoDspGenerator {
3544
3544
  return null;
3545
3545
  }
3546
3546
  }
3547
+ addSoundfiles(soundfileMap) {
3548
+ if (!this.factory)
3549
+ throw new Error("Code is not compiled, please define the factory or call `await this.compile()` first.");
3550
+ for (const id in soundfileMap) {
3551
+ this.factory.soundfiles[id] = soundfileMap[id];
3552
+ }
3553
+ }
3554
+ getSoundfileList() {
3555
+ if (!this.factory)
3556
+ throw new Error("Code is not compiled, please define the factory or call `await this.compile()` first.");
3557
+ const meta = JSON.parse(this.factory.json);
3558
+ const map = SoundfileReader_default.findSoundfilesFromMeta(meta);
3559
+ return Object.keys(map);
3560
+ }
3547
3561
  async createNode(context, name = this.name, factory = this.factory, sp = false, bufferSize = 1024, processorName = (factory == null ? void 0 : factory.shaKey) || name) {
3548
3562
  var _a, _b;
3549
3563
  if (!factory)
@@ -3796,6 +3810,24 @@ process = adaptorIns(dsp_code.process) : dsp_code.effect : adaptorOuts;
3796
3810
  return null;
3797
3811
  }
3798
3812
  }
3813
+ addSoundfiles(soundfileMap) {
3814
+ if (!this.voiceFactory)
3815
+ throw new Error("Code is not compiled, please define the factory or call `await this.compile()` first.");
3816
+ for (const id in soundfileMap) {
3817
+ this.voiceFactory.soundfiles[id] = soundfileMap[id];
3818
+ }
3819
+ }
3820
+ getSoundfileList() {
3821
+ if (!this.voiceFactory)
3822
+ throw new Error("Code is not compiled, please define the factory or call `await this.compile()` first.");
3823
+ const meta = JSON.parse(this.voiceFactory.json);
3824
+ const map = SoundfileReader_default.findSoundfilesFromMeta(meta);
3825
+ if (!this.effectFactory)
3826
+ return Object.keys(map);
3827
+ const effectMeta = JSON.parse(this.effectFactory.json);
3828
+ const effectMap = SoundfileReader_default.findSoundfilesFromMeta(effectMeta);
3829
+ return Object.keys({ ...effectMap, ...map });
3830
+ }
3799
3831
  async createNode(context, voices, name = this.name, voiceFactory = this.voiceFactory, mixerModule = this.mixerModule, effectFactory = this.effectFactory, sp = false, bufferSize = 1024, processorName = ((voiceFactory == null ? void 0 : voiceFactory.shaKey) || "") + ((effectFactory == null ? void 0 : effectFactory.shaKey) || "") || `${name}_poly`) {
3800
3832
  var _a, _b;
3801
3833
  if (!voiceFactory)