@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.
@@ -736,6 +736,26 @@ export interface IFaustBaseWebAudioDsp {
736
736
  * event: Pick<DeviceOrientationEvent, "alpha" | "beta" | "gamma">
737
737
  */
738
738
  propagateGyr(event: Pick<DeviceOrientationEvent, "alpha" | "beta" | "gamma">): void;
739
+ /**
740
+ * Reinitialize the DSP using its configured sample rate.
741
+ */
742
+ init(): void;
743
+ /**
744
+ * Reinitialize the DSP instance state using its configured sample rate.
745
+ */
746
+ instanceInit(): void;
747
+ /**
748
+ * Clear the DSP instance state.
749
+ */
750
+ instanceClear(): void;
751
+ /**
752
+ * Reinitialize the DSP instance constants using its configured sample rate.
753
+ */
754
+ instanceConstants(): void;
755
+ /**
756
+ * Reset DSP user interface parameters to their default values.
757
+ */
758
+ instanceResetUserInterface(): void;
739
759
  /**
740
760
  * Start the DSP audio processing.
741
761
  */
@@ -910,6 +930,11 @@ export declare class FaustBaseWebAudioDsp implements IFaustBaseWebAudioDsp {
910
930
  hasSoundfiles(): boolean;
911
931
  startSensors(): void;
912
932
  stopSensors(): void;
933
+ init(): void;
934
+ instanceInit(): void;
935
+ instanceClear(): void;
936
+ instanceConstants(): void;
937
+ instanceResetUserInterface(): void;
913
938
  start(): void;
914
939
  stop(): void;
915
940
  destroy(): void;
@@ -917,7 +942,13 @@ export declare class FaustBaseWebAudioDsp implements IFaustBaseWebAudioDsp {
917
942
  export declare class FaustMonoWebAudioDsp extends FaustBaseWebAudioDsp implements IFaustMonoWebAudioDsp {
918
943
  private fInstance;
919
944
  private fDSP;
945
+ private fSampleRate;
920
946
  constructor(instance: FaustMonoDspInstance, sampleRate: number, sampleSize: number, bufferSize: number, soundfiles: LooseFaustDspFactory["soundfiles"]);
947
+ init(): void;
948
+ instanceInit(): void;
949
+ instanceClear(): void;
950
+ instanceConstants(): void;
951
+ instanceResetUserInterface(): void;
921
952
  private initMemory;
922
953
  toString(): string;
923
954
  compute(input: Float32Array[] | ((input: Float32Array[] | Float64Array[]) => any), output: Float32Array[] | ((output: Float32Array[] | Float64Array[]) => any)): boolean;
@@ -945,6 +976,7 @@ export declare class FaustWebAudioDspVoice {
945
976
  private fVelLabel;
946
977
  private fDSP;
947
978
  private fAPI;
979
+ private fSampleRate;
948
980
  fCurNote: number;
949
981
  fNextNote: number;
950
982
  fNextVel: number;
@@ -955,6 +987,11 @@ export declare class FaustWebAudioDspVoice {
955
987
  }, sampleRate: number);
956
988
  static midiToFreq(note: number): number;
957
989
  static normalizeVelocity(velocity: number): number;
990
+ init(sampleRate: number): void;
991
+ instanceInit(): void;
992
+ instanceClear(): void;
993
+ instanceConstants(): void;
994
+ instanceResetUserInterface(): void;
958
995
  private extractPaths;
959
996
  keyOn(pitch: number, velocity: number, legato?: boolean): void;
960
997
  keyOff(hard?: boolean): void;
@@ -970,7 +1007,13 @@ export declare class FaustPolyWebAudioDsp extends FaustBaseWebAudioDsp implement
970
1007
  private fAudioMixing;
971
1008
  private fAudioMixingHalf;
972
1009
  private fVoiceTable;
1010
+ private fSampleRate;
973
1011
  constructor(instance: FaustPolyDspInstance, sampleRate: number, sampleSize: number, bufferSize: number, soundfiles: LooseFaustDspFactory["soundfiles"]);
1012
+ init(): void;
1013
+ instanceInit(): void;
1014
+ instanceClear(): void;
1015
+ instanceConstants(): void;
1016
+ instanceResetUserInterface(): void;
974
1017
  private initMemory;
975
1018
  toString(): string;
976
1019
  private allocVoice;
@@ -1265,6 +1308,11 @@ export declare class FaustOfflineProcessor<Poly extends boolean = false> {
1265
1308
  getJSON(): string;
1266
1309
  getDescriptors(): FaustUIInputItem[];
1267
1310
  getUI(): FaustUIDescriptor;
1311
+ init(): void;
1312
+ instanceInit(): void;
1313
+ instanceClear(): void;
1314
+ instanceConstants(): void;
1315
+ instanceResetUserInterface(): void;
1268
1316
  start(): void;
1269
1317
  stop(): void;
1270
1318
  destroy(): void;
@@ -1385,13 +1433,6 @@ export declare class SoundfileReader {
1385
1433
  * @returns : the URLs
1386
1434
  */
1387
1435
  static findSoundfilesFromMeta(dspMeta: FaustDspMeta): LooseFaustDspFactory["soundfiles"];
1388
- /**
1389
- * Check if the file exists.
1390
- *
1391
- * @param url : the url of the file to check
1392
- * @returns : true if the file exists, otherwise false
1393
- */
1394
- private static checkFileExists;
1395
1436
  /**
1396
1437
  * Fetch the soundfile.
1397
1438
  *
@@ -1477,6 +1518,11 @@ export declare class FaustAudioWorkletNode<Poly extends boolean = false> extends
1477
1518
  getJSON(): string;
1478
1519
  getUI(): FaustUIDescriptor;
1479
1520
  getDescriptors(): FaustUIInputItem[];
1521
+ init(): void;
1522
+ instanceInit(): void;
1523
+ instanceClear(): void;
1524
+ instanceConstants(): void;
1525
+ instanceResetUserInterface(): void;
1480
1526
  start(): void;
1481
1527
  stop(): void;
1482
1528
  destroy(): void;
@@ -1515,7 +1561,12 @@ export declare class FaustScriptProcessorNode<Poly extends boolean = false> exte
1515
1561
  protected fOutputs: Float32Array[];
1516
1562
  protected handleDeviceMotion: any;
1517
1563
  protected handleDeviceOrientation: any;
1518
- init(instance: Poly extends true ? FaustPolyWebAudioDsp : FaustMonoWebAudioDsp): void;
1564
+ setupNode(instance: Poly extends true ? FaustPolyWebAudioDsp : FaustMonoWebAudioDsp): void;
1565
+ init(): void;
1566
+ instanceInit(): void;
1567
+ instanceClear(): void;
1568
+ instanceConstants(): void;
1569
+ instanceResetUserInterface(): void;
1519
1570
  /** Start accelerometer and gyroscope handlers */
1520
1571
  startSensors(): Promise<void>;
1521
1572
  /** Stop accelerometer and gyroscope handlers */
@@ -6007,6 +6007,26 @@ var getFaustAudioWorkletProcessor = (dependencies, faustData, register = true) =
6007
6007
  this.setupWamEventHandler();
6008
6008
  break;
6009
6009
  }
6010
+ case "init": {
6011
+ this.fDSPCode.init();
6012
+ break;
6013
+ }
6014
+ case "instanceInit": {
6015
+ this.fDSPCode.instanceInit();
6016
+ break;
6017
+ }
6018
+ case "instanceClear": {
6019
+ this.fDSPCode.instanceClear();
6020
+ break;
6021
+ }
6022
+ case "instanceConstants": {
6023
+ this.fDSPCode.instanceConstants();
6024
+ break;
6025
+ }
6026
+ case "instanceResetUserInterface": {
6027
+ this.fDSPCode.instanceResetUserInterface();
6028
+ break;
6029
+ }
6010
6030
  case "start": {
6011
6031
  this.fDSPCode.start();
6012
6032
  break;
@@ -8500,7 +8520,7 @@ var FaustBaseWebAudioDsp = class _FaustBaseWebAudioDsp {
8500
8520
  const trimmed = input.replace(/^\{|\}$/g, "");
8501
8521
  return trimmed.split(";").map(
8502
8522
  (str) => str.length <= 2 ? "" : str.substring(1, str.length - 1)
8503
- );
8523
+ ).map((str) => str.trim()).filter((str) => str.length > 0);
8504
8524
  }
8505
8525
  get hasAccInput() {
8506
8526
  return this.fAcc.x.length + this.fAcc.y.length + this.fAcc.z.length > 0;
@@ -8914,6 +8934,16 @@ var FaustBaseWebAudioDsp = class _FaustBaseWebAudioDsp {
8914
8934
  stopSensors() {
8915
8935
  this.stopSensors();
8916
8936
  }
8937
+ init() {
8938
+ }
8939
+ instanceInit() {
8940
+ }
8941
+ instanceClear() {
8942
+ }
8943
+ instanceConstants() {
8944
+ }
8945
+ instanceResetUserInterface() {
8946
+ }
8917
8947
  start() {
8918
8948
  this.fProcessing = true;
8919
8949
  }
@@ -8932,6 +8962,7 @@ var FaustMonoWebAudioDsp = class extends FaustBaseWebAudioDsp {
8932
8962
  constructor(instance, sampleRate, sampleSize, bufferSize, soundfiles) {
8933
8963
  super(sampleSize, bufferSize, soundfiles);
8934
8964
  this.fInstance = instance;
8965
+ this.fSampleRate = sampleRate;
8935
8966
  console.log(`sampleSize: ${sampleSize} bufferSize: ${bufferSize}`);
8936
8967
  this.fJSONDsp = JSON.parse(this.fInstance.json);
8937
8968
  FaustBaseWebAudioDsp.parseUI(this.fJSONDsp.ui, this.fUICallback);
@@ -8945,6 +8976,21 @@ var FaustMonoWebAudioDsp = class extends FaustBaseWebAudioDsp {
8945
8976
  this.initSoundfileMemory(allocator, this.fDSP);
8946
8977
  }
8947
8978
  }
8979
+ init() {
8980
+ this.fInstance.api.init(this.fDSP, this.fSampleRate);
8981
+ }
8982
+ instanceInit() {
8983
+ this.fInstance.api.instanceInit(this.fDSP, this.fSampleRate);
8984
+ }
8985
+ instanceClear() {
8986
+ this.fInstance.api.instanceClear(this.fDSP);
8987
+ }
8988
+ instanceConstants() {
8989
+ this.fInstance.api.instanceConstants(this.fDSP, this.fSampleRate);
8990
+ }
8991
+ instanceResetUserInterface() {
8992
+ this.fInstance.api.instanceResetUserInterface(this.fDSP);
8993
+ }
8948
8994
  initMemory() {
8949
8995
  this.fDSP = 0;
8950
8996
  const $audio = this.fJSONDsp.size;
@@ -9094,7 +9140,6 @@ var FaustWebAudioDspVoice = class _FaustWebAudioDspVoice {
9094
9140
  this.fGainLabel = [];
9095
9141
  this.fKeyLabel = [];
9096
9142
  this.fVelLabel = [];
9097
- // Voice DSP code
9098
9143
  // Accessed by PolyDSPImp class
9099
9144
  this.fCurNote = _FaustWebAudioDspVoice.kFreeVoice;
9100
9145
  this.fNextNote = -1;
@@ -9103,7 +9148,8 @@ var FaustWebAudioDspVoice = class _FaustWebAudioDspVoice {
9103
9148
  this.fLevel = 0;
9104
9149
  this.fDSP = $dsp;
9105
9150
  this.fAPI = api;
9106
- this.fAPI.init(this.fDSP, sampleRate);
9151
+ this.fSampleRate = sampleRate;
9152
+ this.init(sampleRate);
9107
9153
  this.extractPaths(inputItems, pathTable);
9108
9154
  }
9109
9155
  // Voice state
@@ -9131,6 +9177,21 @@ var FaustWebAudioDspVoice = class _FaustWebAudioDspVoice {
9131
9177
  static normalizeVelocity(velocity) {
9132
9178
  return velocity / 127;
9133
9179
  }
9180
+ init(sampleRate) {
9181
+ this.fAPI.init(this.fDSP, sampleRate);
9182
+ }
9183
+ instanceInit() {
9184
+ this.fAPI.instanceInit(this.fDSP, this.fSampleRate);
9185
+ }
9186
+ instanceClear() {
9187
+ this.fAPI.instanceClear(this.fDSP);
9188
+ }
9189
+ instanceConstants() {
9190
+ this.fAPI.instanceConstants(this.fDSP, this.fSampleRate);
9191
+ }
9192
+ instanceResetUserInterface() {
9193
+ this.fAPI.instanceResetUserInterface(this.fDSP);
9194
+ }
9134
9195
  extractPaths(inputItems, pathTable) {
9135
9196
  inputItems.forEach((item) => {
9136
9197
  if (item.endsWith("/gate")) {
@@ -9211,6 +9272,7 @@ var FaustPolyWebAudioDsp = class _FaustPolyWebAudioDsp extends FaustBaseWebAudio
9211
9272
  constructor(instance, sampleRate, sampleSize, bufferSize, soundfiles) {
9212
9273
  super(sampleSize, bufferSize, soundfiles);
9213
9274
  this.fInstance = instance;
9275
+ this.fSampleRate = sampleRate;
9214
9276
  console.log(`sampleSize: ${sampleSize} bufferSize: ${bufferSize}`);
9215
9277
  this.fJSONDsp = JSON.parse(this.fInstance.voiceJSON);
9216
9278
  this.fJSONEffect = this.fInstance.effectAPI && this.fInstance.effectJSON ? JSON.parse(this.fInstance.effectJSON) : null;
@@ -9242,6 +9304,37 @@ var FaustPolyWebAudioDsp = class _FaustPolyWebAudioDsp extends FaustBaseWebAudio
9242
9304
  }
9243
9305
  }
9244
9306
  }
9307
+ init() {
9308
+ this.fVoiceTable.forEach((voice) => voice.init(this.fSampleRate));
9309
+ if (this.fInstance.effectAPI)
9310
+ this.fInstance.effectAPI.init(this.fEffect, this.fSampleRate);
9311
+ }
9312
+ instanceInit() {
9313
+ this.fVoiceTable.forEach((voice) => voice.instanceInit());
9314
+ if (this.fInstance.effectAPI)
9315
+ this.fInstance.effectAPI.instanceInit(
9316
+ this.fEffect,
9317
+ this.fSampleRate
9318
+ );
9319
+ }
9320
+ instanceClear() {
9321
+ this.fVoiceTable.forEach((voice) => voice.instanceClear());
9322
+ if (this.fInstance.effectAPI)
9323
+ this.fInstance.effectAPI.instanceClear(this.fEffect);
9324
+ }
9325
+ instanceConstants() {
9326
+ this.fVoiceTable.forEach((voice) => voice.instanceConstants());
9327
+ if (this.fInstance.effectAPI)
9328
+ this.fInstance.effectAPI.instanceConstants(
9329
+ this.fEffect,
9330
+ this.fSampleRate
9331
+ );
9332
+ }
9333
+ instanceResetUserInterface() {
9334
+ this.fVoiceTable.forEach((voice) => voice.instanceResetUserInterface());
9335
+ if (this.fInstance.effectAPI)
9336
+ this.fInstance.effectAPI.instanceResetUserInterface(this.fEffect);
9337
+ }
9245
9338
  initMemory() {
9246
9339
  this.fEffect = this.fJSONDsp.size * this.fInstance.voices;
9247
9340
  const $audio = this.fEffect + (this.fJSONEffect ? this.fJSONEffect.size : 0);
@@ -9698,6 +9791,21 @@ var FaustOfflineProcessor = class {
9698
9791
  getUI() {
9699
9792
  return this.fDSPCode.getUI();
9700
9793
  }
9794
+ init() {
9795
+ this.fDSPCode.init();
9796
+ }
9797
+ instanceInit() {
9798
+ this.fDSPCode.instanceInit();
9799
+ }
9800
+ instanceClear() {
9801
+ this.fDSPCode.instanceClear();
9802
+ }
9803
+ instanceConstants() {
9804
+ this.fDSPCode.instanceConstants();
9805
+ }
9806
+ instanceResetUserInterface() {
9807
+ this.fDSPCode.instanceResetUserInterface();
9808
+ }
9701
9809
  start() {
9702
9810
  this.fDSPCode.start();
9703
9811
  }
@@ -9761,7 +9869,7 @@ var FaustOfflineProcessor = class {
9761
9869
  outputs[i].set(output, l);
9762
9870
  }
9763
9871
  }
9764
- l += this.fBufferSize;
9872
+ l += sliceLength;
9765
9873
  onUpdate == null ? void 0 : onUpdate(l);
9766
9874
  }
9767
9875
  this.fDSPCode.stop();
@@ -10310,29 +10418,12 @@ var SoundfileReader = class {
10310
10418
  const callback = (item) => {
10311
10419
  if (item.type === "soundfile") {
10312
10420
  const urls = FaustBaseWebAudioDsp.splitSoundfileNames(item.url);
10313
- urls.forEach((url) => soundfiles[url] = null);
10421
+ urls.filter((url) => url.trim().length > 0).forEach((url) => soundfiles[url] = null);
10314
10422
  }
10315
10423
  };
10316
10424
  FaustBaseWebAudioDsp.parseUI(dspMeta.ui, callback);
10317
10425
  return soundfiles;
10318
10426
  }
10319
- /**
10320
- * Check if the file exists.
10321
- *
10322
- * @param url : the url of the file to check
10323
- * @returns : true if the file exists, otherwise false
10324
- */
10325
- static async checkFileExists(url) {
10326
- try {
10327
- console.log(`"checkFileExists" url: ${url}`);
10328
- const response = await fetch(url);
10329
- console.log(`"checkFileExists" response.ok: ${response.ok}`);
10330
- return response.ok;
10331
- } catch (error) {
10332
- console.error("Fetch error:", error);
10333
- return false;
10334
- }
10335
- }
10336
10427
  /**
10337
10428
  * Fetch the soundfile.
10338
10429
  *
@@ -10367,17 +10458,20 @@ var SoundfileReader = class {
10367
10458
  (path) => new URL(filename, path.endsWith("/") ? path : `${path}/`).href
10368
10459
  )
10369
10460
  ];
10370
- const checkResults = await Promise.all(
10371
- urlsToCheck.map((url) => this.checkFileExists(url))
10372
- );
10373
- const successIndex = checkResults.findIndex((r) => !!r);
10374
- if (successIndex === -1)
10375
- throw new Error(
10376
- `Failed to load sound file ${filename}, all check failed.`
10377
- );
10378
- soundfiles[filename] = await this.fetchSoundfile(
10379
- urlsToCheck[successIndex],
10380
- audioCtx
10461
+ let lastError = null;
10462
+ for (const url of urlsToCheck) {
10463
+ try {
10464
+ soundfiles[filename] = await this.fetchSoundfile(
10465
+ url,
10466
+ audioCtx
10467
+ );
10468
+ return;
10469
+ } catch (error) {
10470
+ lastError = error;
10471
+ }
10472
+ }
10473
+ throw new Error(
10474
+ `Failed to load sound file ${filename}, all check failed. Last error: ${String(lastError)}`
10381
10475
  );
10382
10476
  }
10383
10477
  /**
@@ -10755,7 +10849,10 @@ var FaustAudioWorkletNode = class extends (globalThis.AudioWorkletNode || null)
10755
10849
  }
10756
10850
  setParamValue(path, value) {
10757
10851
  const resolved = this.fParamAliases[path] || path;
10758
- this.port.postMessage({ type: "param", data: { path: resolved, value } });
10852
+ this.port.postMessage({
10853
+ type: "param",
10854
+ data: { path: resolved, value }
10855
+ });
10759
10856
  const param = this.parameters.get(resolved);
10760
10857
  if (param) param.setValueAtTime(value, this.context.currentTime);
10761
10858
  }
@@ -10779,6 +10876,21 @@ var FaustAudioWorkletNode = class extends (globalThis.AudioWorkletNode || null)
10779
10876
  getDescriptors() {
10780
10877
  return this.fDescriptor;
10781
10878
  }
10879
+ init() {
10880
+ this.port.postMessage({ type: "init" });
10881
+ }
10882
+ instanceInit() {
10883
+ this.port.postMessage({ type: "instanceInit" });
10884
+ }
10885
+ instanceClear() {
10886
+ this.port.postMessage({ type: "instanceClear" });
10887
+ }
10888
+ instanceConstants() {
10889
+ this.port.postMessage({ type: "instanceConstants" });
10890
+ }
10891
+ instanceResetUserInterface() {
10892
+ this.port.postMessage({ type: "instanceResetUserInterface" });
10893
+ }
10782
10894
  start() {
10783
10895
  this.port.postMessage({ type: "start" });
10784
10896
  }
@@ -10875,7 +10987,7 @@ var FaustScriptProcessorNode = class extends (globalThis.ScriptProcessorNode ||
10875
10987
  this.handleDeviceMotion = void 0;
10876
10988
  this.handleDeviceOrientation = void 0;
10877
10989
  }
10878
- init(instance) {
10990
+ setupNode(instance) {
10879
10991
  this.fDSPCode = instance;
10880
10992
  this.fInputs = new Array(this.fDSPCode.getNumInputs());
10881
10993
  this.fOutputs = new Array(this.fDSPCode.getNumOutputs());
@@ -10905,6 +11017,21 @@ var FaustScriptProcessorNode = class extends (globalThis.ScriptProcessorNode ||
10905
11017
  };
10906
11018
  this.start();
10907
11019
  }
11020
+ init() {
11021
+ this.fDSPCode.init();
11022
+ }
11023
+ instanceInit() {
11024
+ this.fDSPCode.instanceInit();
11025
+ }
11026
+ instanceClear() {
11027
+ this.fDSPCode.instanceClear();
11028
+ }
11029
+ instanceConstants() {
11030
+ this.fDSPCode.instanceConstants();
11031
+ }
11032
+ instanceResetUserInterface() {
11033
+ this.fDSPCode.instanceResetUserInterface();
11034
+ }
10908
11035
  // Public API
10909
11036
  /** Start accelerometer and gyroscope handlers */
10910
11037
  async startSensors() {
@@ -11122,7 +11249,7 @@ var _FaustMonoDspGenerator = class _FaustMonoDspGenerator {
11122
11249
  monoDsp.getNumOutputs()
11123
11250
  );
11124
11251
  Object.setPrototypeOf(sp2, FaustMonoScriptProcessorNode.prototype);
11125
- sp2.init(monoDsp);
11252
+ sp2.setupNode(monoDsp);
11126
11253
  return sp2;
11127
11254
  } else {
11128
11255
  if (!_FaustMonoDspGenerator.gWorkletProcessors.has(context))
@@ -11506,7 +11633,7 @@ process = adaptorIns(dsp_code.process) : dsp_code.effect : adaptorOuts;
11506
11633
  polyDsp.getNumOutputs()
11507
11634
  );
11508
11635
  Object.setPrototypeOf(sp2, FaustPolyScriptProcessorNode.prototype);
11509
- sp2.init(polyDsp);
11636
+ sp2.setupNode(polyDsp);
11510
11637
  return sp2;
11511
11638
  } else {
11512
11639
  if (!_FaustPolyDspGenerator.gWorkletProcessors.has(context))