Skip to main content

Module downsample

Module downsample 

Source
Expand description

FFT-based downconversion / decimation.

Ported from WSJT-X ft8_downsample.f90 and generalised to arbitrary MFSK signals. The algorithm is:

  1. Zero-pad the real input to DownsampleCfg::fft1_size samples and take a forward FFT.
  2. Extract the positive-frequency bins covering [f0 - leading_pad·Δf, f0 + trailing_pad·Δf], where the pads are expressed in tone-spacing units.
  3. Hann-taper DownsampleCfg::edge_taper_bins on each side of the extracted block to suppress FFT ringing.
  4. Cyclic-rotate so that f0 lands at DC.
  5. Inverse FFT of size DownsampleCfg::fft2_size gives the decimated complex baseband.
  6. 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§

DownsampleCfg
Runtime parameters shared by downsample, downsample_cached, and build_fft_cache. Callers typically keep one instance per protocol.

Functions§

build_fft_cache
Compute only the large forward-FFT cache. Subsequent calls to downsample_cached reuse it across all candidate frequencies, which is the expensive operation amortised by ft8-core::decode::process_candidate.
downsample
Downconvert audio to a complex baseband centred on f0.
downsample_cached
Downconvert using a pre-computed forward-FFT cache.