spessasynth_lib 3.20.8 → 3.20.9

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.
@@ -46,7 +46,7 @@ import { interpolationTypes } from './worklet_utilities/wavetable_oscillator.js'
46
46
  * purpose: manages the synthesizer (and worklet sequencer) from the AudioWorkletGlobalScope and renders the audio data
47
47
  */
48
48
 
49
- const WORKLET_PROCESSOR_VERSION = "3.20.8";
49
+ const WORKLET_PROCESSOR_VERSION = "3.20.9";
50
50
 
51
51
  export const MIN_NOTE_LENGTH = 0.07; // if the note is released faster than that, it forced to last that long
52
52
 
@@ -108,7 +108,8 @@ export function renderVoice(
108
108
  // use modulation multiplier (RPN modulation depth)
109
109
  cents += modLfoValue * (modPitchDepth * channel.customControllers[customControllers.modulationMultiplier]);
110
110
  // volenv volume offset
111
- modLfoCentibels = modLfoValue * modVolDepth;
111
+ // the lfo returns from -1 to 1, we change it to 0-1 here because the volume excursion is only positive
112
+ modLfoCentibels = (modLfoValue / 2 + 0.5) * modVolDepth;
112
113
  // lowpass frequency
113
114
  lowpassCents += modLfoValue * modFilterDepth;
114
115
  }
@@ -145,7 +145,7 @@ export class WorkletVolumeEnvelope
145
145
  }
146
146
  // calculate absolute times (they can change so we have to recalculate every time
147
147
  env.attenuation = voice.modulatedGenerators[generatorTypes.initialAttenuation] / 10; // divide by ten to get decibelts
148
- env.sustainDb = voice.volumeEnvelope.attenuation + voice.modulatedGenerators[generatorTypes.sustainVolEnv] / 10;
148
+ env.sustainDb = Math.min(100, voice.volumeEnvelope.attenuation + voice.modulatedGenerators[generatorTypes.sustainVolEnv] / 10);
149
149
 
150
150
  // calculate durations
151
151
  env.attackDuration = timecentsToSamples(voice.modulatedGenerators[generatorTypes.attackVolEnv]);
@@ -154,8 +154,8 @@ export class WorkletVolumeEnvelope
154
154
  // therefore we need to calculate the real time
155
155
  // (changing from attenuation to sustain instead of -100dB)
156
156
  const fullChange = voice.modulatedGenerators[generatorTypes.decayVolEnv];
157
- const keyNumAddition = ((60 - voice.targetKey) * voice.modulatedGenerators[generatorTypes.keyNumToVolEnvDecay]);
158
- const fraction = (env.sustainDb - env.attenuation) / (100 - env.attenuation);
157
+ const keyNumAddition = (60 - voice.targetKey) * voice.modulatedGenerators[generatorTypes.keyNumToVolEnvDecay];
158
+ const fraction = (env.sustainDb - env.attenuation) / 100;
159
159
  env.decayDuration = timecentsToSamples(fullChange + keyNumAddition) * fraction;
160
160
 
161
161
  env.releaseDuration = timecentsToSamples(voice.modulatedGenerators[generatorTypes.releaseVolEnv]);
@@ -334,7 +334,7 @@ export class WorkletVolumeEnvelope
334
334
  case 3:
335
335
  // decay phase: linear ramp from attenuation to sustain
336
336
  const dbDifference = env.sustainDb - env.attenuation;
337
- while(env.currentSampleTime++ < env.decayEnd)
337
+ while(env.currentSampleTime < env.decayEnd)
338
338
  {
339
339
  const newAttenuation = (1 - (env.decayEnd - env.currentSampleTime) / env.decayDuration) * dbDifference + env.attenuation;
340
340
  audioBuffer[filledBuffer] *= WorkletVolumeEnvelope.getInterpolatedGain(env, newAttenuation + decibelOffset, smoothingFactor);
@@ -350,6 +350,15 @@ export class WorkletVolumeEnvelope
350
350
 
351
351
  case 4:
352
352
  // sustain phase: stay at sustain
353
+ if(env.sustainDb > PERCEIVED_DB_SILENCE)
354
+ {
355
+ voice.finished = true;
356
+ while(filledBuffer < audioBuffer.length)
357
+ {
358
+ audioBuffer[filledBuffer++] = 0;
359
+ }
360
+ return;
361
+ }
353
362
  while(true)
354
363
  {
355
364
  audioBuffer[filledBuffer] *= WorkletVolumeEnvelope.getInterpolatedGain(env, env.sustainDb + decibelOffset, smoothingFactor);