@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/cjs/index.js CHANGED
@@ -248,6 +248,26 @@ export default ${(_b = jsCode.match(jsCodeHead)) == null ? void 0 : _b[1]};
248
248
  this.setupWamEventHandler();
249
249
  break;
250
250
  }
251
+ case "init": {
252
+ this.fDSPCode.init();
253
+ break;
254
+ }
255
+ case "instanceInit": {
256
+ this.fDSPCode.instanceInit();
257
+ break;
258
+ }
259
+ case "instanceClear": {
260
+ this.fDSPCode.instanceClear();
261
+ break;
262
+ }
263
+ case "instanceConstants": {
264
+ this.fDSPCode.instanceConstants();
265
+ break;
266
+ }
267
+ case "instanceResetUserInterface": {
268
+ this.fDSPCode.instanceResetUserInterface();
269
+ break;
270
+ }
251
271
  case "start": {
252
272
  this.fDSPCode.start();
253
273
  break;
@@ -2741,7 +2761,7 @@ export default ${(_b = jsCode.match(jsCodeHead)) == null ? void 0 : _b[1]};
2741
2761
  const trimmed = input.replace(/^\{|\}$/g, "");
2742
2762
  return trimmed.split(";").map(
2743
2763
  (str) => str.length <= 2 ? "" : str.substring(1, str.length - 1)
2744
- );
2764
+ ).map((str) => str.trim()).filter((str) => str.length > 0);
2745
2765
  }
2746
2766
  get hasAccInput() {
2747
2767
  return this.fAcc.x.length + this.fAcc.y.length + this.fAcc.z.length > 0;
@@ -3155,6 +3175,16 @@ export default ${(_b = jsCode.match(jsCodeHead)) == null ? void 0 : _b[1]};
3155
3175
  stopSensors() {
3156
3176
  this.stopSensors();
3157
3177
  }
3178
+ init() {
3179
+ }
3180
+ instanceInit() {
3181
+ }
3182
+ instanceClear() {
3183
+ }
3184
+ instanceConstants() {
3185
+ }
3186
+ instanceResetUserInterface() {
3187
+ }
3158
3188
  start() {
3159
3189
  this.fProcessing = true;
3160
3190
  }
@@ -3173,6 +3203,7 @@ export default ${(_b = jsCode.match(jsCodeHead)) == null ? void 0 : _b[1]};
3173
3203
  constructor(instance, sampleRate, sampleSize, bufferSize, soundfiles) {
3174
3204
  super(sampleSize, bufferSize, soundfiles);
3175
3205
  this.fInstance = instance;
3206
+ this.fSampleRate = sampleRate;
3176
3207
  console.log(`sampleSize: ${sampleSize} bufferSize: ${bufferSize}`);
3177
3208
  this.fJSONDsp = JSON.parse(this.fInstance.json);
3178
3209
  FaustBaseWebAudioDsp.parseUI(this.fJSONDsp.ui, this.fUICallback);
@@ -3186,6 +3217,21 @@ export default ${(_b = jsCode.match(jsCodeHead)) == null ? void 0 : _b[1]};
3186
3217
  this.initSoundfileMemory(allocator, this.fDSP);
3187
3218
  }
3188
3219
  }
3220
+ init() {
3221
+ this.fInstance.api.init(this.fDSP, this.fSampleRate);
3222
+ }
3223
+ instanceInit() {
3224
+ this.fInstance.api.instanceInit(this.fDSP, this.fSampleRate);
3225
+ }
3226
+ instanceClear() {
3227
+ this.fInstance.api.instanceClear(this.fDSP);
3228
+ }
3229
+ instanceConstants() {
3230
+ this.fInstance.api.instanceConstants(this.fDSP, this.fSampleRate);
3231
+ }
3232
+ instanceResetUserInterface() {
3233
+ this.fInstance.api.instanceResetUserInterface(this.fDSP);
3234
+ }
3189
3235
  initMemory() {
3190
3236
  this.fDSP = 0;
3191
3237
  const $audio = this.fJSONDsp.size;
@@ -3335,7 +3381,6 @@ export default ${(_b = jsCode.match(jsCodeHead)) == null ? void 0 : _b[1]};
3335
3381
  this.fGainLabel = [];
3336
3382
  this.fKeyLabel = [];
3337
3383
  this.fVelLabel = [];
3338
- // Voice DSP code
3339
3384
  // Accessed by PolyDSPImp class
3340
3385
  this.fCurNote = _FaustWebAudioDspVoice.kFreeVoice;
3341
3386
  this.fNextNote = -1;
@@ -3344,7 +3389,8 @@ export default ${(_b = jsCode.match(jsCodeHead)) == null ? void 0 : _b[1]};
3344
3389
  this.fLevel = 0;
3345
3390
  this.fDSP = $dsp;
3346
3391
  this.fAPI = api;
3347
- this.fAPI.init(this.fDSP, sampleRate);
3392
+ this.fSampleRate = sampleRate;
3393
+ this.init(sampleRate);
3348
3394
  this.extractPaths(inputItems, pathTable);
3349
3395
  }
