@grame/faustwasm 0.15.6 → 0.16.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.
@@ -729,6 +729,26 @@ export interface IFaustBaseWebAudioDsp {
729
729
  * event: Pick<DeviceOrientationEvent, "alpha" | "beta" | "gamma">
730
730
  */
731
731
  propagateGyr(event: Pick<DeviceOrientationEvent, "alpha" | "beta" | "gamma">): void;
732
+ /**
733
+ * Reinitialize the DSP using its configured sample rate.
734
+ */
735
+ init(): void;
736
+ /**
737
+ * Reinitialize the DSP instance state using its configured sample rate.
738
+ */
739
+ instanceInit(): void;
740
+ /**
741
+ * Clear the DSP instance state.
742
+ */
743
+ instanceClear(): void;
744
+ /**
745
+ * Reinitialize the DSP instance constants using its configured sample rate.
746
+ */
747
+ instanceConstants(): void;
748
+ /**
749
+ * Reset DSP user interface parameters to their default values.
750
+ */
751
+ instanceResetUserInterface(): void;
732
752
  /**
733
753
  * Start the DSP audio processing.
734
754
  */
@@ -903,6 +923,11 @@ export declare class FaustBaseWebAudioDsp implements IFaustBaseWebAudioDsp {
903
923
  hasSoundfiles(): boolean;
904
924
  startSensors(): void;
905
925
  stopSensors(): void;
926
+ init(): void;
927
+ instanceInit(): void;
928
+ instanceClear(): void;
929
+ instanceConstants(): void;
930
+ instanceResetUserInterface(): void;
906
931
  start(): void;
907
932
  stop(): void;
908
933
  destroy(): void;
@@ -910,7 +935,13 @@ export declare class FaustBaseWebAudioDsp implements IFaustBaseWebAudioDsp {
910
935
  export declare class FaustMonoWebAudioDsp extends FaustBaseWebAudioDsp implements IFaustMonoWebAudioDsp {
911
936
  private fInstance;
912
937
  private fDSP;
938
+ private fSampleRate;
913
939
  constructor(instance: FaustMonoDspInstance, sampleRate: number, sampleSize: number, bufferSize: number, soundfiles: LooseFaustDspFactory["soundfiles"]);
940
+ init(): void;
941
+ instanceInit(): void;
942
+ instanceClear(): void;
943
+ instanceConstants(): void;
944
+ instanceResetUserInterface(): void;
914
945
  private initMemory;
915
946
  toString(): string;
916
947
  compute(input: Float32Array[] | ((input: Float32Array[] | Float64Array[]) => any), output: Float32Array[] | ((output: Float32Array[] | Float64Array[]) => any)): boolean;
@@ -938,6 +969,7 @@ export declare class FaustWebAudioDspVoice {
938
969
  private fVelLabel;
939
970
  private fDSP;
940
971
  private fAPI;
972
+ private fSampleRate;
941
973
  fCurNote: number;
942
974
  fNextNote: number;
943
975
  fNextVel: number;
@@ -948,6 +980,11 @@ export declare class FaustWebAudioDspVoice {
948
980
  }, sampleRate: number);
949
981
  static midiToFreq(note: number): number;
950
982
  static normalizeVelocity(velocity: number): number;
983
+ init(sampleRate: number): void;
984
+ instanceInit(): void;
985
+ instanceClear(): void;
986
+ instanceConstants(): void;
987
+ instanceResetUserInterface(): void;
951
988
  private extractPaths;
952
989
  keyOn(pitch: number, velocity: number, legato?: boolean): void;
953
990
  keyOff(hard?: boolean): void;
@@ -963,7 +1000,13 @@ export declare class FaustPolyWebAudioDsp extends FaustBaseWebAudioDsp implement
963
1000
  private fAudioMixing;
964
1001
  private fAudioMixingHalf;
965
1002
  private fVoiceTable;
1003
+ private fSampleRate;
966
1004
  constructor(instance: FaustPolyDspInstance, sampleRate: number, sampleSize: number, bufferSize: number, soundfiles: LooseFaustDspFactory["soundfiles"]);
1005
+ init(): void;
1006
+ instanceInit(): void;
1007
+ instanceClear(): void;
1008
+ instanceConstants(): void;
1009
+ instanceResetUserInterface(): void;
967
1010
  private initMemory;
968
1011
  toString(): string;
969
1012
  private allocVoice;
@@ -1258,6 +1301,11 @@ export declare class FaustOfflineProcessor<Poly extends boolean = false> {
1258
1301
  getJSON(): string;
1259
1302
  getDescriptors(): FaustUIInputItem[];
1260
1303
  getUI(): FaustUIDescriptor;
1304
+ init(): void;
1305
+ instanceInit(): void;
1306
+ instanceClear(): void;
1307
+ instanceConstants(): void;
1308
+ instanceResetUserInterface(): void;
1261
1309
  start(): void;
1262
1310
  stop(): void;
1263
1311
  destroy(): void;
@@ -1378,13 +1426,6 @@ export declare class SoundfileReader {
1378
1426
  * @returns : the URLs
1379
1427
  */
1380
1428
  static findSoundfilesFromMeta(dspMeta: FaustDspMeta): LooseFaustDspFactory["soundfiles"];
1381
- /**
1382
- * Check if the file exists.
1383
- *
1384
- * @param url : the url of the file to check
1385
- * @returns : true if the file exists, otherwise false
1386
- */
1387
- private static checkFileExists;
1388
1429
  /**
1389
1430
  * Fetch the soundfile.
1390
1431
  *
@@ -1470,6 +1511,11 @@ export declare class FaustAudioWorkletNode<Poly extends boolean = false> extends
1470
1511
  getJSON(): string;
1471
1512
  getUI(): FaustUIDescriptor;
1472
1513
  getDescriptors(): FaustUIInputItem[];
1514
+ init(): void;
1515
+ instanceInit(): void;
1516
+ instanceClear(): void;
1517
+ instanceConstants(): void;
1518
+ instanceResetUserInterface(): void;
1473
1519
  start(): void;
1474
1520
  stop(): void;
1475
1521
  destroy(): void;
@@ -1508,7 +1554,12 @@ export declare class FaustScriptProcessorNode<Poly extends boolean = false> exte
1508
1554
  protected fOutputs: Float32Array[];
1509
1555
  protected handleDeviceMotion: any;
1510
1556
  protected handleDeviceOrientation: any;
1511
- init(instance: Poly extends true ? FaustPolyWebAudioDsp : FaustMonoWebAudioDsp): void;
1557
+ setupNode(instance: Poly extends true ? FaustPolyWebAudioDsp : FaustMonoWebAudioDsp): void;
1558
+ init(): void;
1559
+ instanceInit(): void;
1560
+ instanceClear(): void;
1561
+ instanceConstants(): void;
1562
+ instanceResetUserInterface(): void;
1512
1563
  /** Start accelerometer and gyroscope handlers */
1513
1564
  startSensors(): Promise<void>;
1514
1565
  /** Stop accelerometer and gyroscope handlers */
package/dist/esm/index.js CHANGED
@@ -219,6 +219,26 @@ var getFaustAudioWorkletProcessor = (dependencies, faustData, register = true) =
219
219
  this.setupWamEventHandler();
220
220
  break;
221
221
  }
222
+ case "init": {
223
+ this.fDSPCode.init();
224
+ break;
225
+ }
226
+ case "instanceInit": {
227
+ this.fDSPCode.instanceInit();
228
+ break;
229
+ }
230
+ case "instanceClear": {
231
+ this.fDSPCode.instanceClear();
232
+ break;
233
+ }
234
+ case "instanceConstants": {
235
+ this.fDSPCode.instanceConstants();
236
+ break;
237
+ }
238
+ case "instanceResetUserInterface": {
239
+ this.fDSPCode.instanceResetUserInterface();
240
+ break;
241
+ }
222
242
  case "start": {
223
243
  this.fDSPCode.start();
224
244
  break;
@@ -2712,7 +2732,7 @@ var FaustBaseWebAudioDsp = class _FaustBaseWebAudioDsp {
2712
2732
  const trimmed = input.replace(/^\{|\}$/g, "");
2713
2733
  return trimmed.split(";").map(
2714
2734
  (str) => str.length <= 2 ? "" : str.substring(1, str.length - 1)
2715
- );
2735
+ ).map((str) => str.trim()).filter((str) => str.length > 0);
2716
2736
  }
2717
2737
  get hasAccInput() {
2718
2738
  return this.fAcc.x.length + this.fAcc.y.length + this.fAcc.z.length > 0;
@@ -3126,6 +3146,16 @@ var FaustBaseWebAudioDsp = class _FaustBaseWebAudioDsp {
3126
3146
  stopSensors() {
3127
3147
  this.stopSensors();
3128
3148
  }
3149
+ init() {
3150
+ }
3151
+ instanceInit() {
3152
+ }
3153
+ instanceClear() {
3154
+ }
3155
+ instanceConstants() {
3156
+ }
3157
+ instanceResetUserInterface() {
3158
+ }
3129
3159
  start() {
3130
3160
  this.fProcessing = true;
3131
3161
  }
@@ -3144,6 +3174,7 @@ var FaustMonoWebAudioDsp = class extends FaustBaseWebAudioDsp {
3144
3174
  constructor(instance, sampleRate, sampleSize, bufferSize, soundfiles) {
3145
3175
  super(sampleSize, bufferSize, soundfiles);
3146
3176
  this.fInstance = instance;
3177
+ this.fSampleRate = sampleRate;
3147
3178
  console.log(`sampleSize: ${sampleSize} bufferSize: ${bufferSize}`);
3148
3179
  this.fJSONDsp = JSON.parse(this.fInstance.json);
3149
3180
  FaustBaseWebAudioDsp.parseUI(this.fJSONDsp.ui, this.fUICallback);
@@ -3157,6 +3188,21 @@ var FaustMonoWebAudioDsp = class extends FaustBaseWebAudioDsp {
3157
3188
  this.initSoundfileMemory(allocator, this.fDSP);
3158
3189
  }
3159
3190
  }
3191
+ init() {
3192
+ this.fInstance.api.init(this.fDSP, this.fSampleRate);
3193
+ }
3194
+ instanceInit() {
3195
+ this.fInstance.api.instanceInit(this.fDSP, this.fSampleRate);
3196
+ }
3197
+ instanceClear() {
3198
+ this.fInstance.api.instanceClear(this.fDSP);
3199
+ }
3200
+ instanceConstants() {
3201
+ this.fInstance.api.instanceConstants(this.fDSP, this.fSampleRate);
3202
+ }
3203
+ instanceResetUserInterface() {
3204
+ this.fInstance.api.instanceResetUserInterface(this.fDSP);
3205
+ }
3160
3206
  initMemory() {
3161
3207
  this.fDSP = 0;
3162
3208
  const $audio = this.fJSONDsp.size;
@@ -3306,7 +3352,6 @@ var FaustWebAudioDspVoice = class _FaustWebAudioDspVoice {
3306
3352
  this.fGainLabel = [];
3307
3353
  this.fKeyLabel = [];
3308
3354
  this.fVelLabel = [];
3309
- // Voice DSP code
3310
3355
  // Accessed by PolyDSPImp class
3311
3356
  this.fCurNote = _FaustWebAudioDspVoice.kFreeVoice;
3312
3357
  this.fNextNote = -1;
@@ -3315,7 +3360,8 @@ var FaustWebAudioDspVoice = class _FaustWebAudioDspVoice {
3315
3360
  this.fLevel = 0;
3316
3361
  this.fDSP = $dsp;
3317
3362
  this.fAPI = api;
3318
- this.fAPI.init(this.fDSP, sampleRate);
3363
+ this.fSampleRate = sampleRate;
3364
+ this.init(sampleRate);
3319
3365
  this.extractPaths(inputItems, pathTable);
3320
3366
  }
3321
3367
  // Voice state
@@ -3343,6 +3389,21 @@ var FaustWebAudioDspVoice = class _FaustWebAudioDspVoice {
3343
3389
  static normalizeVelocity(velocity) {
3344
3390
  return velocity / 127;
3345
3391
  }
3392
+ init(sampleRate) {
3393
+ this.fAPI.init(this.fDSP, sampleRate);
3394
+ }
3395
+ instanceInit() {
3396
+ this.fAPI.instanceInit(this.fDSP, this.fSampleRate);
3397
+ }
3398
+ instanceClear() {
3399
+ this.fAPI.instanceClear(this.fDSP);
3400
+ }
3401
+ instanceConstants() {
3402
+ this.fAPI.instanceConstants(this.fDSP, this.fSampleRate);
3403
+ }
3404
+ instanceResetUserInterface() {
3405
+ this.fAPI.instanceResetUserInterface(this.fDSP);
3406
+ }
3346
3407
  extractPaths(inputItems, pathTable) {
3347
3408
  inputItems.forEach((item) => {
3348
3409
  if (item.endsWith("/gate")) {
@@ -3423,6 +3484,7 @@ var FaustPolyWebAudioDsp = class _FaustPolyWebAudioDsp extends FaustBaseWebAudio
3423
3484
  constructor(instance, sampleRate, sampleSize, bufferSize, soundfiles) {
3424
3485
  super(sampleSize, bufferSize, soundfiles);
3425
3486
  this.fInstance = instance;
3487
+ this.fSampleRate = sampleRate;
3426
3488
  console.log(`sampleSize: ${sampleSize} bufferSize: ${bufferSize}`);
3427
3489
  this.fJSONDsp = JSON.parse(this.fInstance.voiceJSON);
3428
3490
  this.fJSONEffect = this.fInstance.effectAPI && this.fInstance.effectJSON ? JSON.parse(this.fInstance.effectJSON) : null;
@@ -3454,6 +3516,37 @@ var FaustPolyWebAudioDsp = class _FaustPolyWebAudioDsp extends FaustBaseWebAudio
3454
3516
  }
3455
3517
  }
3456
3518
  }
3519
+ init() {
3520
+ this.fVoiceTable.forEach((voice) => voice.init(this.fSampleRate));
3521
+ if (this.fInstance.effectAPI)
3522
+ this.fInstance.effectAPI.init(this.fEffect, this.fSampleRate);
3523
+ }
3524
+ instanceInit() {
3525
+ this.fVoiceTable.forEach((voice) => voice.instanceInit());
3526
+ if (this.fInstance.effectAPI)
3527
+ this.fInstance.effectAPI.instanceInit(
3528
+ this.fEffect,
3529
+ this.fSampleRate
3530
+ );
3531
+ }
3532
+ instanceClear() {
3533
+ this.fVoiceTable.forEach((voice) => voice.instanceClear());
3534
+ if (this.fInstance.effectAPI)
3535
+ this.fInstance.effectAPI.instanceClear(this.fEffect);
3536
+ }
3537
+ instanceConstants() {
3538
+ this.fVoiceTable.forEach((voice) => voice.instanceConstants());
3539
+ if (this.fInstance.effectAPI)
3540
+ this.fInstance.effectAPI.instanceConstants(
3541
+ this.fEffect,
3542
+ this.fSampleRate
3543
+ );
3544
+ }
3545
+ instanceResetUserInterface() {
3546
+ this.fVoiceTable.forEach((voice) => voice.instanceResetUserInterface());
3547
+ if (this.fInstance.effectAPI)
3548
+ this.fInstance.effectAPI.instanceResetUserInterface(this.fEffect);
3549
+ }
3457
3550
  initMemory() {
3458
3551
  this.fEffect = this.fJSONDsp.size * this.fInstance.voices;
3459
3552
  const $audio = this.fEffect + (this.fJSONEffect ? this.fJSONEffect.size : 0);
@@ -3910,6 +4003,21 @@ var FaustOfflineProcessor = class {
3910
4003
  getUI() {
3911
4004
  return this.fDSPCode.getUI();
3912
4005
  }
4006
+ init() {
4007
+ this.fDSPCode.init();
4008
+ }
4009
+ instanceInit() {
4010
+ this.fDSPCode.instanceInit();
4011
+ }
4012
+ instanceClear() {
4013
+ this.fDSPCode.instanceClear();
4014
+ }
4015
+ instanceConstants() {
4016
+ this.fDSPCode.instanceConstants();
4017
+ }
4018
+ instanceResetUserInterface() {
4019
+ this.fDSPCode.instanceResetUserInterface();
4020
+ }
3913
4021
  start() {
3914
4022
  this.fDSPCode.start();
3915
4023
  }
@@ -3973,7 +4081,7 @@ var FaustOfflineProcessor = class {
3973
4081
  outputs[i].set(output, l);
3974
4082
  }
3975
4083
  }
3976
- l += this.fBufferSize;
4084
+ l += sliceLength;
3977
4085
  onUpdate == null ? void 0 : onUpdate(l);
3978
4086
  }
3979
4087
  this.fDSPCode.stop();
@@ -4522,29 +4630,12 @@ var SoundfileReader = class {
4522
4630
  const callback = (item) => {
4523
4631
  if (item.type === "soundfile") {
4524
4632
  const urls = FaustBaseWebAudioDsp.splitSoundfileNames(item.url);
4525
- urls.forEach((url) => soundfiles[url] = null);
4633
+ urls.filter((url) => url.trim().length > 0).forEach((url) => soundfiles[url] = null);
4526
4634
  }
4527
4635
  };
4528
4636
  FaustBaseWebAudioDsp.parseUI(dspMeta.ui, callback);
4529
4637
  return soundfiles;
4530
4638
  }
4531
- /**
4532
- * Check if the file exists.
4533
- *
4534
- * @param url : the url of the file to check
4535
- * @returns : true if the file exists, otherwise false
4536
- */
4537
- static async checkFileExists(url) {
4538
- try {
4539
- console.log(`"checkFileExists" url: ${url}`);
4540
- const response = await fetch(url);
4541
- console.log(`"checkFileExists" response.ok: ${response.ok}`);
4542
- return response.ok;
4543
- } catch (error) {
4544
- console.error("Fetch error:", error);
4545
- return false;
4546
- }
4547
- }
4548
4639
  /**
4549
4640
  * Fetch the soundfile.
4550
4641
  *
@@ -4579,17 +4670,20 @@ var SoundfileReader = class {
4579
4670
  (path) => new URL(filename, path.endsWith("/") ? path : `${path}/`).href
4580
4671
  )
4581
4672
  ];
4582
- const checkResults = await Promise.all(
4583
- urlsToCheck.map((url) => this.checkFileExists(url))
4584
- );
4585
- const successIndex = checkResults.findIndex((r) => !!r);
4586
- if (successIndex === -1)
4587
- throw new Error(
4588
- `Failed to load sound file ${filename}, all check failed.`
4589
- );
4590
- soundfiles[filename] = await this.fetchSoundfile(
4591
- urlsToCheck[successIndex],
4592
- audioCtx
4673
+ let lastError = null;
4674
+ for (const url of urlsToCheck) {
4675
+ try {
4676
+ soundfiles[filename] = await this.fetchSoundfile(
4677
+ url,
4678
+ audioCtx
4679
+ );
4680
+ return;
4681
+ } catch (error) {
4682
+ lastError = error;
4683
+ }
4684
+ }
4685
+ throw new Error(
4686
+ `Failed to load sound file ${filename}, all check failed. Last error: ${String(lastError)}`
4593
4687
  );
4594
4688
  }
4595
4689
  /**
@@ -4967,7 +5061,10 @@ var FaustAudioWorkletNode = class extends (globalThis.AudioWorkletNode || null)
4967
5061
  }
4968
5062
  setParamValue(path, value) {
4969
5063
  const resolved = this.fParamAliases[path] || path;
4970
- this.port.postMessage({ type: "param", data: { path: resolved, value } });
5064
+ this.port.postMessage({
5065
+ type: "param",
5066
+ data: { path: resolved, value }
5067
+ });
4971
5068
  const param = this.parameters.get(resolved);
4972
5069
  if (param) param.setValueAtTime(value, this.context.currentTime);
4973
5070
  }
@@ -4991,6 +5088,21 @@ var FaustAudioWorkletNode = class extends (globalThis.AudioWorkletNode || null)
4991
5088
  getDescriptors() {
4992
5089
  return this.fDescriptor;
4993
5090
  }
5091
+ init() {
5092
+ this.port.postMessage({ type: "init" });
5093
+ }
5094
+ instanceInit() {
5095
+ this.port.postMessage({ type: "instanceInit" });
5096
+ }
5097
+ instanceClear() {
5098
+ this.port.postMessage({ type: "instanceClear" });
5099
+ }
5100
+ instanceConstants() {
5101
+ this.port.postMessage({ type: "instanceConstants" });
5102
+ }
5103
+ instanceResetUserInterface() {
5104
+ this.port.postMessage({ type: "instanceResetUserInterface" });
5105
+ }
4994
5106
  start() {
4995
5107
  this.port.postMessage({ type: "start" });
4996
5108
  }
@@ -5087,7 +5199,7 @@ var FaustScriptProcessorNode = class extends (globalThis.ScriptProcessorNode ||
5087
5199
  this.handleDeviceMotion = void 0;
5088
5200
  this.handleDeviceOrientation = void 0;
5089
5201
  }
5090
- init(instance) {
5202
+ setupNode(instance) {
5091
5203
  this.fDSPCode = instance;
5092
5204
  this.fInputs = new Array(this.fDSPCode.getNumInputs());
5093
5205
  this.fOutputs = new Array(this.fDSPCode.getNumOutputs());
@@ -5117,6 +5229,21 @@ var FaustScriptProcessorNode = class extends (globalThis.ScriptProcessorNode ||
5117
5229
  };
5118
5230
  this.start();
5119
5231
  }
5232
+ init() {
5233
+ this.fDSPCode.init();
5234
+ }
5235
+ instanceInit() {
5236
+ this.fDSPCode.instanceInit();
5237
+ }
5238
+ instanceClear() {
5239
+ this.fDSPCode.instanceClear();
5240
+ }
5241
+ instanceConstants() {
5242
+ this.fDSPCode.instanceConstants();
5243
+ }
5244
+ instanceResetUserInterface() {
5245
+ this.fDSPCode.instanceResetUserInterface();
5246
+ }
5120
5247
  // Public API
5121
5248
  /** Start accelerometer and gyroscope handlers */
5122
5249
  async startSensors() {
@@ -5334,7 +5461,7 @@ var _FaustMonoDspGenerator = class _FaustMonoDspGenerator {
5334
5461
  monoDsp.getNumOutputs()
5335
5462
  );
5336
5463
  Object.setPrototypeOf(sp2, FaustMonoScriptProcessorNode.prototype);
5337
- sp2.init(monoDsp);
5464
+ sp2.setupNode(monoDsp);
5338
5465
  return sp2;
5339
5466
  } else {
5340
5467
  if (!_FaustMonoDspGenerator.gWorkletProcessors.has(context))
@@ -5718,7 +5845,7 @@ process = adaptorIns(dsp_code.process) : dsp_code.effect : adaptorOuts;
5718
5845
  polyDsp.getNumOutputs()
5719
5846
  );
5720
5847
  Object.setPrototypeOf(sp2, FaustPolyScriptProcessorNode.prototype);
5721
- sp2.init(polyDsp);
5848
+ sp2.setupNode(polyDsp);
5722
5849
  return sp2;
5723
5850
  } else {
5724
5851
  if (!_FaustPolyDspGenerator.gWorkletProcessors.has(context))