use super::{TtsClip, TtsEngine, TTS_SAMPLE_RATE};
use crate::error::Result;
const FREQ_HZ: f32 = 220.0;
const MS_PER_CHAR: f32 = 55.0;
const MIN_MS: f32 = 250.0;
const MAX_MS: f32 = 2_500.0;
const EDGE_MS: f32 = 5.0;
const PEAK: f32 = 0.3;
#[derive(Debug, Default, Clone, Copy)]
pub struct MockTts;
impl MockTts {
pub fn new() -> Self {
Self
}
}
impl TtsEngine for MockTts {
fn synthesize(&mut self, text: &str) -> Result<TtsClip> {
let chars = text.chars().count();
let ms = (chars as f32 * MS_PER_CHAR).clamp(MIN_MS, MAX_MS);
let n = (TTS_SAMPLE_RATE as f32 * ms / 1000.0).round() as usize;
let edge = ((TTS_SAMPLE_RATE as f32 * EDGE_MS / 1000.0) as usize).min(n / 2);
let mut samples = Vec::with_capacity(n);
for i in 0..n {
let phase = 2.0 * std::f32::consts::PI * FREQ_HZ * i as f32 / TTS_SAMPLE_RATE as f32;
let gain = if edge > 0 && i < edge {
0.5 * (1.0 - (std::f32::consts::PI * i as f32 / edge as f32).cos())
} else if edge > 0 && i >= n - edge {
let k = n - 1 - i;
0.5 * (1.0 - (std::f32::consts::PI * k as f32 / edge as f32).cos())
} else {
1.0
};
samples.push(PEAK * gain * phase.sin());
}
Ok(TtsClip {
samples,
sample_rate: TTS_SAMPLE_RATE,
})
}
}