jbonsai 0.4.1

Voice synthesis library for Text-to-Speech applications (Currently HTS Engine rewrite in Rust language).
use super::{
    buffer::*,
    coefficients::{Coefficients, CoefficientsT, GeneralizedCoefficients},
    generalized::Generalized,
};

#[derive(Debug, Clone)]
pub struct MelCepstrum {
    pub(super) buffer: Vec<f64>,
    pub(super) alpha: f64,
}

deref_buffer!(MelCepstrum);

impl MelCepstrum {
    pub fn new(c: &[f64], alpha: f64) -> Self {
        Self {
            buffer: c.to_vec(),
            alpha,
        }
    }

    pub fn postfilter_mcp(&mut self, beta: f64) {
        if beta > 0.0 && self.len() > 2 {
            let mut coefficients = self.mc2b();
            let e1 = coefficients.b2en(self.alpha);

            coefficients[1] -= beta * self.alpha * coefficients[2];
            for k in 2..self.len() {
                coefficients[k] *= 1.0 + beta;
            }

            let e2 = coefficients.b2en(self.alpha);
            coefficients[0] += (e1 / e2).ln() / 2.0;
            *self = coefficients.b2mc(self.alpha);
        }
    }
}

impl CepstrumT for MelCepstrum {
    type Coef = Coefficients;

    fn alpha(&self) -> f64 {
        self.alpha
    }

    fn to_coef(&self) -> Self::Coef {
        Self::Coef::new(self)
    }

    fn clone_with_size(&self, size: usize) -> Self {
        Self {
            buffer: vec![0.0; size],
            alpha: self.alpha,
        }
    }
}

#[derive(Debug, Clone)]
pub struct MelGeneralizedCepstrum {
    pub(super) buffer: Vec<f64>,
    pub(super) alpha: f64,
    pub(super) gamma: f64,
}

deref_buffer!(MelGeneralizedCepstrum);

impl MelGeneralizedCepstrum {
    fn gc2gc(&self, m2: usize, gamma: f64) -> Self {
        let mut cepstrum = Self {
            buffer: vec![0.0; m2 + 1],
            alpha: self.alpha,
            gamma,
        };
        cepstrum[0] = self[0];

        for i in 1..=m2 {
            let mut ss1 = 0.0;
            let mut ss2 = 0.0;
            for k in 1..self.len().min(i) {
                let mk = i - k;
                let cc = self[k] * cepstrum[mk];
                ss1 += mk as f64 * cc;
                ss2 += k as f64 * cc;
            }
            if i < self.len() {
                cepstrum[i] = self[i] + (cepstrum.gamma * ss2 - self.gamma * ss1) / (i as f64);
            } else {
                cepstrum[i] = (cepstrum.gamma * ss2 - self.gamma * ss1) / (i as f64);
            }
        }

        cepstrum
    }

    pub fn mgc2mgc(&self, m2: usize, alpha: f64, gamma: f64) -> Self {
        if self.alpha == alpha {
            self.gnorm().gc2gc(m2, gamma).ignorm()
        } else {
            let alpha = (alpha - self.alpha) / (1.0 - self.alpha * alpha);
            self.freqt(m2, alpha).gnorm().gc2gc(m2, gamma).ignorm()
        }
    }
}

impl CepstrumT for MelGeneralizedCepstrum {
    type Coef = GeneralizedCoefficients;

    fn alpha(&self) -> f64 {
        self.alpha
    }

    fn to_coef(&self) -> Self::Coef {
        Self::Coef::new(self, self.gamma)
    }

    fn clone_with_size(&self, size: usize) -> Self {
        Self {
            buffer: vec![0.0; size],
            alpha: self.alpha,
            gamma: self.gamma,
        }
    }
}

impl Generalized for MelGeneralizedCepstrum {
    fn gamma(&self) -> f64 {
        self.gamma
    }
}

pub trait CepstrumT: Buffer + Sized {
    type Coef: CoefficientsT;

    fn alpha(&self) -> f64;

    fn to_coef(&self) -> Self::Coef;

    fn mc2b(&self) -> Self::Coef {
        let mut coefficients = self.to_coef();
        if self.alpha() != 0.0 {
            let last = self.len() - 1;
            coefficients[last] = self[last];
            for i in (0..last).rev() {
                coefficients[i] = self[i] - self.alpha() * coefficients[i + 1];
            }
        }
        coefficients
    }

    fn clone_with_size(&self, size: usize) -> Self;

    fn freqt(&self, m2: usize, alpha: f64) -> Self {
        let aa = 1.0 - alpha * alpha;

        let mut cepstrum = self.clone_with_size(m2 + 1);
        let mut f = vec![0.0; cepstrum.len()];

        for i in 0..self.len() {
            f[0] = cepstrum[0];
            cepstrum[0] = self[i] + alpha * cepstrum[0];
            if 1 <= m2 {
                f[1] = cepstrum[1];
                cepstrum[1] = aa * f[0] + alpha * cepstrum[1];
            }
            for j in 2..cepstrum.len() {
                f[j] = cepstrum[j];
                cepstrum[j] = f[j - 1] + alpha * (cepstrum[j] - cepstrum[j - 1]);
            }
        }

        cepstrum
    }

    fn c2ir(&self, len: usize) -> Vec<f64> {
        let mut ir = vec![0.0; len];
        ir[0] = self[0].exp();
        for n in 1..len {
            let mut d = 0.0;
            for k in 1..self.len().min(n + 1) {
                d += k as f64 * self[k] * ir[n - k];
            }
            ir[n] = d / n as f64;
        }
        ir
    }
}