3350
3396
  // Voice state
@@ -3372,6 +3418,21 @@ export default ${(_b = jsCode.match(jsCodeHead)) == null ? void 0 : _b[1]};
3372
3418
  static normalizeVelocity(velocity) {
3373
3419
  return velocity / 127;
3374
3420
  }
3421
+ init(sampleRate) {
3422
+ this.fAPI.init(this.fDSP, sampleRate);
3423
+ }
3424
+ instanceInit() {
3425
+ this.fAPI.instanceInit(this.fDSP, this.fSampleRate);
3426
+ }
3427
+ instanceClear() {
3428
+ this.fAPI.instanceClear(this.fDSP);
3429
+ }
3430
+ instanceConstants() {
3431
+ this.fAPI.instanceConstants(this.fDSP, this.fSampleRate);
3432
+ }
3433
+ instanceResetUserInterface() {
3434
+ this.fAPI.instanceResetUserInterface(this.fDSP);
3435
+ }
3375
3436
  extractPaths(inputItems, pathTable) {
3376
3437
  inputItems.forEach((item) => {
3377
3438
  if (item.endsWith("/gate")) {
@@ -3452,6 +3513,7 @@ export default ${(_b = jsCode.match(jsCodeHead)) == null ? void 0 : _b[1]};
3452
3513
  constructor(instance, sampleRate, sampleSize, bufferSize, soundfiles) {
3453
3514
  super(sampleSize, bufferSize, soundfiles);
3454
3515
  this.fInstance = instance;
3516
+ this.fSampleRate = sampleRate;
3455
3517
  console.log(`sampleSize: ${sampleSize} bufferSize: ${bufferSize}`);
3456
3518
  this.fJSONDsp = JSON.parse(this.fInstance.voiceJSON);
3457
3519
  this.fJSONEffect = this.fInstance.effectAPI && this.fInstance.effectJSON ? JSON.parse(this.fInstance.effectJSON) : null;
@@ -3483,6 +3545,37 @@ export default ${(_b = jsCode.match(jsCodeHead)) == null ? void 0 : _b[1]};
3483
3545
  }
3484
3546
  }
3485
3547
  }
3548
+ init() {
3549
+ this.fVoiceTable.forEach((voice) => voice.init(this.fSampleRate));
3550
+ if (this.fInstance.effectAPI)
3551
+ this.fInstance.effectAPI.init(this.fEffect, this.fSampleRate);
3552
+ }
3553
+ instanceInit() {
3554
+ this.fVoiceTable.forEach((voice) => voice.instanceInit());
3555
+ if (this.fInstance.effectAPI)
3556
+ this.fInstance.effectAPI.instanceInit(
3557
+ this.fEffect,
3558
+ this.fSampleRate
3559
+ );
3560
+ }
3561
+ instanceClear() {
3562
+ this.fVoiceTable.forEach((voice) => voice.instanceClear());
3563
+ if (this.fInstance.effectAPI)
3564
+ this.fInstance.effectAPI.instanceClear(this.fEffect);
3565
+ }
3566
+ instanceConstants() {
3567
+ this.fVoiceTable.forEach((voice) => voice.instanceConstants());
3568
+ if (this.fInstance.effectAPI)
3569
+ this.fInstance.effectAPI.instanceConstants(
3570
+ this.fEffect,
3571
+ this.fSampleRate
3572
+ );
3573
+ }
3574
+ instanceResetUserInterface() {
3575
+ this.fVoiceTable.forEach((voice) => voice.instanceResetUserInterface());
3576
+ if (this.fInstance.effectAPI)
3577
+ this.fInstance.effectAPI.instanceResetUserInterface(this.fEffect);
3578
+ }
3486
3579
  initMemory() {
3487
3580
  this.fEffect = this.fJSONDsp.size * this.fInstance.voices;
3488
3581
  const $audio = this.fEffect + (this.fJSONEffect ? this.fJSONEffect.size : 0);
@@ -3939,6 +4032,21 @@ export default ${(_b = jsCode.match(jsCodeHead)) == null ? void 0 : _b[1]};
3939
4032
  getUI() {
3940
4033
  return this.fDSPCode.getUI();
3941
4034
  }
4035
+ init() {
4036
+ this.fDSPCode.init();
4037
+ }
4038
+ instanceInit() {
4039
+ this.fDSPCode.instanceInit();
4040
+ }
4041
+ instanceClear() {
4042
+ this.fDSPCode.instanceClear();
4043
+ }
4044
+ instanceConstants() {
4045
+ this.fDSPCode.instanceConstants();
4046
+ }
4047
+ instanceResetUserInterface() {
4048
+ this.fDSPCode.instanceResetUserInterface();
4049
+ }
3942
4050
  start() {
3943
4051
  this.fDSPCode.start();
3944
4052
  }
@@ -4002,7 +4110,7 @@ export default ${(_b = jsCode.match(jsCodeHead)) == null ? void 0 : _b[1]};
4002
4110
  outputs[i].set(output, l);
4003
4111
  }
4004
4112
  }
4005
- l += this.fBufferSize;
4113
+ l += sliceLength;
4006
4114
  onUpdate == null ? void 0 : onUpdate(l);
4007
4115
  }
