nk
1.0.0
C++ Numerical Computing Runtime
Toggle main menu visibility
Loading...
Searching...
No Matches
iir_filter.hpp
1
// ops/include/nk/ops/iir_filter.hpp
2
//
3
// Direct-Form-II-transposed IIR filter recurrence — the numerical core of
4
// signal's filter()/filtfilt() (and the zi/zf initial-condition forms exposed
5
// through the register layer). Raw-buffer, core-free; the recurrence is
6
// inherently sequential (each output feeds the next), so there is no SIMD
7
// backend — the value of living in ops is dedup (one kernel for filter/filtfilt/
8
// the register half) plus a single native codegen-lowering target for filter().
9
//
10
// b/a are expected a0-normalised by the caller (the Value-API divides by a(1)).
11
12
#pragma once
13
14
#include <nk/value/value.hpp>
// nk::Complex
15
#include <nk/value/scratch.hpp>
// ScratchVec
16
17
#include <cstddef>
18
#include <memory_resource>
19
20
namespace
nk::ops {
21
22
// Direct-form-II transposed IIR filter (real), applied to a flat input buffer.
23
// Optional `zi` (length ziLen) seeds the initial delay state; when `zfOut` is
24
// non-null the final state (length max(nb,na)-1) is written there — this backs
25
// MATLAB's filter(b,a,x,zi) and [y,zf] = filter(...).
26
ScratchVec<double> applyFilterDf2t(
const
double
*bn, std::size_t nb,
const
double
*an,
27
std::size_t na,
const
double
*input, std::size_t len,
28
std::pmr::memory_resource *mr,
29
const
double
*zi =
nullptr
, std::size_t ziLen = 0,
30
double
*zfOut =
nullptr
);
31
32
// Complex DF2T variant. filter() is bilinear (the recursive a-part mixes
33
// terms), so a real/imag split does not apply — the recurrence runs over
34
// Complex.
35
ScratchVec<Complex> applyFilterDf2tComplex(
const
Complex *bn, std::size_t nb,
36
const
Complex *an, std::size_t na,
37
const
Complex *input, std::size_t len,
38
std::pmr::memory_resource *mr,
39
const
Complex *zi =
nullptr
,
40
std::size_t ziLen = 0,
41
Complex *zfOut =
nullptr
);
42
43
// ── Second-order section (biquad) DF2T ────────────────────────────────────
44
// One biquad section applied in place to a single-channel signal, Direct-Form-II
45
// transposed. b/a are pre-normalised so a0 = 1:
46
// y[n] = b0*x[n] + s1; s1 = b1*x[n] - a1*y[n] + s2; s2 = b2*x[n] - a2*y[n].
47
// The building block of an SOS cascade (signal sosfilt/sosfiltfilt). Like the
48
// general DF2T above it is a sequential recurrence — no SIMD.
49
void
biquadDf2t(
double
b0,
double
b1,
double
b2,
double
a1,
double
a2,
50
const
double
*x,
double
*y, std::size_t n);
51
52
// Same recurrence seeded with an explicit initial state (s1_init, s2_init) —
53
// used by the forward/backward passes of sosfiltfilt.
54
void
biquadDf2tWithState(
double
b0,
double
b1,
double
b2,
double
a1,
double
a2,
55
const
double
*x,
double
*y, std::size_t n,
56
double
s1_init,
double
s2_init);
57
58
}
// namespace nk::ops
src
ops
include
nk
ops
iir_filter.hpp
Generated by
1.17.0