use crate::types::*;
pub struct FirInstanceF32<'a> {
pub num_taps: u16,
pub coeffs: &'a [f32],
pub state: &'a mut [f32],
}
impl<'a> FirInstanceF32<'a> {
pub fn init(num_taps: u16, coeffs: &'a [f32], state: &'a mut [f32]) -> Self {
state.fill(0.0);
Self {
num_taps,
coeffs,
state,
}
}
}
pub fn fir_f32(instance: &mut FirInstanceF32, src: &[f32], dst: &mut [f32]) {
let num_taps = instance.num_taps as usize;
let block_size = src.len().min(dst.len());
for i in 0..block_size {
for k in (1..num_taps).rev() {
instance.state[k] = instance.state[k - 1];
}
instance.state[0] = src[i];
let mut acc = 0.0f32;
for k in 0..num_taps {
acc += instance.state[k] * instance.coeffs[k];
}
dst[i] = acc;
}
}
pub struct FirInstanceQ31<'a> {
pub num_taps: u16,
pub coeffs: &'a [q31],
pub state: &'a mut [q31],
}
impl<'a> FirInstanceQ31<'a> {
pub fn init(num_taps: u16, coeffs: &'a [q31], state: &'a mut [q31]) -> Self {
state.fill(q31::ZERO);
Self {
num_taps,
coeffs,
state,
}
}
}
pub fn fir_q31(instance: &mut FirInstanceQ31, src: &[q31], dst: &mut [q31]) {
let num_taps = instance.num_taps as usize;
let block_size = src.len().min(dst.len());
for i in 0..block_size {
for k in (1..num_taps).rev() {
instance.state[k] = instance.state[k - 1];
}
instance.state[0] = src[i];
let mut acc: i64 = 0;
for k in 0..num_taps {
acc += (instance.state[k].to_bits() as i64 * instance.coeffs[k].to_bits() as i64) >> 31;
}
dst[i] = q31::from_bits(acc.clamp(i32::MIN as i64, i32::MAX as i64) as i32);
}
}
pub struct FirInstanceQ15<'a> {
pub num_taps: u16,
pub coeffs: &'a [q15],
pub state: &'a mut [q15],
}
impl<'a> FirInstanceQ15<'a> {
pub fn init(num_taps: u16, coeffs: &'a [q15], state: &'a mut [q15]) -> Self {
state.fill(q15::ZERO);
Self {
num_taps,
coeffs,
state,
}
}
}
pub fn fir_q15(instance: &mut FirInstanceQ15, src: &[q15], dst: &mut [q15]) {
let num_taps = instance.num_taps as usize;
let block_size = src.len().min(dst.len());
for i in 0..block_size {
for k in (1..num_taps).rev() {
instance.state[k] = instance.state[k - 1];
}
instance.state[0] = src[i];
let mut acc: i32 = 0;
for k in 0..num_taps {
acc += (instance.state[k].to_bits() as i32 * instance.coeffs[k].to_bits() as i32) >> 15;
}
dst[i] = q15::from_bits(acc.clamp(i16::MIN as i32, i16::MAX as i32) as i16);
}
}
pub struct BiquadCascadeInstanceF32<'a> {
pub num_stages: u8,
pub coeffs: &'a [f32], pub state: &'a mut [f32], }
impl<'a> BiquadCascadeInstanceF32<'a> {
pub fn init(num_stages: u8, coeffs: &'a [f32], state: &'a mut [f32]) -> Self {
state.fill(0.0);
Self {
num_stages,
coeffs,
state,
}
}
}
pub fn biquad_cascade_df1_f32(
instance: &mut BiquadCascadeInstanceF32,
src: &[f32],
dst: &mut [f32],
) {
let num_stages = instance.num_stages as usize;
let block_size = src.len().min(dst.len());
let mut in_val;
let mut out_val;
for i in 0..block_size {
in_val = src[i];
for stage in 0..num_stages {
let b0 = instance.coeffs[stage * 5];
let b1 = instance.coeffs[stage * 5 + 1];
let b2 = instance.coeffs[stage * 5 + 2];
let a1 = instance.coeffs[stage * 5 + 3];
let a2 = instance.coeffs[stage * 5 + 4];
let x1 = instance.state[stage * 4];
let x2 = instance.state[stage * 4 + 1];
let y1 = instance.state[stage * 4 + 2];
let y2 = instance.state[stage * 4 + 3];
out_val = b0 * in_val + b1 * x1 + b2 * x2 + a1 * y1 + a2 * y2;
instance.state[stage * 4 + 1] = x1;
instance.state[stage * 4] = in_val;
instance.state[stage * 4 + 3] = y1;
instance.state[stage * 4 + 2] = out_val;
in_val = out_val;
}
dst[i] = in_val;
}
}
pub struct BiquadCascadeDf2tInstanceF32<'a> {
pub num_stages: u8,
pub coeffs: &'a [f32],
pub state: &'a mut [f32],
}
impl<'a> BiquadCascadeDf2tInstanceF32<'a> {
pub fn init(num_stages: u8, coeffs: &'a [f32], state: &'a mut [f32]) -> Self {
state.fill(0.0);
Self {
num_stages,
coeffs,
state,
}
}
}
pub fn biquad_cascade_df2t_f32(
instance: &mut BiquadCascadeDf2tInstanceF32,
src: &[f32],
dst: &mut [f32],
) {
let num_stages = instance.num_stages as usize;
let block_size = src.len().min(dst.len());
for i in 0..block_size {
let mut in_val = src[i];
for stage in 0..num_stages {
let b0 = instance.coeffs[stage * 5];
let b1 = instance.coeffs[stage * 5 + 1];
let b2 = instance.coeffs[stage * 5 + 2];
let a1 = instance.coeffs[stage * 5 + 3];
let a2 = instance.coeffs[stage * 5 + 4];
let s1 = instance.state[stage * 2];
let s2 = instance.state[stage * 2 + 1];
let y = b0 * in_val + s1;
instance.state[stage * 2] = b1 * in_val + a1 * y + s2;
instance.state[stage * 2 + 1] = b2 * in_val + a2 * y;
in_val = y;
}
dst[i] = in_val;
}
}
pub struct BiquadCascadeInstanceQ15<'a> {
pub num_stages: u8,
pub post_shift: u8,
pub coeffs: &'a [q15],
pub state: &'a mut [q15],
}
impl<'a> BiquadCascadeInstanceQ15<'a> {
pub fn init(num_stages: u8, coeffs: &'a [q15], state: &'a mut [q15], post_shift: u8) -> Self {
state.fill(q15::ZERO);
Self {
num_stages,
post_shift,
coeffs,
state,
}
}
}
pub fn biquad_cascade_df1_q15(
instance: &mut BiquadCascadeInstanceQ15,
src: &[q15],
dst: &mut [q15],
) {
let num_stages = instance.num_stages as usize;
let block_size = src.len().min(dst.len());
let shift = 15u32.saturating_sub(instance.post_shift as u32).min(31);
for i in 0..block_size {
let mut in_val = src[i].to_bits() as i64;
for stage in 0..num_stages {
let b0 = instance.coeffs[stage * 5].to_bits() as i64;
let b1 = instance.coeffs[stage * 5 + 1].to_bits() as i64;
let b2 = instance.coeffs[stage * 5 + 2].to_bits() as i64;
let a1 = instance.coeffs[stage * 5 + 3].to_bits() as i64;
let a2 = instance.coeffs[stage * 5 + 4].to_bits() as i64;
let x1 = instance.state[stage * 4].to_bits() as i64;
let x2 = instance.state[stage * 4 + 1].to_bits() as i64;
let y1 = instance.state[stage * 4 + 2].to_bits() as i64;
let y2 = instance.state[stage * 4 + 3].to_bits() as i64;
let acc = b0 * in_val + b1 * x1 + b2 * x2 + a1 * y1 + a2 * y2;
let out_val = (acc >> shift).clamp(i16::MIN as i64, i16::MAX as i64);
instance.state[stage * 4 + 1] = q15::from_bits(x1 as i16);
instance.state[stage * 4] = q15::from_bits(in_val as i16);
instance.state[stage * 4 + 3] = q15::from_bits(y1 as i16);
instance.state[stage * 4 + 2] = q15::from_bits(out_val as i16);
in_val = out_val;
}
dst[i] = q15::from_bits(in_val as i16);
}
}
pub struct BiquadCascadeInstanceQ31<'a> {
pub num_stages: u8,
pub post_shift: u8,
pub coeffs: &'a [q31],
pub state: &'a mut [q31],
}
impl<'a> BiquadCascadeInstanceQ31<'a> {
pub fn init(num_stages: u8, coeffs: &'a [q31], state: &'a mut [q31], post_shift: u8) -> Self {
state.fill(q31::ZERO);
Self {
num_stages,
post_shift,
coeffs,
state,
}
}
}
pub fn biquad_cascade_df1_q31(
instance: &mut BiquadCascadeInstanceQ31,
src: &[q31],
dst: &mut [q31],
) {
let num_stages = instance.num_stages as usize;
let block_size = src.len().min(dst.len());
let shift = 31u32.saturating_sub(instance.post_shift as u32).min(63);
for i in 0..block_size {
let mut in_val = src[i].to_bits() as i64;
for stage in 0..num_stages {
let b0 = instance.coeffs[stage * 5].to_bits() as i64;
let b1 = instance.coeffs[stage * 5 + 1].to_bits() as i64;
let b2 = instance.coeffs[stage * 5 + 2].to_bits() as i64;
let a1 = instance.coeffs[stage * 5 + 3].to_bits() as i64;
let a2 = instance.coeffs[stage * 5 + 4].to_bits() as i64;
let x1 = instance.state[stage * 4].to_bits() as i64;
let x2 = instance.state[stage * 4 + 1].to_bits() as i64;
let y1 = instance.state[stage * 4 + 2].to_bits() as i64;
let y2 = instance.state[stage * 4 + 3].to_bits() as i64;
let acc = b0 * in_val + b1 * x1 + b2 * x2 + a1 * y1 + a2 * y2;
let out_val = (acc >> shift).clamp(i32::MIN as i64, i32::MAX as i64);
instance.state[stage * 4 + 1] = q31::from_bits(x1 as i32);
instance.state[stage * 4] = q31::from_bits(in_val as i32);
instance.state[stage * 4 + 3] = q31::from_bits(y1 as i32);
instance.state[stage * 4 + 2] = q31::from_bits(out_val as i32);
in_val = out_val;
}
dst[i] = q31::from_bits(in_val as i32);
}
}
pub struct BiquadCascadeDf2tInstanceQ15<'a> {
pub num_stages: u8,
pub post_shift: u8,
pub coeffs: &'a [q15],
pub state: &'a mut [q15],
}
impl<'a> BiquadCascadeDf2tInstanceQ15<'a> {
pub fn init(num_stages: u8, coeffs: &'a [q15], state: &'a mut [q15], post_shift: u8) -> Self {
state.fill(q15::ZERO);
Self {
num_stages,
post_shift,
coeffs,
state,
}
}
}
pub fn biquad_cascade_df2t_q15(
instance: &mut BiquadCascadeDf2tInstanceQ15,
src: &[q15],
dst: &mut [q15],
) {
let num_stages = instance.num_stages as usize;
let block_size = src.len().min(dst.len());
let shift = 15u32.saturating_sub(instance.post_shift as u32).min(31);
for i in 0..block_size {
let mut in_val = src[i].to_bits() as i64;
for stage in 0..num_stages {
let b0 = instance.coeffs[stage * 5].to_bits() as i64;
let b1 = instance.coeffs[stage * 5 + 1].to_bits() as i64;
let b2 = instance.coeffs[stage * 5 + 2].to_bits() as i64;
let a1 = instance.coeffs[stage * 5 + 3].to_bits() as i64;
let a2 = instance.coeffs[stage * 5 + 4].to_bits() as i64;
let s1 = instance.state[stage * 2].to_bits() as i64;
let s2 = instance.state[stage * 2 + 1].to_bits() as i64;
let y = (b0 * in_val + (s1 << shift)).clamp(i64::MIN >> 1, i64::MAX >> 1) >> shift;
let out_val = y.clamp(i16::MIN as i64, i16::MAX as i64);
let s1_new = (b1 * in_val + a1 * out_val + (s2 << shift)) >> shift;
let s2_new = (b2 * in_val + a2 * out_val) >> shift;
instance.state[stage * 2] =
q15::from_bits(s1_new.clamp(i16::MIN as i64, i16::MAX as i64) as i16);
instance.state[stage * 2 + 1] =
q15::from_bits(s2_new.clamp(i16::MIN as i64, i16::MAX as i64) as i16);
in_val = out_val;
}
dst[i] = q15::from_bits(in_val as i16);
}
}
pub struct BiquadCascadeDf2tInstanceQ31<'a> {
pub num_stages: u8,
pub post_shift: u8,
pub coeffs: &'a [q31],
pub state: &'a mut [q31],
}
impl<'a> BiquadCascadeDf2tInstanceQ31<'a> {
pub fn init(num_stages: u8, coeffs: &'a [q31], state: &'a mut [q31], post_shift: u8) -> Self {
state.fill(q31::ZERO);
Self {
num_stages,
post_shift,
coeffs,
state,
}
}
}
pub fn biquad_cascade_df2t_q31(
instance: &mut BiquadCascadeDf2tInstanceQ31,
src: &[q31],
dst: &mut [q31],
) {
let num_stages = instance.num_stages as usize;
let block_size = src.len().min(dst.len());
let shift = 31u32.saturating_sub(instance.post_shift as u32).min(63);
for i in 0..block_size {
let mut in_val = src[i].to_bits() as i64;
for stage in 0..num_stages {
let b0 = instance.coeffs[stage * 5].to_bits() as i64;
let b1 = instance.coeffs[stage * 5 + 1].to_bits() as i64;
let b2 = instance.coeffs[stage * 5 + 2].to_bits() as i64;
let a1 = instance.coeffs[stage * 5 + 3].to_bits() as i64;
let a2 = instance.coeffs[stage * 5 + 4].to_bits() as i64;
let s1 = instance.state[stage * 2].to_bits() as i64;
let s2 = instance.state[stage * 2 + 1].to_bits() as i64;
let y = (b0 * in_val + (s1 << shift)).clamp(i64::MIN >> 1, i64::MAX >> 1) >> shift;
let out_val = y.clamp(i32::MIN as i64, i32::MAX as i64);
let s1_new = (b1 * in_val + a1 * out_val + (s2 << shift)) >> shift;
let s2_new = (b2 * in_val + a2 * out_val) >> shift;
instance.state[stage * 2] =
q31::from_bits(s1_new.clamp(i32::MIN as i64, i32::MAX as i64) as i32);
instance.state[stage * 2 + 1] =
q31::from_bits(s2_new.clamp(i32::MIN as i64, i32::MAX as i64) as i32);
in_val = out_val;
}
dst[i] = q31::from_bits(in_val as i32);
}
}
pub struct LmsInstanceF32<'a> {
pub num_taps: u16,
pub coeffs: &'a mut [f32],
pub state: &'a mut [f32],
pub mu: f32,
}
impl<'a> LmsInstanceF32<'a> {
pub fn init(num_taps: u16, coeffs: &'a mut [f32], state: &'a mut [f32], mu: f32) -> Self {
state.fill(0.0);
coeffs.fill(0.0);
Self {
num_taps,
coeffs,
state,
mu,
}
}
}
pub fn lms_f32(
instance: &mut LmsInstanceF32,
src: &[f32],
ref_signal: &[f32],
out: &mut [f32],
err: &mut [f32],
) {
let num_taps = instance.num_taps as usize;
let block_size = src
.len()
.min(ref_signal.len())
.min(out.len())
.min(err.len());
for i in 0..block_size {
for k in (1..num_taps).rev() {
instance.state[k] = instance.state[k - 1];
}
instance.state[0] = src[i];
let mut acc = 0.0f32;
for k in 0..num_taps {
acc += instance.state[k] * instance.coeffs[k];
}
out[i] = acc;
let e = ref_signal[i] - acc;
err[i] = e;
let alpha = 2.0 * instance.mu * e;
for k in 0..num_taps {
instance.coeffs[k] += alpha * instance.state[k];
}
}
}
pub fn lms_leaky_f32(
instance: &mut LmsInstanceF32,
src: &[f32],
ref_signal: &[f32],
out: &mut [f32],
err: &mut [f32],
leak: f32,
) {
let num_taps = instance.num_taps as usize;
let block_size = src
.len()
.min(ref_signal.len())
.min(out.len())
.min(err.len());
let keep = 1.0 - leak;
for i in 0..block_size {
for k in (1..num_taps).rev() {
instance.state[k] = instance.state[k - 1];
}
instance.state[0] = src[i];
let mut acc = 0.0f32;
for k in 0..num_taps {
acc += instance.state[k] * instance.coeffs[k];
}
out[i] = acc;
let e = ref_signal[i] - acc;
err[i] = e;
let alpha = 2.0 * instance.mu * e;
for k in 0..num_taps {
instance.coeffs[k] = keep * instance.coeffs[k] + alpha * instance.state[k];
}
}
}
pub struct NlmsInstanceF32<'a> {
pub num_taps: u16,
pub coeffs: &'a mut [f32],
pub state: &'a mut [f32],
pub mu: f32,
pub eps: f32,
}
impl<'a> NlmsInstanceF32<'a> {
pub fn init(
num_taps: u16,
coeffs: &'a mut [f32],
state: &'a mut [f32],
mu: f32,
eps: f32,
) -> Self {
state.fill(0.0);
coeffs.fill(0.0);
Self {
num_taps,
coeffs,
state,
mu,
eps,
}
}
}
pub fn nlms_f32(
instance: &mut NlmsInstanceF32,
src: &[f32],
ref_signal: &[f32],
out: &mut [f32],
err: &mut [f32],
) {
let num_taps = instance.num_taps as usize;
let block_size = src
.len()
.min(ref_signal.len())
.min(out.len())
.min(err.len());
for i in 0..block_size {
for k in (1..num_taps).rev() {
instance.state[k] = instance.state[k - 1];
}
instance.state[0] = src[i];
let mut acc = 0.0f32;
let mut power = instance.eps;
for k in 0..num_taps {
acc += instance.state[k] * instance.coeffs[k];
power += instance.state[k] * instance.state[k];
}
out[i] = acc;
let e = ref_signal[i] - acc;
err[i] = e;
let alpha = instance.mu * e / power;
for k in 0..num_taps {
instance.coeffs[k] += alpha * instance.state[k];
}
}
}
pub struct LmsInstanceQ15<'a> {
pub num_taps: u16,
pub coeffs: &'a mut [q15],
pub state: &'a mut [q15],
pub mu: q15,
}
impl<'a> LmsInstanceQ15<'a> {
pub fn init(num_taps: u16, coeffs: &'a mut [q15], state: &'a mut [q15], mu: q15) -> Self {
state.fill(q15::ZERO);
coeffs.fill(q15::ZERO);
Self {
num_taps,
coeffs,
state,
mu,
}
}
}
fn lms_q15_inner(
instance: &mut LmsInstanceQ15,
src: &[q15],
ref_signal: &[q15],
out: &mut [q15],
err: &mut [q15],
leak: q15,
) {
let num_taps = instance.num_taps as usize;
let block_size = src
.len()
.min(ref_signal.len())
.min(out.len())
.min(err.len());
let keep = 32767i32 - leak.to_bits().max(0) as i32;
for i in 0..block_size {
for k in (1..num_taps).rev() {
instance.state[k] = instance.state[k - 1];
}
instance.state[0] = src[i];
let mut acc: i64 = 0;
for k in 0..num_taps {
acc += instance.state[k].to_bits() as i64 * instance.coeffs[k].to_bits() as i64;
}
let y = (acc >> 15).clamp(i16::MIN as i64, i16::MAX as i64);
out[i] = q15::from_bits(y as i16);
let e = (ref_signal[i].to_bits() as i32 - y as i32).clamp(i16::MIN as i32, i16::MAX as i32);
err[i] = q15::from_bits(e as i16);
let alpha = (2i64 * instance.mu.to_bits() as i64 * e as i64) >> 15;
for k in 0..num_taps {
let leaked = (keep as i64 * instance.coeffs[k].to_bits() as i64) >> 15;
let upd = leaked + ((alpha * instance.state[k].to_bits() as i64) >> 15);
instance.coeffs[k] = q15::from_bits(upd.clamp(i16::MIN as i64, i16::MAX as i64) as i16);
}
}
}
pub fn lms_q15(
instance: &mut LmsInstanceQ15,
src: &[q15],
ref_signal: &[q15],
out: &mut [q15],
err: &mut [q15],
) {
lms_q15_inner(instance, src, ref_signal, out, err, q15::ZERO);
}
pub fn lms_leaky_q15(
instance: &mut LmsInstanceQ15,
src: &[q15],
ref_signal: &[q15],
out: &mut [q15],
err: &mut [q15],
leak: q15,
) {
lms_q15_inner(instance, src, ref_signal, out, err, leak);
}
pub struct NlmsInstanceQ15<'a> {
pub num_taps: u16,
pub coeffs: &'a mut [q15],
pub state: &'a mut [q15],
pub mu: q15,
pub eps: q15,
}
impl<'a> NlmsInstanceQ15<'a> {
pub fn init(
num_taps: u16,
coeffs: &'a mut [q15],
state: &'a mut [q15],
mu: q15,
eps: q15,
) -> Self {
state.fill(q15::ZERO);
coeffs.fill(q15::ZERO);
Self {
num_taps,
coeffs,
state,
mu,
eps,
}
}
}
pub fn nlms_q15(
instance: &mut NlmsInstanceQ15,
src: &[q15],
ref_signal: &[q15],
out: &mut [q15],
err: &mut [q15],
) {
let num_taps = instance.num_taps as usize;
let block_size = src
.len()
.min(ref_signal.len())
.min(out.len())
.min(err.len());
for i in 0..block_size {
for k in (1..num_taps).rev() {
instance.state[k] = instance.state[k - 1];
}
instance.state[0] = src[i];
let mut acc: i64 = 0;
let mut power: i64 = instance.eps.to_bits().max(1) as i64;
for k in 0..num_taps {
let x = instance.state[k].to_bits() as i64;
acc += x * instance.coeffs[k].to_bits() as i64;
power += (x * x) >> 15;
}
let y = (acc >> 15).clamp(i16::MIN as i64, i16::MAX as i64);
out[i] = q15::from_bits(y as i16);
let e = (ref_signal[i].to_bits() as i32 - y as i32).clamp(i16::MIN as i32, i16::MAX as i32);
err[i] = q15::from_bits(e as i16);
let alpha = (instance.mu.to_bits() as i64 * e as i64) / power;
for k in 0..num_taps {
let upd = instance.coeffs[k].to_bits() as i64
+ ((alpha * instance.state[k].to_bits() as i64) >> 15);
instance.coeffs[k] = q15::from_bits(upd.clamp(i16::MIN as i64, i16::MAX as i64) as i16);
}
}
}
pub fn conv_f32(src_a: &[f32], src_b: &[f32], dst: &mut [f32]) {
let len_a = src_a.len();
let len_b = src_b.len();
let out_len = (len_a + len_b - 1).min(dst.len());
dst[..out_len].fill(0.0);
for i in 0..len_a {
for j in 0..len_b {
if i + j < out_len {
dst[i + j] += src_a[i] * src_b[j];
}
}
}
}
pub fn conv_q31(src_a: &[q31], src_b: &[q31], dst: &mut [q31]) {
let len_a = src_a.len();
let len_b = src_b.len();
let out_len = (len_a + len_b - 1).min(dst.len());
for n in 0..out_len {
let mut acc: i64 = 0;
let k_min = if n >= len_b - 1 { n - (len_b - 1) } else { 0 };
let k_max = n.min(len_a - 1);
for k in k_min..=k_max {
acc += (src_a[k].to_bits() as i64 * src_b[n - k].to_bits() as i64) >> 31;
}
dst[n] = q31::from_bits(acc.clamp(i32::MIN as i64, i32::MAX as i64) as i32);
}
}
pub fn conv_q15(src_a: &[q15], src_b: &[q15], dst: &mut [q15]) {
let len_a = src_a.len();
let len_b = src_b.len();
let out_len = (len_a + len_b - 1).min(dst.len());
for n in 0..out_len {
let mut acc: i32 = 0;
let k_min = if n >= len_b - 1 { n - (len_b - 1) } else { 0 };
let k_max = n.min(len_a - 1);
for k in k_min..=k_max {
acc += (src_a[k].to_bits() as i32 * src_b[n - k].to_bits() as i32) >> 15;
}
dst[n] = q15::from_bits(acc.clamp(i16::MIN as i32, i16::MAX as i32) as i16);
}
}
pub fn conv_q7(src_a: &[q7], src_b: &[q7], dst: &mut [q7]) {
let len_a = src_a.len();
let len_b = src_b.len();
let out_len = (len_a + len_b - 1).min(dst.len());
for n in 0..out_len {
let mut acc: i32 = 0;
let k_min = if n >= len_b - 1 { n - (len_b - 1) } else { 0 };
let k_max = n.min(len_a - 1);
for k in k_min..=k_max {
acc += (src_a[k].to_bits() as i32 * src_b[n - k].to_bits() as i32) >> 7;
}
dst[n] = q7::from_bits(acc.clamp(i8::MIN as i32, i8::MAX as i32) as i8);
}
}
pub fn correlate_f32(src_a: &[f32], src_b: &[f32], dst: &mut [f32]) {
let len_a = src_a.len();
let len_b = src_b.len();
let out_len = (len_a + len_b - 1).min(dst.len());
dst[..out_len].fill(0.0);
for n in 0..out_len {
let mut acc = 0.0f32;
for k in 0..len_a {
let idx_b = (k as isize) + (len_b as isize - 1) - (n as isize);
if idx_b >= 0 && (idx_b as usize) < len_b {
acc += src_a[k] * src_b[idx_b as usize];
}
}
dst[n] = acc;
}
}
pub fn correlate_q31(src_a: &[q31], src_b: &[q31], dst: &mut [q31]) {
let len_a = src_a.len();
let len_b = src_b.len();
let out_len = (len_a + len_b - 1).min(dst.len());
for n in 0..out_len {
let mut acc: i64 = 0;
for k in 0..len_a {
let idx_b = (k as isize) + (len_b as isize - 1) - (n as isize);
if idx_b >= 0 && (idx_b as usize) < len_b {
acc += (src_a[k].to_bits() as i64 * src_b[idx_b as usize].to_bits() as i64) >> 31;
}
}
dst[n] = q31::from_bits(acc.clamp(i32::MIN as i64, i32::MAX as i64) as i32);
}
}
pub fn correlate_q15(src_a: &[q15], src_b: &[q15], dst: &mut [q15]) {
let len_a = src_a.len();
let len_b = src_b.len();
let out_len = (len_a + len_b - 1).min(dst.len());
for n in 0..out_len {
let mut acc: i32 = 0;
for k in 0..len_a {
let idx_b = (k as isize) + (len_b as isize - 1) - (n as isize);
if idx_b >= 0 && (idx_b as usize) < len_b {
acc += (src_a[k].to_bits() as i32 * src_b[idx_b as usize].to_bits() as i32) >> 15;
}
}
dst[n] = q15::from_bits(acc.clamp(i16::MIN as i32, i16::MAX as i32) as i16);
}
}
#[allow(unused_imports)]
use crate::math::FloatMath;
#[cfg(feature = "transform")]
use crate::transform::cfft_f32;
pub fn median_filter_1d_f32(
src: &[f32],
dst: &mut [f32],
window_len: usize,
threshold: f32,
) -> Status {
let n = src.len();
if n == 0 || dst.len() < n {
return Status::LengthError;
}
if window_len == 0 || window_len % 2 == 0 || window_len > 63 {
return Status::ArgumentError;
}
let half = window_len / 2;
let mut sort_buf = [0.0f32; 64];
for i in 0..n {
for j in 0..window_len {
let idx = (i as isize + j as isize - half as isize).clamp(0, (n - 1) as isize) as usize;
sort_buf[j] = src[idx];
}
for a in 1..window_len {
let mut b = a;
while b > 0 && sort_buf[b - 1] > sort_buf[b] {
sort_buf.swap(b - 1, b);
b -= 1;
}
}
let med = sort_buf[half];
let center = src[i];
if (center - med).abs() >= threshold {
dst[i] = med;
} else {
dst[i] = center;
}
}
Status::Success
}
pub fn median_filter_1d_q15(
src: &[q15],
dst: &mut [q15],
window_len: usize,
threshold: q15,
) -> Status {
let n = src.len();
if n == 0 || dst.len() < n {
return Status::LengthError;
}
if window_len == 0 || window_len % 2 == 0 || window_len > 63 {
return Status::ArgumentError;
}
let half = window_len / 2;
let mut sort_buf = [q15::ZERO; 64];
for i in 0..n {
for j in 0..window_len {
let idx = (i as isize + j as isize - half as isize).clamp(0, (n - 1) as isize) as usize;
sort_buf[j] = src[idx];
}
for a in 1..window_len {
let mut b = a;
while b > 0 && sort_buf[b - 1] > sort_buf[b] {
sort_buf.swap(b - 1, b);
b -= 1;
}
}
let med = sort_buf[half];
let center = src[i];
let diff = (center.to_bits() as i32 - med.to_bits() as i32).abs();
if diff >= threshold.to_bits() as i32 {
dst[i] = med;
} else {
dst[i] = center;
}
}
Status::Success
}
pub fn median_filter_1d_q31(
src: &[q31],
dst: &mut [q31],
window_len: usize,
threshold: q31,
) -> Status {
let n = src.len();
if n == 0 || dst.len() < n {
return Status::LengthError;
}
if window_len == 0 || window_len % 2 == 0 || window_len > 63 {
return Status::ArgumentError;
}
let half = window_len / 2;
let mut sort_buf = [q31::ZERO; 64];
for i in 0..n {
for j in 0..window_len {
let idx = (i as isize + j as isize - half as isize).clamp(0, (n - 1) as isize) as usize;
sort_buf[j] = src[idx];
}
for a in 1..window_len {
let mut b = a;
while b > 0 && sort_buf[b - 1] > sort_buf[b] {
sort_buf.swap(b - 1, b);
b -= 1;
}
}
let med = sort_buf[half];
let center = src[i];
let diff = (center.to_bits() as i64 - med.to_bits() as i64).abs();
if diff >= threshold.to_bits() as i64 {
dst[i] = med;
} else {
dst[i] = center;
}
}
Status::Success
}
#[cfg(feature = "transform")]
pub fn fast_convolve_f32(signal: &[f32], kernel: &[f32], dst: &mut [f32]) -> Status {
let len_sig = signal.len();
let len_ker = kernel.len();
if len_sig == 0 || len_ker == 0 {
return Status::LengthError;
}
let total_len = len_sig + len_ker - 1;
if dst.len() < total_len {
return Status::LengthError;
}
let mut fft_n = 1;
while fft_n < total_len {
fft_n <<= 1;
}
if fft_n > 512 {
conv_f32(signal, kernel, dst);
return Status::Success;
}
let mut sig_buf = [0.0f32; 1024]; let mut ker_buf = [0.0f32; 1024];
for i in 0..len_sig {
sig_buf[2 * i] = signal[i];
}
for i in 0..len_ker {
ker_buf[2 * i] = kernel[i];
}
cfft_f32(&mut sig_buf[..2 * fft_n], fft_n, 0, 1);
cfft_f32(&mut ker_buf[..2 * fft_n], fft_n, 0, 1);
for i in 0..fft_n {
let a = sig_buf[2 * i];
let b = sig_buf[2 * i + 1];
let c = ker_buf[2 * i];
let d = ker_buf[2 * i + 1];
sig_buf[2 * i] = a * c - b * d;
sig_buf[2 * i + 1] = a * d + b * c;
}
cfft_f32(&mut sig_buf[..2 * fft_n], fft_n, 1, 1);
for i in 0..total_len {
dst[i] = sig_buf[2 * i];
}
Status::Success
}
#[derive(Debug, Clone, Copy)]
pub struct CircularBuffer<T, const N: usize> {
buffer: [T; N],
head: usize,
count: usize,
}
impl<T: Copy, const N: usize> CircularBuffer<T, N> {
pub const fn new(init_val: T) -> Self {
Self {
buffer: [init_val; N],
head: 0,
count: 0,
}
}
#[inline(always)]
pub fn push(&mut self, sample: T) {
if N == 0 {
return;
}
self.buffer[self.head] = sample;
self.head = (self.head + 1) % N;
if self.count < N {
self.count += 1;
}
}
#[inline(always)]
pub fn get(&self, lag: usize) -> Option<T> {
if lag >= self.count || N == 0 {
return None;
}
let idx = (self.head + N - 1 - (lag % N)) % N;
Some(self.buffer[idx])
}
#[inline(always)]
pub fn latest(&self) -> Option<T> {
self.get(0)
}
#[inline(always)]
pub fn oldest(&self) -> Option<T> {
if self.count == 0 {
None
} else {
self.get(self.count - 1)
}
}
#[inline(always)]
pub const fn len(&self) -> usize {
self.count
}
#[inline(always)]
pub const fn capacity(&self) -> usize {
N
}
#[inline(always)]
pub const fn is_empty(&self) -> bool {
self.count == 0
}
#[inline(always)]
pub const fn is_full(&self) -> bool {
self.count == N
}
pub fn clear(&mut self, reset_val: T) {
self.buffer = [reset_val; N];
self.head = 0;
self.count = 0;
}
}
#[derive(Debug, Clone, Copy, Default)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct SinglePoleFilter {
b0: f32,
b1: f32,
a1: f32,
x1: f32,
y1: f32,
}
impl SinglePoleFilter {
pub fn lowpass(decay: f32) -> Self {
Self {
b0: 1.0 - decay,
b1: 0.0,
a1: decay,
x1: 0.0,
y1: 0.0,
}
}
pub fn highpass(decay: f32) -> Self {
let b0 = (1.0 + decay) / 2.0;
Self {
b0,
b1: -b0,
a1: decay,
x1: 0.0,
y1: 0.0,
}
}
#[inline(always)]
pub fn process(&mut self, x: f32) -> f32 {
let y = self.b0 * x + self.b1 * self.x1 + self.a1 * self.y1;
self.x1 = x;
self.y1 = y;
y
}
pub fn reset(&mut self) {
self.x1 = 0.0;
self.y1 = 0.0;
}
}
#[derive(Debug, Clone, Copy, Default)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct SinglePoleFilterQ15 {
b0: q15,
b1: q15,
a1: q15,
x1: q15,
y1: q15,
}
impl SinglePoleFilterQ15 {
pub fn lowpass(decay: q15) -> Self {
let decay = decay.max(q15::ZERO);
Self {
b0: q15::from_bits((32767i32 - decay.to_bits() as i32) as i16),
b1: q15::ZERO,
a1: decay,
x1: q15::ZERO,
y1: q15::ZERO,
}
}
pub fn highpass(decay: q15) -> Self {
let decay = decay.max(q15::ZERO);
let b0 = q15::from_bits(((32767i32 + decay.to_bits() as i32) / 2) as i16);
Self {
b0,
b1: -b0,
a1: decay,
x1: q15::ZERO,
y1: q15::ZERO,
}
}
pub fn lowpass_from_f32(decay: f32) -> Self {
Self::lowpass(q15::saturating_from_num(decay.clamp(0.0, 1.0)))
}
pub fn highpass_from_f32(decay: f32) -> Self {
Self::highpass(q15::saturating_from_num(decay.clamp(0.0, 1.0)))
}
#[inline(always)]
pub fn process(&mut self, x: q15) -> q15 {
let y = (self.b0.to_bits() as i64 * x.to_bits() as i64
+ self.b1.to_bits() as i64 * self.x1.to_bits() as i64
+ self.a1.to_bits() as i64 * self.y1.to_bits() as i64)
>> 15;
let y = q15::from_bits(y.clamp(i16::MIN as i64, i16::MAX as i64) as i16);
self.x1 = x;
self.y1 = y;
y
}
pub fn reset(&mut self) {
self.x1 = q15::ZERO;
self.y1 = q15::ZERO;
}
}
#[derive(Debug, Clone, Copy, Default)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct DcBlockerQ15 {
inner: SinglePoleFilterQ15,
}
impl DcBlockerQ15 {
pub fn new(decay: q15) -> Self {
Self {
inner: SinglePoleFilterQ15::highpass(decay),
}
}
pub fn from_f32_decay(decay: f32) -> Self {
Self {
inner: SinglePoleFilterQ15::highpass_from_f32(decay),
}
}
#[inline(always)]
pub fn process(&mut self, x: q15) -> q15 {
self.inner.process(x)
}
pub fn reset(&mut self) {
self.inner.reset();
}
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct RecursiveMovingAverage<const N: usize> {
history: CircularBuffer<f32, N>,
sum: f32,
}
impl<const N: usize> RecursiveMovingAverage<N> {
pub const fn new() -> Self {
Self {
history: CircularBuffer::new(0.0),
sum: 0.0,
}
}
#[inline(always)]
pub fn process(&mut self, x: f32) -> f32 {
let oldest = if self.history.is_full() {
self.history.oldest().unwrap_or(0.0)
} else {
0.0
};
self.sum += x - oldest;
self.history.push(x);
if self.history.len() == 0 {
0.0
} else {
self.sum / self.history.len() as f32
}
}
pub fn reset(&mut self) {
self.history.clear(0.0);
self.sum = 0.0;
}
}
impl<const N: usize> Default for RecursiveMovingAverage<N> {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct RecursiveMovingAverageQ15<const N: usize> {
history: CircularBuffer<q15, N>,
sum: i32,
}
impl<const N: usize> RecursiveMovingAverageQ15<N> {
pub const fn new() -> Self {
Self {
history: CircularBuffer::new(q15::ZERO),
sum: 0,
}
}
#[inline(always)]
pub fn process(&mut self, x: q15) -> q15 {
let oldest = if self.history.is_full() {
self.history.oldest().unwrap_or(q15::ZERO)
} else {
q15::ZERO
};
self.sum += x.to_bits() as i32 - oldest.to_bits() as i32;
self.history.push(x);
if self.history.len() == 0 {
q15::ZERO
} else {
q15::from_bits(
(self.sum / self.history.len() as i32).clamp(i16::MIN as i32, i16::MAX as i32)
as i16,
)
}
}
pub fn reset(&mut self) {
self.history.clear(q15::ZERO);
self.sum = 0;
}
}
impl<const N: usize> Default for RecursiveMovingAverageQ15<N> {
fn default() -> Self {
Self::new()
}
}