fix: align playback and WAV export with the displayed frequency axis

Follows 81bab18, which fixed the same class of bug in the PNG export path.
sel.freq* are fractions of the *displayed* frequency axis (capped at
EffectiveMaxFreqHz), not of true Nyquist, but BuildSelectionAudio and
ExportSelectionWAV both scaled them against sampleRate/2. With a display
crop active this widened the bandpass by 1/DisplayFreqFraction(), so the
audio you heard (and the WAV you exported) covered a higher, wider band
than the box you drew.

Convert through EffectiveMaxFreqHz for the selection bounds; the filter
still reasons in true-Nyquist terms, which is what the separate `nyquist`
local is for. The "is this effectively full-band?" test likewise compares
against nyquist, so an uncropped selection still skips filtering.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V8ZWfr5XZyyDttvkhJUgHN
This commit is contained in:
2026-08-12 00:17:49 -07:00
parent d35cc66ae6
commit 46e796cdeb
+9 -3
View File
@@ -204,10 +204,16 @@ static float* BuildSelectionAudio(int* outNumSamples)
if (!regionSamples) return NULL;
memcpy(regionSamples, app.signal.samples + startSample, numSamples * sizeof(float));
float maxFreq = (float)app.signal.sampleRate / 2.0f;
// sel.freq* are fractions of the *displayed* axis (capped at
// EffectiveMaxFreqHz), not of true Nyquist — same convention the PNG export
// in ui.c uses. Convert through EffectiveMaxFreqHz so a display crop doesn't
// scale the passband up by 1/DisplayFreqFraction(). The filter itself still
// works in true-Nyquist terms, which is what nyquist is for.
float nyquist = (float)app.signal.sampleRate / 2.0f;
float maxFreq = EffectiveMaxFreqHz();
float freqLow = app.sel.freqStart * maxFreq;
float freqHigh = app.sel.freqEnd * maxFreq;
if (freqLow > 10.0f || freqHigh < maxFreq - 10.0f) {
if (freqLow > 10.0f || freqHigh < nyquist - 10.0f) {
TraceLog(LOG_INFO, "Applying bandpass filter: %.0f - %.0f Hz", freqLow, freqHigh);
ApplyBandpassFilter(regionSamples, numSamples, app.signal.sampleRate, freqLow, freqHigh);
}
@@ -257,7 +263,7 @@ void ExportSelectionWAV(const char* dirPath)
return;
}
float maxFreq = (float)app.signal.sampleRate / 2.0f;
float maxFreq = EffectiveMaxFreqHz(); // sel.freq* are display-axis fractions
float t0 = app.sel.timeStart * app.signal.duration;
float t1 = app.sel.timeEnd * app.signal.duration;
float f0 = app.sel.freqStart * maxFreq;