ref: 91c24e1620a8f9c13be1aa21698757e5ad5a95a6
parent: e1aa80797db4a593e0cc003c7e6b2a437dcb7b1a
author: Bernhard Schelling <14200249+schellingb@users.noreply.github.com>
date: Wed Mar 18 20:42:24 EDT 2020
Avoid coefficient overflow in the lowpass filter (could easily happen with an output sample rate below 44100Hz) Fixes #45
--- a/tsf.h
+++ b/tsf.h
@@ -995,8 +995,9 @@
if (dynamicLowpass)
{
float fres = tmpInitialFilterFc + v->modlfo.level * tmpModLfoToFilterFc + v->modenv.level * tmpModEnvToFilterFc;
- tmpLowpass.active = (fres <= 13500.0f);
- if (tmpLowpass.active) tsf_voice_lowpass_setup(&tmpLowpass, tsf_cents2Hertz(fres) / tmpSampleRate);
+ float lowpassFc = (fres <= 13500 ? tsf_cents2Hertz(fres) / f->outSampleRate : 1.0f);
+ tmpLowpass.active = (lowpassFc < 0.499f);
+ if (tmpLowpass.active) tsf_voice_lowpass_setup(&tmpLowpass, lowpassFc);
}
if (dynamicPitchRatio)
@@ -1241,7 +1242,7 @@
voicePlayIndex = f->voicePlayIndex++;
for (region = f->presets[preset_index].regions, regionEnd = region + f->presets[preset_index].regionNum; region != regionEnd; region++)
{
- struct tsf_voice *voice, *v, *vEnd; TSF_BOOL doLoop; float filterQDB;
+ struct tsf_voice *voice, *v, *vEnd; TSF_BOOL doLoop; float lowpassFilterQDB, lowpassFc;
if (key < region->lokey || key > region->hikey || midiVelocity < region->lovel || midiVelocity > region->hivel) continue;
voice = TSF_NULL, v = f->voices, vEnd = v + f->voiceNum;
@@ -1292,11 +1293,12 @@
tsf_voice_envelope_setup(&voice->modenv, ®ion->modenv, key, midiVelocity, TSF_FALSE, f->outSampleRate);
// Setup lowpass filter.
- filterQDB = region->initialFilterQ / 10.0f;
- voice->lowpass.QInv = 1.0 / TSF_POW(10.0, (filterQDB / 20.0));
+ lowpassFc = (region->initialFilterFc <= 13500 ? tsf_cents2Hertz((float)region->initialFilterFc) / f->outSampleRate : 1.0f);
+ lowpassFilterQDB = region->initialFilterQ / 10.0f;
+ voice->lowpass.QInv = 1.0 / TSF_POW(10.0, (lowpassFilterQDB / 20.0));
voice->lowpass.z1 = voice->lowpass.z2 = 0;
- voice->lowpass.active = (region->initialFilterFc <= 13500);
- if (voice->lowpass.active) tsf_voice_lowpass_setup(&voice->lowpass, tsf_cents2Hertz((float)region->initialFilterFc) / f->outSampleRate);
+ voice->lowpass.active = (lowpassFc < 0.499f);
+ if (voice->lowpass.active) tsf_voice_lowpass_setup(&voice->lowpass, lowpassFc);
// Setup LFO filters.
tsf_voice_lfo_setup(&voice->modlfo, region->delayModLFO, region->freqModLFO, f->outSampleRate);