jbonsai 0.4.1

Voice synthesis library for Text-to-Speech applications (Currently HTS Engine rewrite in Rust language).
use serde::{Deserialize, Serialize};

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Windows {
    windows: Vec<Window>,
}

impl Windows {
    pub fn new(windows: Vec<Window>) -> Self {
        Self { windows }
    }

    pub fn iter(&self) -> impl '_ + Iterator<Item = &Window> {
        self.windows.iter()
    }
    pub fn size(&self) -> usize {
        self.windows.len()
    }
    pub fn max_width(&self) -> usize {
        self.windows.iter().map(Window::width).max().unwrap_or(0) / 2
    }
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Window {
    coefficients: Vec<f64>,
}

impl Window {
    pub fn new(coefficients: Vec<f64>) -> Self {
        Self { coefficients }
    }

    pub fn iter_rev(&self, start: usize) -> impl '_ + Iterator<Item = (WindowIndex, f64)> {
        let width = self.width();
        self.coefficients[start..]
            .iter()
            .enumerate()
            .rev()
            .zip(std::iter::repeat((start, width)))
            .map(|((idx, coef), (start, width))| (WindowIndex::new(start + idx, width), *coef))
    }

    #[inline]
    pub fn width(&self) -> usize {
        self.coefficients.len()
    }
    #[inline]
    pub fn left_width(&self) -> usize {
        self.width() / 2
    }
    #[inline]
    pub fn right_width(&self) -> usize {
        self.width() - self.left_width() - 1
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct WindowIndex {
    index: usize,
    width: usize,
}

impl WindowIndex {
    pub fn new(index: usize, width: usize) -> Self {
        Self { index, width }
    }

    #[inline]
    pub fn position(&self) -> isize {
        self.index as isize - (self.width / 2) as isize
    }
    #[inline]
    pub fn index(&self) -> usize {
        self.index
    }
}

#[cfg(test)]
mod tests {
    use super::Window;

    #[test]
    fn width_1() {
        let window = Window::new(vec![0.0]);
        assert_eq!(window.width(), 1);
        assert_eq!(window.left_width(), 0);
        assert_eq!(window.right_width(), 0);
    }

    #[test]
    fn width_3() {
        let window = Window::new(vec![-1.0, 0.0, 1.0]);
        assert_eq!(window.width(), 3);
        assert_eq!(window.left_width(), 1);
        assert_eq!(window.right_width(), 1);
    }

    #[test]
    fn iterator() {
        let window = Window::new(vec![-1.0, 0.0, 1.0]);
        let iterated = window.iter_rev(0).collect::<Vec<_>>();

        assert_eq!(iterated[2].1, -1.0);
        assert_eq!(iterated[1].1, 0.0);
        assert_eq!(iterated[0].1, 1.0);

        assert_eq!(iterated[2].0.index(), 0);
        assert_eq!(iterated[1].0.index(), 1);
        assert_eq!(iterated[0].0.index(), 2);

        assert_eq!(iterated[2].0.position(), -1);
        assert_eq!(iterated[1].0.position(), 0);
        assert_eq!(iterated[0].0.position(), 1);
    }
}