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