diff --git a/src/vocoder/coefficients.rs b/src/vocoder/coefficients.rs index 22c130c..2462788 100644 --- a/src/vocoder/coefficients.rs +++ b/src/vocoder/coefficients.rs @@ -57,7 +57,13 @@ impl CoefficientsT for GeneralizedCoefficients { } } -pub trait CoefficientsT: Buffer { +impl Generalized for GeneralizedCoefficients { + fn gamma(&self) -> f64 { + self.gamma + } +} + +pub trait CoefficientsT: Buffer + Sized { type Cep: CepstrumT; fn to_cep(&self, alpha: f64) -> Self::Cep; @@ -76,10 +82,45 @@ pub trait CoefficientsT: Buffer { let ir = self.b2mc(alpha).freqt(576 - 1, -alpha).c2ir(576); ir.iter().map(|x| x * x).sum() } + + fn start(&mut self, target: Self, fperiod: usize) -> CoefficientsSession<'_, Self> { + let increment = self + .iter() + .zip(&target[..self.len()]) + .map(|(current, target)| (target - current) / fperiod as f64) + .collect(); + CoefficientsSession { + current: self, + increment, + target, + } + } } -impl Generalized for GeneralizedCoefficients { - fn gamma(&self) -> f64 { - self.gamma +pub struct CoefficientsSession<'a, T: CoefficientsT> { + current: &'a mut T, + increment: Vec, + target: T, +} + +impl<'a, T: CoefficientsT> CoefficientsSession<'a, T> { + pub fn advance(&mut self) { + for (current, inc) in self.current.iter_mut().zip(&self.increment) { + *current += inc; + } + } +} + +impl Deref for CoefficientsSession<'_, T> { + type Target = T; + + fn deref(&self) -> &Self::Target { + self.current + } +} + +impl Drop for CoefficientsSession<'_, T> { + fn drop(&mut self) { + self.current.copy_from_slice(&self.target); } } diff --git a/src/vocoder/mod.rs b/src/vocoder/mod.rs index 83c00d0..8c80161 100644 --- a/src/vocoder/mod.rs +++ b/src/vocoder/mod.rs @@ -17,6 +17,7 @@ mod stage; use self::{ cepstrum::{CepstrumT, MelCepstrum}, + coefficients::CoefficientsT, excitation::Excitation, generalized::Generalized, lsp::LineSpectralPairs, @@ -116,28 +117,21 @@ impl Vocoder { let mut cepstrum = MelCepstrum::new(spectrum, self.alpha); cepstrum.postfilter_mcp(self.beta); let cc = cepstrum.mc2b(); - let cinc: Vec<_> = cc - .iter() - .zip(coefficients.iter()) - .map(|(cc, c)| (cc - c) / self.fperiod as f64) - .collect(); + let mut coefficients = coefficients.start(cc, self.fperiod); self.excitation.start(p, self.fperiod); - (0..self.fperiod).for_each(|i| { + for r in &mut rawdata[..self.fperiod] { let mut x = self.excitation.get(lpf); if x != 0.0 { x *= coefficients[0].exp(); } - filter.df(&mut x, self.alpha, coefficients); - for i in 0..coefficients.len() { - coefficients[i] += cinc[i]; - } - rawdata[i] = x * self.volume; - }); + filter.df(&mut x, self.alpha, &coefficients); + coefficients.advance(); + *r = x * self.volume; + } self.excitation.end(p); - *coefficients = cc; } Stage::NonZero { stage, @@ -153,26 +147,19 @@ impl Vocoder { for i in 1..cc.len() { cc[i] *= gamma; } - let cinc: Vec<_> = cc - .iter() - .zip(coefficients.iter()) - .map(|(cc, c)| (cc - c) / self.fperiod as f64) - .collect(); + let mut coefficients = coefficients.start(cc, self.fperiod); self.excitation.start(p, self.fperiod); - (0..self.fperiod).for_each(|i| { + for r in &mut rawdata[..self.fperiod] { let mut x = self.excitation.get(lpf); x *= coefficients[0]; - filter.df(&mut x, self.alpha, coefficients); - for i in 0..coefficients.len() { - coefficients[i] += cinc[i]; - } - rawdata[i] = x * self.volume; - }); + filter.df(&mut x, self.alpha, &coefficients); + coefficients.advance(); + *r = x * self.volume; + } self.excitation.end(p); - *coefficients = cc; } } }