improve: bandpass skirt width in Hz, not bins (consistent across selections)
The playback bandpass transition was freqPerBin*10 wide, and freqPerBin depends on the FFT size, which is derived from the selection length — so the same frequency band got a sharper or softer filter depending on how long a region you selected. Set the skirt to ~20% of the passband (capped at 100 Hz), floored at 3 FFT bins so it stays smooth at coarse resolution. Now a given band sounds the same regardless of selection duration. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
+11
-2
@@ -136,14 +136,23 @@ static void ApplyBandpassFilterFFT(float* samples, int numSamples, int sampleRat
|
||||
FFT(fftInput, fftOutput, fftSize, false);
|
||||
|
||||
float freqPerBin = (float)sampleRate / fftSize;
|
||||
|
||||
// Transition (skirt) width in Hz: ~20% of the passband, capped at 100 Hz,
|
||||
// with a floor of 3 FFT bins so it stays smooth at coarse resolution.
|
||||
// Previously the skirt was tied to bin width alone (freqPerBin * 10), so the
|
||||
// FFT size — and thus the filter's sharpness — changed with the selection
|
||||
// length: the same band sounded different depending on how much you boxed.
|
||||
float bandwidthHz = freqHigh - freqLow;
|
||||
float transitionHz = fmaxf(fminf(bandwidthHz * 0.2f, 100.0f), freqPerBin * 3.0f);
|
||||
|
||||
for (int bin = 0; bin < fftSize / 2 + 1; bin++) {
|
||||
float frequency = bin * freqPerBin;
|
||||
float attenuation = 1.0f;
|
||||
if (frequency < freqLow) {
|
||||
float dist = (freqLow - frequency) / (freqPerBin * 10.0f);
|
||||
float dist = (freqLow - frequency) / transitionHz;
|
||||
attenuation = 1.0f / (1.0f + dist * dist * dist);
|
||||
} else if (frequency > freqHigh) {
|
||||
float dist = (frequency - freqHigh) / (freqPerBin * 10.0f);
|
||||
float dist = (frequency - freqHigh) / transitionHz;
|
||||
attenuation = 1.0f / (1.0f + dist * dist * dist);
|
||||
}
|
||||
fftOutput[bin] *= attenuation;
|
||||
|
||||
Reference in New Issue
Block a user