shithub: sf2mid

Download patch

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, &region->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);