4008
4116
  this.fDSPCode.stop();
@@ -4551,29 +4659,12 @@ export default ${(_b = jsCode.match(jsCodeHead)) == null ? void 0 : _b[1]};
4551
4659
  const callback = (item) => {
4552
4660
  if (item.type === "soundfile") {
4553
4661
  const urls = FaustBaseWebAudioDsp.splitSoundfileNames(item.url);
4554
- urls.forEach((url) => soundfiles[url] = null);
4662
+ urls.filter((url) => url.trim().length > 0).forEach((url) => soundfiles[url] = null);
4555
4663
  }
4556
4664
  };
4557
4665
  FaustBaseWebAudioDsp.parseUI(dspMeta.ui, callback);
4558
4666
  return soundfiles;
4559
4667
  }
4560
- /**
4561
- * Check if the file exists.
4562
- *
4563
- * @param url : the url of the file to check
4564
- * @returns : true if the file exists, otherwise false
4565
- */
4566
- static async checkFileExists(url) {
4567
- try {
4568
- console.log(`"checkFileExists" url: ${url}`);
4569
- const response = await fetch(url);
4570
- console.log(`"checkFileExists" response.ok: ${response.ok}`);
4571
- return response.ok;
4572
- } catch (error) {
4573
- console.error("Fetch error:", error);
4574
- return false;
4575
- }
4576
- }
4577
4668
  /**
4578
4669
  * Fetch the soundfile.
4579
4670
  *
@@ -4608,17 +4699,20 @@ export default ${(_b = jsCode.match(jsCodeHead)) == null ? void 0 : _b[1]};
4608
4699
  (path) => new URL(filename, path.endsWith("/") ? path : `${path}/`).href
4609
4700
  )
4610
4701
  ];
4611
- const checkResults = await Promise.all(
4612
- urlsToCheck.map((url) => this.checkFileExists(url))
4613
- );
4614
- const successIndex = checkResults.findIndex((r) => !!r);
4615
- if (successIndex === -1)
4616
- throw new Error(
4617
- `Failed to load sound file ${filename}, all check failed.`
4618
- );
4619
- soundfiles[filename] = await this.fetchSoundfile(
4620
- urlsToCheck[successIndex],
4621
- audioCtx
4702
+ let lastError = null;
4703
+ for (const url of urlsToCheck) {
4704
+ try {
4705
+ soundfiles[filename] = await this.fetchSoundfile(
4706
+ url,
4707
+ audioCtx
4708
+ );
4709
+ return;
4710
+ } catch (error) {
4711
+ lastError = error;
4712
+ }
4713
+ }
4714
+ throw new Error(
4715
+ `Failed to load sound file ${filename}, all check failed. Last error: ${String(lastError)}`
4622
4716
  );
4623
4717
  }
4624
4718
  /**
@@ -4996,7 +5090,10 @@ export default ${(_b = jsCode.match(jsCodeHead)) == null ? void 0 : _b[1]};
4996
5090
  }
4997
5091
  setParamValue(path, value) {
4998
5092
  const resolved = this.fParamAliases[path] || path;
4999
- this.port.postMessage({ type: "param", data: { path: resolved, value } });
5093
+ this.port.postMessage({
5094
+ type: "param",
5095
+ data: { path: resolved, value }
5096
+ });
5000
5097
  const param = this.parameters.get(resolved);
5001
5098
  if (param) param.setValueAtTime(value, this.context.currentTime);
5002
5099
  }
@@ -5020,6 +5117,21 @@ export default ${(_b = jsCode.match(jsCodeHead)) == null ? void 0 : _b[1]};
5020
5117
  getDescriptors() {
5021
5118
  return this.fDescriptor;
5022
5119
  }
5120
+ init() {
5121
+ this.port.postMessage({ type: "init" });
5122
+ }
5123
+ instanceInit() {
5124
+ this.port.postMessage({ type: "instanceInit" });
5125
+ }
5126
+ instanceClear() {
5127
+ this.port.postMessage({ type: "instanceClear" });
5128
+ }
5129
+ instanceConstants() {
5130
+ this.port.postMessage({ type: "instanceConstants" });
5131
+ }
5132
+ instanceResetUserInterface() {
5133
+ this.port.postMessage({ type: "instanceResetUserInterface" });
5134
+ }
5023
5135
  start() {
5024
5136
  this.port.postMessage({ type: "start" });
5025
5137
  }
@@ -5116,7 +5228,7 @@ export default ${(_b = jsCode.match(jsCodeHead)) == null ? void 0 : _b[1]};
5116
5228
  this.handleDeviceMotion = void 0;
5117
5229
  this.handleDeviceOrientation = void 0;
5118
5230
  }
5119
- init(instance) {
5231
+ setupNode(instance) {
5120
5232
  this.fDSPCode = instance;
5121
5233
  this.fInputs = new Array(this.fDSPCode.getNumInputs());
5122
5234
  this.fOutputs = new Array(this.fDSPCode.getNumOutputs());
@@ -5146,6 +5258,21 @@ export default ${(_b = jsCode.match(jsCodeHead)) == null ? void 0 : _b[1]};
5146
5258
  };
5147
5259
  this.start();
5148
5260
  }
5261
+ init() {
5262
+ this.fDSPCode.init();
5263
+ }
5264
+ instanceInit() {
5265
+ this.fDSPCode.instanceInit();
5266
+ }
5267
+ instanceClear() {
5268
+ this.fDSPCode.instanceClear();
5269
+ }
5270
+ instanceConstants() {
5271
+ this.fDSPCode.instanceConstants();
5272
+ }
5273
+ instanceResetUserInterface() {
5274
+ this.fDSPCode.instanceResetUserInterface();
5275
+ }
5149
5276
  // Public API
5150
5277
  /** Start accelerometer and gyroscope handlers */
5151
5278
  async startSensors() {
@@ -5363,7 +5490,7 @@ export default ${(_b = jsCode.match(jsCodeHead)) == null ? void 0 : _b[1]};
5363
5490
  monoDsp.getNumOutputs()
5364
5491
  );
5365
5492
  Object.setPrototypeOf(sp2, FaustMonoScriptProcessorNode.prototype);
5366
- sp2.init(monoDsp);
5493
+ sp2.setupNode(monoDsp);
5367
5494
  return sp2;
5368
5495
  } else {
5369
5496
  if (!_FaustMonoDspGenerator.gWorkletProcessors.has(context))
@@ -5747,7 +5874,7 @@ process = adaptorIns(dsp_code.process) : dsp_code.effect : adaptorOuts;
5747
5874
  polyDsp.getNumOutputs()
5748
5875
  );
5749
5876
  Object.setPrototypeOf(sp2, FaustPolyScriptProcessorNode.prototype);
5750
- sp2.init(polyDsp);
5877
+ sp2.setupNode(polyDsp);
5751
5878
  return sp2;
5752
5879
  } else {
5753
5880
  if (!_FaustPolyDspGenerator.gWorkletProcessors.has(context))