filter

package
v0.3.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 2, 2026 License: Apache-2.0 Imports: 3 Imported by: 0

Documentation

Overview

Package filter implements the FIR/CIC/halfband primitives used by the DSP pipeline. All filters operate on complex64 IQ samples or real float32 signals; coefficients are stored as float32.

Index

Constants

View Source
const (
	DeEmphasis75us = 75 * time.Microsecond // FM broadcast in North America
	DeEmphasis50us = 50 * time.Microsecond // FM broadcast in Europe / most other regions
)

Common pre-emphasis time constants. Pass to NewDeEmphasis with the PCM sample rate the filter will see.

Variables

This section is empty.

Functions

func Gaussian

func Gaussian(sps, nSymbols int, bt float64) []float32

Gaussian returns the impulse response of a Gaussian pulse-shaping / matched filter parameterised by samples-per-symbol, span (in symbols), and the BT product (3 dB bandwidth × symbol period). BT = 0.3 is the standard GFSK premod for EDACS / GE-Marc; BT = 0.5 is typical for Bluetooth. Taps are normalised to unit DC gain so a sustained NRZ level passes through unchanged at the symbol centre.

func HalfbandLowpass

func HalfbandLowpass(n int) []float32

HalfbandLowpass returns coefficients for a length-N halfband lowpass suitable for ×2 decimation. Roughly half the taps are zero (every other tap except the center). Designed via Kaiser window with cutoff at fs/4.

func LowpassKaiser

func LowpassKaiser(n int, fc, beta float64) []float32

LowpassKaiser designs a length-N (odd) lowpass FIR with cutoff fc (normalized; 0.5 = Nyquist) using a Kaiser window with shape beta.

func RootRaisedCosine

func RootRaisedCosine(sps, nSymbols int, alpha float64) []float32

RootRaisedCosine returns the impulse response of a root-raised-cosine pulse-shaping filter. sps = samples per symbol, nSymbols = total span, alpha = roll-off (0 < alpha ≤ 1). The filter is normalized to unit energy.

Types

type CICDecimator

type CICDecimator struct {
	// contains filtered or unexported fields
}

CICDecimator is a multi-stage CIC decimator with rate factor R and N stages. Output is at input/R rate. Suitable for an initial coarse decimation before a sharper FIR; CIC has a sin(x)/x droop that should be compensated by a downstream FIR.

func NewCICDecimator

func NewCICDecimator(rate, stages int) *CICDecimator

func (*CICDecimator) Gain

func (c *CICDecimator) Gain() int64

Gain returns the DC gain of the cascade: R^N. Callers typically divide the output by this value (or shift right by ceil(N*log2(R))).

func (*CICDecimator) ProcessReal

func (c *CICDecimator) ProcessReal(dst []int64, src []int64) []int64

ProcessReal decimates a real signal scaled into int16 (caller scales as needed). Returns the decimated samples appended to dst.

type DeEmphasis

type DeEmphasis struct {
	// contains filtered or unexported fields
}

DeEmphasis is the single-pole IIR low-pass that recovers the pre-emphasized treble curve broadcast FM transmitters apply for SNR. The transmitter pre-emphasizes (boosts highs) with a single-pole high-shelf characterized by time constant τ; the receiver inverts with the matching low-pass:

H(s) = 1 / (1 + sτ)

Discretized impulse-invariant at sample rate fs, the difference equation is:

α   = exp(-1 / (τ × fs))
y[n] = (1 - α) × x[n] + α × y[n-1]

The DC gain is unity, the −3 dB cutoff is fc = 1 / (2π τ).

Use NewDeEmphasisUS for the 75 µs constant standard in NA, or NewDeEmphasisEU for the 50 µs constant used in most of the world.

DeEmphasis is *not* safe for concurrent Process calls — pin it to a single demod goroutine and Reset between calls.

func NewDeEmphasis

func NewDeEmphasis(tau time.Duration, sampleRate float64) *DeEmphasis

NewDeEmphasis builds a de-emphasis filter tuned to time constant τ at the given sample rate. Both must be positive; the constructor panics otherwise so misconfiguration trips at startup rather than silently producing wrong audio.

func NewDeEmphasisUS

func NewDeEmphasisUS(sampleRate float64) *DeEmphasis

NewDeEmphasisUS is shorthand for NewDeEmphasis(DeEmphasis75us, sampleRate).

func (*DeEmphasis) Process

func (d *DeEmphasis) Process(dst, src []float32) []float32

Process applies the filter to src and writes the result to dst (or appends to it). dst is reused if it has enough capacity. In-place operation (dst == src) is supported.

func (*DeEmphasis) Reset

func (d *DeEmphasis) Reset()

Reset clears the filter's running state. Call between calls so stale audio from one transmission doesn't bleed into the next.

type FIR

type FIR struct {
	// contains filtered or unexported fields
}

FIR is a linear-phase finite-impulse-response filter for complex64 IQ. It maintains an internal sample history so consecutive Process calls produce a continuous output stream.

func NewFIR

func NewFIR(taps []float32) *FIR

func (*FIR) Process

func (f *FIR) Process(dst, src []complex64) []complex64

Process consumes one input slice and returns an output slice of the same length. dst is reused if it has enough capacity.

func (*FIR) Reset

func (f *FIR) Reset()

Reset clears the internal history.

type Halfband2x

type Halfband2x struct {
	// contains filtered or unexported fields
}

Halfband2x decimates by 2 using a halfband FIR. Internally it just routes the decimated stream out of a regular FIR; we keep this as a convenience because we know half the taps multiply by zero and could be skipped in a SIMD pass later.

func NewHalfband2x

func NewHalfband2x(taps []float32) *Halfband2x

func (*Halfband2x) Process

func (h *Halfband2x) Process(dst, src []complex64) []complex64

type RealFIR

type RealFIR struct {
	// contains filtered or unexported fields
}

RealFIR is the real-valued counterpart of FIR. Same circular-buffer convolution shape, but operates on float32 audio samples instead of complex IQ. Sized for the post-demod chain in internal/voice/composer where the FM demod hands real audio to a band-limiting LPF before the second decimation to PCM.

Like FIR, it isn't safe for concurrent Process calls — pin it to a single demod goroutine and Reset between calls.

func NewRealFIR

func NewRealFIR(taps []float32) *RealFIR

NewRealFIR copies taps into a new filter and allocates the matching history ring. The constructor panics on an empty tap slice so a misconfiguration trips at startup.

func (*RealFIR) Process

func (f *RealFIR) Process(dst, src []float32) []float32

Process consumes one input slice and returns an output slice of the same length. dst is reused if it has enough capacity. In-place operation (dst == src) is supported.

func (*RealFIR) Reset

func (f *RealFIR) Reset()

Reset clears the internal history so the next Process starts fresh.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL