Filters

Basic fixed-point audio filters.

class tiliqua.dsp.SVF(*args, src_loc_at=0, **kwargs)

Oversampled Chamberlin State Variable Filter. Provides tunable high-, low-, and band-pass outputs given a stream of input samples. Filter cutoff and resonance are tunable at the system sample rate, with highpass, lowpass, bandpass outputs available on stream payloads hp, lp, bp.

Includes 2x oversampling internally for improved stability close to Nyquist / at high resonances. Each output sample uses 6 multiplies.

Reference: Fig.3 in https://arxiv.org/pdf/2111.05592

Members:
  • i (In(stream.Signature(StructLayout({"x": sq, "cutoff": sq, "resonance": sq}))) – Input stream for sending input x and tuning values cutoff, resonance to the filter.

  • o (Out(stream.Signature(StructLayout({"lp": sq, "hp": sq, "bp": sq}))) – Output stream for getting high-, low-, bandpass samples from the filter.

__init__(sq=ASQ, macp=None)
sqfixed.SQ

Data type for all input/output payloads of the SVF.

macpmac.MAC

Optional shared MAC provider.

class tiliqua.dsp.FIR(*args, src_loc_at=0, **kwargs)

Fixed-point FIR filter that uses a single multiplier.

This filter contains some optional optimizations to act as an efficient interpolator/decimator. For details, see stride_i, stride_o below.

Members:
  • i (In(stream.Signature(ASQ))) – Input stream for sending samples to the filter.

  • o (In(stream.Signature(ASQ))) – Output stream for getting samples from the filter. There is 1 output sample per input sample, presented filter_order+1 cycles after the input sample. For stride_o > 1, there is only 1 output sample per stride_o input samples.

__init__(fs, filter_cutoff_hz, filter_order, filter_type='lowpass', prescale=1, stride_i=1, stride_o=1, shape=ASQ)
fsint

Sample rate of the filter, used for calculating FIR coefficients.

filter_cutoff_hzint

Cutoff frequency of the filter, used for calculating FIR coefficients.

filter_orderint

Size of the filter (number of coefficients).

filter_typestr

Type of the filter passed to signal.firwin - "lowpass", "highpass" or so on.

prescalefloat

All taps are scaled by prescale. This is used in cases where you are upsampling and need to preserve energy. Be careful with this, it can overflow the tap coefficients (you’ll get a warning).

stride_iint

When an FIR filter is used as an interpolator, a common pattern is to provide 1 ‘actual’ sample and pad S-1 zeroes for every S output samples needed. For any stride > 1, the stride must evenly divide filter_order (i.e. no remainder). For stride > 1, this core applies some optimizations, assuming every S’th sample is nonzero, and the rest are zero. This results in a factor S reduction in MAC ops (latency) and a factor S reduction in RAM needed for sample storage. The tap storage remains of size filter_order as all taps are still mathematically required. The nonzero sample must be the first sample to arrive.

stride_oint

When an FIR filter is used as a decimator, it is common to keep only 1 sample and discard M-1 samples (if decimating by factor M). For stride_o == M, only 1 output sample is produced per M input samples. This does not reduce LUT/RAM usage, but avoids performing MACs to produce samples that will be discarded.

shapefixed.Shape

Fixed-point shape for input/output samples. Defaults to ASQ.

class tiliqua.dsp.DCBlock(*args, src_loc_at=0, **kwargs)

DC blocker (single-pole IIR with a cutoff near DC). Useful before components that can stack DC and overflow (e.g. matrix mixers). Only needs a single multiply per sample.

Loosely based on: https://dspguru.com/dsp/tricks/fixed-point-dc-blocking-filter-with-noise-shaping/

__init__(pole=0.999, sq=ASQ, macp=None)
polefloat

Filter cutoff. Closer to 1 is closer to DC.

sqfixed.SQ

Data type for all input/output payloads of the filter.

macpmac.MAC

Optional shared MAC provider.