mod g2pw;
mod jyutping_list;
mod split;
mod yue;
use {
crate::{error::GSVError, text::get_phone_symbol},
log::{debug, warn},
};
pub use {
g2pw::{G2PW, G2PWOut},
split::split_zh_ph,
};
#[derive(Debug)]
pub enum ZhMode {
Mandarin,
Cantonese,
}
#[derive(Debug, Default)]
pub struct ZhSentence {
pub phone_ids: Vec<i64>,
pub phones: Vec<G2PWOut>,
pub word2ph: Vec<i32>,
pub text: String,
}
impl ZhSentence {
pub fn g2p(&mut self, g2pw: &mut G2PW, mode: ZhMode) {
match mode {
ZhMode::Mandarin => self.g2p_mandarin(g2pw),
ZhMode::Cantonese => self.g2p_cantonese(),
}
}
fn g2p_mandarin(&mut self, g2pw: &mut G2PW) {
let pinyin = g2pw.g2p(&self.text);
if pinyin.len() != self.text.chars().count() && !self.text.is_empty() {
warn!(
"Pinyin length mismatch: {} (pinyin) vs {} (text chars) for text '{}'",
pinyin.len(),
self.text.chars().count(),
self.text
);
}
self.phones = pinyin;
debug!("phones: {:?}", self.phones);
self.build_phone_id_and_word2ph();
}
fn g2p_cantonese(&mut self) {
let (pinyin, word2ph) = yue::g2p(&self.text);
debug!("pinyin: {:?}", pinyin);
self.phones = pinyin.into_iter().map(G2PWOut::Yue).collect();
self.build_phone_id_and_word2ph();
self.word2ph = word2ph; }
fn build_phone_id_and_word2ph(&mut self) {
self.phone_ids.clear();
self.word2ph.clear();
for p in &self.phones {
match p {
G2PWOut::Pinyin(p) => {
let (initial, final_) = split_zh_ph(p);
self.phone_ids.push(get_phone_symbol(initial));
if !final_.is_empty() {
self.phone_ids.push(get_phone_symbol(final_));
self.word2ph.push(2);
} else {
self.word2ph.push(1);
}
}
G2PWOut::Yue(c) => {
self.phone_ids.push(get_phone_symbol(c));
self.word2ph.push(2);
}
G2PWOut::RawChar(c) => {
self.phone_ids.push(get_phone_symbol(&c.to_string()));
self.word2ph.push(1);
}
}
}
debug!("phone_id {:?}", self.phone_ids);
}
pub fn build_phone(&self) -> Result<Vec<i64>, GSVError> {
Ok(self.phone_ids.clone())
}
}