Skip to main content

piper_plus/phonemize/
mod.rs

1//! Phonemizer trait, language registry, and language-specific implementations.
2//!
3//! Phase 3: 7 languages (ja, en, zh, ko, es, fr, pt) + multilingual support.
4//! JSONL 入力 (Phase 1) に加え、テキスト直接入力をサポート。
5
6use std::collections::HashMap;
7
8use crate::config::PhonemeIdMap;
9use crate::error::PiperError;
10
11// Re-export from piper-g2p for backward compatibility
12pub use piper_plus_g2p::G2pError;
13pub use piper_plus_g2p::PhonemeIdMap as G2pPhonemeIdMap;
14
15pub mod adapter;
16pub mod chinese;
17pub use piper_plus_g2p::custom_dict;
18pub mod english;
19pub mod french;
20#[cfg(feature = "japanese")]
21pub mod japanese;
22pub mod korean;
23pub use piper_plus_g2p::multilingual;
24pub mod portuguese;
25pub mod spanish;
26pub use piper_plus_g2p::token_map;
27
28/// プロソディ情報 (言語間で共有)
29#[derive(Debug, Clone, Copy)]
30pub struct ProsodyInfo {
31    pub a1: i32,
32    pub a2: i32,
33    pub a3: i32,
34}
35
36/// プロソディ特徴量 (ONNX 入力用)
37pub type ProsodyFeature = [i32; 3];
38
39/// 言語固有の音素化トレイト
40pub trait Phonemizer: Send + Sync {
41    /// テキストを音素トークン列 + プロソディ情報に変換
42    fn phonemize_with_prosody(
43        &self,
44        text: &str,
45    ) -> Result<(Vec<String>, Vec<Option<ProsodyInfo>>), PiperError>;
46
47    /// 言語固有の phoneme_id_map を返す (None なら config.json のものを使用)
48    fn get_phoneme_id_map(&self) -> Option<&PhonemeIdMap>;
49
50    /// BOS/EOS/パディング挿入
51    fn post_process_ids(
52        &self,
53        ids: Vec<i64>,
54        prosody: Vec<Option<ProsodyFeature>>,
55        id_map: &PhonemeIdMap,
56    ) -> (Vec<i64>, Vec<Option<ProsodyFeature>>);
57
58    /// 言語コード ("ja", "en", "zh" 等)
59    fn language_code(&self) -> &str;
60
61    /// テキストの主要言語を検出する。
62    ///
63    /// 多言語対応の phonemizer は最初の言語セグメントの言語コードを返す。
64    /// デフォルト実装は `language_code()` を返す (単言語 phonemizer 用)。
65    fn detect_primary_language(&self, _text: &str) -> &str {
66        self.language_code()
67    }
68}
69
70/// 言語レジストリ
71pub struct PhonemizerRegistry {
72    registry: HashMap<String, Box<dyn Phonemizer>>,
73}
74
75impl PhonemizerRegistry {
76    pub fn new() -> Self {
77        Self {
78            registry: HashMap::new(),
79        }
80    }
81
82    pub fn register(&mut self, lang_code: &str, phonemizer: Box<dyn Phonemizer>) {
83        self.registry.insert(lang_code.to_string(), phonemizer);
84    }
85
86    pub fn get(&self, lang_code: &str) -> Option<&dyn Phonemizer> {
87        self.registry.get(lang_code).map(|p| p.as_ref())
88    }
89
90    pub fn available_languages(&self) -> Vec<&str> {
91        self.registry.keys().map(|s| s.as_str()).collect()
92    }
93}
94
95impl Default for PhonemizerRegistry {
96    fn default() -> Self {
97        Self::new()
98    }
99}