simple_src/
lib.rs

1//! Simple sample rate conversion lib.
2//!
3//! ## Usage
4//!
5//! See [sinc] or [linear]
6
7pub mod linear;
8pub mod sinc;
9
10pub struct ConvertIter<'a, I, C> {
11    iter: I,
12    cvtr: &'a mut C,
13}
14
15impl<'a, I, C> ConvertIter<'a, I, C> {
16    #[inline]
17    pub fn new(iter: I, cvtr: &'a mut C) -> Self {
18        Self { iter, cvtr }
19    }
20}
21
22impl<I, C> Iterator for ConvertIter<'_, I, C>
23where
24    I: Iterator<Item = f64>,
25    C: Convert,
26{
27    type Item = f64;
28
29    #[inline]
30    fn next(&mut self) -> Option<Self::Item> {
31        self.cvtr.next_sample(&mut self.iter)
32    }
33}
34
35pub trait Convert {
36    /// Get the next sample converted, return `None` until the input samples is
37    /// not enough.
38    ///
39    /// Note that the output can be continued after `None` returned.
40    fn next_sample<I>(&mut self, iter: &mut I) -> Option<f64>
41    where
42        I: Iterator<Item = f64>,
43        Self: Sized;
44
45    /// Process samples and return an iterator, can be called multiple times.
46    fn process<I>(&mut self, iter: I) -> ConvertIter<'_, I, Self>
47    where
48        I: Iterator<Item = f64>,
49        Self: Sized,
50    {
51        ConvertIter::new(iter, self)
52    }
53}
54
55#[derive(Debug)]
56pub enum Error {
57    UnsupportedRatio,
58    InvalidParam,
59    NotEnoughParam,
60}
61
62pub type Result<T> = std::result::Result<T, Error>;
63
64use num_rational::Rational64;
65
66fn supported_ratio(ratio: Rational64) -> bool {
67    ratio > Rational64::default()
68        && *ratio.numer() <= 1024
69        && ratio.ceil().to_integer() <= 16
70        && ratio.recip().ceil().to_integer() <= 16
71}
72
73#[cfg(test)]
74mod tests {
75    use super::*;
76
77    #[allow(dead_code)]
78    struct DynTest;
79
80    impl DynTest {
81        #[allow(dead_code)]
82        pub fn new(a: i32) -> Box<dyn Convert> {
83            if a == 0 {
84                let manager = linear::Manager::new(2.0).unwrap();
85                Box::new(manager.converter())
86            } else {
87                let manager = sinc::Manager::new(2.0, 48.0, 8, 0.2).unwrap();
88                Box::new(manager.converter())
89            }
90        }
91    }
92
93    #[test]
94    #[ignore = "display only"]
95    fn test1() {
96        let samples = vec![1.0, 2.0, 3.0, 4.0];
97        let manager = linear::Manager::new(2.0).unwrap();
98        let mut cvtr = manager.converter();
99        for s in cvtr.process(samples.into_iter()) {
100            println!("sample = {s}");
101        }
102    }
103
104    #[test]
105    #[ignore = "display only"]
106    fn test2() {
107        let samples = vec![1.0, 2.0, 3.0, 4.0, 5.0];
108        let manager = sinc::Manager::with_raw(2.0, 16, 4, 5.0, 1.0).unwrap();
109        for s in manager
110            .converter()
111            .process(samples.into_iter())
112            .skip(manager.latency())
113        {
114            println!("sample = {s}");
115        }
116    }
117
118    #[test]
119    #[ignore = "display only"]
120    fn test3() {
121        let samples = vec![1.0, 2.0, 3.0, 4.0, 5.0];
122        let manager = sinc::Manager::with_order(2.0, 30.0, 16, 4).unwrap();
123        for s in manager
124            .converter()
125            .process(samples.into_iter())
126            .skip(manager.latency())
127        {
128            println!("sample = {s}");
129        }
130    }
131}