K

Process the spectrum

Work in the frequency domain.

To edit audio by frequency, construct a Spectral STFT in prepare and call process(ctx) each block. The host re-enters processSpectrum once per hop with the complex spectrum.

private stft: Spectral | null = null;

prepare(sampleRate: f64, maxBlock: i32): void {
  this.stft = new Spectral(1024, 2, maxBlock); // fftSize, channels, maxBlock
}

process(ctx: Ctx): void {
  const stft = this.stft;
  if (stft == null) return;
  stft.process(ctx);
}

Edit bins in processSpectrum. A brickwall lowpass keeps the lowest bins and zeroes the rest:

processSpectrum(frame: SpectralFrame, ctx: Ctx): void {
  const keep = <i32>(<f32>frame.binCount * ctx.param(0));
  for (let ch = 0; ch < frame.numChannels; ch++) {
    for (let b = keep; b < frame.binCount; b++) {
      frame.set(ch, b, 0.0, 0.0);
    }
  }
}

Read with frame.real(ch, bin) / frame.imag(ch, bin), overwrite with frame.set(...), or scale a bin's magnitude while keeping its phase with frame.scale(ch, bin, g). Whatever you leave is resynthesized; for an analysis-only pass, never write back. The export * line already exposes the per-frame entry point.

An STFT delays the signal by fftSize, so report it: m.latency(1024).

Note

For a vocoder, pass a sidechain channel count as the 6th Spectral argument and declare a sidechainIn port, then read the modulator's spectrum per bin with frame.sidechainMag(ch, bin). For full control over windowing and hop (a phase vocoder, time-stretch), drop to the raw Fft primitive.

See DSP blocks.