Expand description
FFT-based downconversion / decimation.
Ported from WSJT-X ft8_downsample.f90 and generalised to arbitrary MFSK
signals. The algorithm is:
- Zero-pad the real input to
DownsampleCfg::fft1_sizesamples and take a forward FFT. - Extract the positive-frequency bins covering
[f0 - leading_pad·Δf, f0 + trailing_pad·Δf], where the pads are expressed in tone-spacing units. - Hann-taper
DownsampleCfg::edge_taper_binson each side of the extracted block to suppress FFT ringing. - Cyclic-rotate so that
f0lands at DC. - Inverse FFT of size
DownsampleCfg::fft2_sizegives the decimated complex baseband. - Scale by
1 / sqrt(fft1_size · fft2_size).
The output sample rate is input_rate · fft2_size / fft1_size. For the FT8
tuning (12 000 → 200 Hz) it is 200 Hz; FT4 will pick a different
fft2_size to keep a wider baseband.
§Why a config struct rather than <P> ?
fft1_size is chosen per protocol for FFT efficiency (highly-composite
numbers close to the slot length). It is not simply derived from
SLOT_S · sample_rate — it is a tunable tied to the FFT backend’s
strengths. Keeping it in a runtime struct lets callers express values that
are awkward to pin to associated constants.
Structs§
- Downsample
Cfg - Runtime parameters shared by
downsample,downsample_cached, andbuild_fft_cache. Callers typically keep one instance per protocol.
Functions§
- build_
fft_ cache - Compute only the large forward-FFT cache. Subsequent calls to
downsample_cachedreuse it across all candidate frequencies, which is the expensive operation amortised byft8-core::decode::process_candidate. - downsample
- Downconvert
audioto a complex baseband centred onf0. - downsample_
cached - Downconvert using a pre-computed forward-FFT cache.