Skip to main content

dsp_process/
lib.rs

1#![cfg_attr(not(feature = "std"), no_std)]
2#![doc = include_str!("../README.md")]
3
4mod process;
5pub use process::*;
6mod basic;
7pub use basic::*;
8mod adapters;
9pub use adapters::*;
10mod split;
11pub use split::*;
12mod compose;
13pub use compose::*;
14
15/// Parallel filter pair
16///
17/// This can be viewed as digital lattice filter or butterfly filter or complementary allpass pair
18/// or polyphase interpolator.
19/// Candidates for the branches are allpasses like Wdf or Ldi, polyphase banks for resampling or Hilbert filters.
20///
21/// Potentially required scaling with 0.5 gain is to be performed ahead of the filter, within each branch, or (with headroom) afterwards.
22///
23/// This uses the default configuration-minor/sample-major implementation
24/// and may lead to suboptimal cashing and register thrashing for large branches.
25/// To avoid this, use `block()` and `inplace()` on a scratch buffer ([`Major`] input or output).
26///
27/// The corresponding state for this is `((Unsplit<Identity>, (S0, S1)), Unsplit<Add>)`.
28pub type Pair<C0, C1, X, I = (), J = ()> = Minor<((I, Parallel<(C0, C1)>), J), [X; 2]>;
29
30#[cfg(test)]
31mod test {
32    use super::*;
33    use dsp_fixedpoint::Q32;
34
35    #[test]
36    fn basic() {
37        assert_eq!(3, Identity.process(3));
38        assert_eq!(Split::stateless(Gain(Q32::<3>::new(32))).process(9), 9 * 4);
39        assert_eq!(Split::stateless(Offset(7)).process(9), 7 + 9);
40    }
41
42    #[test]
43    fn stateless() {
44        assert_eq!(Neg.process(9), -9);
45        assert_eq!(Split::stateful(Neg).process(9), -9);
46
47        let mut p = (Split::stateless(Offset(7)) * Split::stateless(Offset(1))).minor();
48        p.assert_process::<i8, _>();
49        assert_eq!(p.process(9), 7 + 1 + 9);
50    }
51
52    #[test]
53    fn stateful() {
54        let mut xy = [3, 0, 0];
55        let mut dly = Buffer::<[_; 2]>::default();
56        dly.inplace(&mut xy);
57        assert_eq!(xy, [0, 0, 3]);
58        let y: i32 = Split::stateful(dly).process(4);
59        assert_eq!(y, 0);
60    }
61
62    #[test]
63    fn pair() {
64        let g = Gain(Q32::<1>::new(4));
65        let mut f = Split::new(
66            Pair::<_, _, _>::new((((), Parallel((Offset(3), g))), ())),
67            ((Unsplit(Identity), Default::default()), Unsplit(Add)),
68        );
69        let y: i32 = f.process(5);
70        assert_eq!(y, (5 + 3) + ((5 * 4) >> 1));
71
72        let y: [i32; 5] = f.channels().process([5; _]);
73        assert_eq!(y, [(5 + 3) + ((5 * 4) >> 1); 5]);
74    }
75}