spessasynth_lib 3.22.10 → 3.22.12

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.
@@ -86,6 +86,12 @@ class SpessaSynthProcessor extends AudioWorkletProcessor
86
86
 
87
87
  this.enableEventSystem = options.processorOptions.enableEventSystem;
88
88
 
89
+ /**
90
+ * If the worklet is alive
91
+ * @type {boolean}
92
+ */
93
+ this.alive = true;
94
+
89
95
  /**
90
96
  * Synth's device id: -1 means all
91
97
  * @type {number}
@@ -131,6 +137,9 @@ class SpessaSynthProcessor extends AudioWorkletProcessor
131
137
 
132
138
  this.midiVolume = 1;
133
139
 
140
+ this.reverbGain = 1;
141
+ this.chorusGain = 1;
142
+
134
143
  /**
135
144
  * Maximum number of voices allowed at once
136
145
  * @type {number}
@@ -310,6 +319,10 @@ class SpessaSynthProcessor extends AudioWorkletProcessor
310
319
  */
311
320
  process(inputs, outputs)
312
321
  {
322
+ if (!this.alive)
323
+ {
324
+ return false;
325
+ }
313
326
  if (this.processTickCallback)
314
327
  {
315
328
  this.processTickCallback();
@@ -382,6 +395,26 @@ class SpessaSynthProcessor extends AudioWorkletProcessor
382
395
  }
383
396
  return true;
384
397
  }
398
+
399
+ destroyWorkletProcessor()
400
+ {
401
+ this.alive = false;
402
+ this.workletProcessorChannels.forEach(c =>
403
+ {
404
+ delete c.midiControllers;
405
+ delete c.voices;
406
+ delete c.sustainedVoices;
407
+ delete c.cachedVoices;
408
+ delete c.lockedControllers;
409
+ delete c.preset;
410
+ delete c.customControllers;
411
+ });
412
+ delete this.workletProcessorChannels;
413
+ delete this.sequencer.midiData;
414
+ delete this.sequencer;
415
+ this.soundfontManager.destroyManager();
416
+ delete this.soundfontManager;
417
+ }
385
418
  }
386
419
 
387
420
  // include other methods
@@ -215,6 +215,15 @@ export function handleMessage(message)
215
215
  SpessaSynthLogging(data[0], data[1], data[2], data[3]);
216
216
  break;
217
217
 
218
+ case workletMessageType.setEffectsGain:
219
+ this.reverbGain = data[0];
220
+ this.chorusGain = data[1];
221
+ break;
222
+
223
+ case workletMessageType.destroyWorklet:
224
+ this.alive = false;
225
+ break;
226
+
218
227
  default:
219
228
  SpessaSynthWarn("Unrecognized event:", data);
220
229
  break;
@@ -28,6 +28,8 @@
28
28
  * @property {number} requestSynthesizerSnapshot - 24 -> (no data)
29
29
  * @property {number} setLogLevel - 25 -> [enableInfo<boolean>, enableWarning<boolean>, enableGroup<boolean>, enableTable<boolean>]
30
30
  * @property {number} keyModifier - 26 -> [messageType<workletKeyModifierMessageType> messageData<any>]
31
+ * @property {number} setEffectsGain - 27 -> [reverbGain<number>, chorusGain<number>]
32
+ * @property {number} destroyWorklet - 28 -> (no data)
31
33
  */
32
34
  export const workletMessageType = {
33
35
  noteOff: 0,
@@ -56,7 +58,9 @@ export const workletMessageType = {
56
58
  sequencerSpecific: 23,
57
59
  requestSynthesizerSnapshot: 24,
58
60
  setLogLevel: 25,
59
- keyModifierManager: 26
61
+ keyModifierManager: 26,
62
+ setEffectsGain: 27,
63
+ destroyWorklet: 28
60
64
  };
61
65
 
62
66
  /**
@@ -143,7 +143,20 @@ export function resetControllers(channel)
143
143
  channelObject.keyCentTuning.fill(0);
144
144
 
145
145
  // reset the array
146
- channelObject.midiControllers.set(resetArray);
146
+ for (let i = 0; i < resetArray.length; i++)
147
+ {
148
+ const resetValue = resetArray[i];
149
+ if (channelObject.midiControllers[i] !== resetValue && i < 127)
150
+ {
151
+ // call cc change if reset
152
+ this.callEvent("controllerchange", {
153
+ channel: channel,
154
+ controllerNumber: i,
155
+ controllerValue: resetValue >> 7
156
+ });
157
+ }
158
+ channelObject.midiControllers[i] = resetValue;
159
+ }
147
160
  channelObject.channelVibrato = { rate: 0, depth: 0, delay: 0 };
148
161
  channelObject.holdPedal = false;
149
162
 
@@ -240,4 +240,13 @@ export class WorkletSoundfontManager
240
240
  return this.soundfontList[0].soundfont.presets[0];
241
241
  }
242
242
  }
243
+
244
+ destroyManager()
245
+ {
246
+ this.soundfontList.forEach(s =>
247
+ {
248
+ s.soundfont.destroySoundfont();
249
+ });
250
+ delete this.soundfontList;
251
+ }
243
252
  }
@@ -144,12 +144,12 @@ export class WorkletLowpassFilter
144
144
  // fix cutoff on low frequencies (fluid_iir_filter.c line 392)
145
145
  filter.cutoffHz = Math.min(filter.cutoffHz, 0.45 * sampleRate);
146
146
 
147
- // adjust the filterQ (fluid_iir_filter.c line 204)
148
- const qDb = (filter.reasonanceCb / 10) - 3.01;
149
- filter.reasonanceGain = decibelAttenuationToGain(-1 * qDb); // -1 because it's attenuation and we don't want attenuation
147
+ const qDb = filter.reasonanceCb / 10;
148
+ // correct the filter gain, like fluid does
149
+ filter.reasonanceGain = decibelAttenuationToGain(-1 * (qDb - 3.01)); // -1 because it's attenuation and we don't want attenuation
150
150
 
151
151
  // reduce the gain by the Q factor (fluid_iir_filter.c line 250)
152
- const qGain = 1 / Math.sqrt(filter.reasonanceGain);
152
+ const qGain = 1 / Math.sqrt(decibelAttenuationToGain(-qDb));
153
153
 
154
154
 
155
155
  // code is ported from https://github.com/sinshu/meltysynth/ to work with js.
@@ -38,8 +38,8 @@ export function panVoice(voice,
38
38
  const gainRight = Math.sin(HALF_PI * voice.currentPan) * gain * this.panRight;
39
39
  // disable reverb and chorus in one output mode
40
40
 
41
- const reverbLevel = voice.modulatedGenerators[generatorTypes.reverbEffectsSend] / WORKLET_SYSTEM_REVERB_DIVIDER * gain;
42
- const chorusLevel = voice.modulatedGenerators[generatorTypes.chorusEffectsSend] / WORKLET_SYSTEM_CHORUS_DIVIDER;
41
+ const reverbLevel = this.reverbGain * voice.modulatedGenerators[generatorTypes.reverbEffectsSend] / WORKLET_SYSTEM_REVERB_DIVIDER * gain;
42
+ const chorusLevel = this.chorusGain * voice.modulatedGenerators[generatorTypes.chorusEffectsSend] / WORKLET_SYSTEM_CHORUS_DIVIDER;
43
43
 
44
44
  if (reverbLevel > 0 && !this.oneOutputMode)
45
45
  {