nx_biquad.nx
buildroot/runtime/nx_biquad.nx
about
nx_biquad.nx -- direct-form-II transposed biquad filter in Q14.
Cross-cutting Substrate B primitive per
nxc2/docs/NISHI_GAME_ENGINE_ROADMAP.md.
Biquad = second-order recursive filter section. Building block for
every parametric EQ, low-pass, high-pass, band-pass, band-stop,
peak, and shelf. Coefficients computed per Bristow-Johnson's
"Audio EQ Cookbook" (W3C public-domain reference).
This primitive ships the EVALUATION (the per-sample state-update
step + block apply); coefficient DESIGN helpers (computing b0..b2,
a1..a2 from filter_kind, cutoff, Q) ship as a follow-up primitive
once the in-house Q14 sin/cos helpers are factored out. Caller
supplies pre-normalized coefficients (a0 = 1 implicit, all others
already divided by a0).
Transposed Direct Form II:
y[n] = b0 * x[n] + s1
s1' = b1 * x[n] + s2 - a1 * y[n]
s2' = b2 * x[n] - a2 * y[n]
Two state vars instead of four. Numerically better-behaved for
IIR than Direct Form I; standard DSP-textbook recommendation.
Fixed-point: Q14 throughout (matches nx_sound's NX_SOUND_Q).
Coefficient * signal products are Q28 internally; divided down to
Q14 immediately to keep state vars in-range.
Loss audit: integer division (/Q) truncates 14 fractional bits per
multiply. For stable filters with |poles| << 1 the error is tiny;
for filters near the unit circle the error can accumulate (the same
limitation any fixed-point biquad has). Documented at the top of
every filter design helper that ships against this primitive.
genealogy_id: bristow_johnson_eq_cookbook + smith_julius_iir_filters_textbook
lineage_id: nx_biquad_tdf2_q14
dependencies 2 imports · 0 importers
imports: nx_syscalls.nxnx_tier.nx
imported by: nobody (leaf or entry point)
call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown
structs
| 75 | struct BiquadState |
consts
| 48 | const NX_MAGIC_12345: i64 = 12345 |
| 49 | const NX_MAGIC_67890: i64 = 67890 |
| 50 | const NX_MAGIC_8000: i64 = 8000 |
| 51 | const NX_MAGIC_4000: i64 = 4000 |
| 52 | const NX_MAGIC_8192: i64 = 8192 |
| 53 | const NX_MAGIC_4096: i64 = 4096 |
| 54 | const NX_MAGIC_2048: i64 = 2048 |
| 59 | const NX_BIQUAD_Q: nx_int = 16384 |
| 65 | const NX_BIQUAD_KIND_LPF: nx_int = 0 |
| 66 | const NX_BIQUAD_KIND_HPF: nx_int = 1 |
| 67 | const NX_BIQUAD_KIND_BPF: nx_int = 2 |
| 68 | const NX_BIQUAD_KIND_BSF: nx_int = 3 |
| 69 | const NX_BIQUAD_KIND_PEAK: nx_int = 4 |
| 70 | const NX_BIQUAD_KIND_LSHELF: nx_int = 5 |
| 71 | const NX_BIQUAD_KIND_HSHELF: nx_int = 6 |
functions
| 81 | func nx_biquad_kind_is_valid(k: nx_int) -> nx_int called by 1: main |
| 93 | func nx_biquad_init(s: *BiquadState) called by 1: main |
| 108 | func nx_biquad_step( |
| 139 | func nx_biquad_block( |
| 160 | func main() -> i64 |