diff --git a/crates/voicevox_core/src/__internal/doctest_fixtures.rs b/crates/voicevox_core/src/__internal/doctest_fixtures.rs index 9f4f91d35..b1122f874 100644 --- a/crates/voicevox_core/src/__internal/doctest_fixtures.rs +++ b/crates/voicevox_core/src/__internal/doctest_fixtures.rs @@ -2,7 +2,7 @@ use std::{ffi::OsString, path::Path}; use camino::Utf8Path; -use crate::{AccelerationMode, InitializeOptions}; +use crate::AccelerationMode; pub use crate::synthesizer::nonblocking::IntoBlocking; @@ -13,7 +13,7 @@ pub async fn synthesizer_with_sample_voice_model( >, open_jtalk_dic_dir: impl AsRef, ) -> anyhow::Result> { - let syntesizer = crate::nonblocking::Synthesizer::new( + let syntesizer = crate::nonblocking::Synthesizer::builder( #[cfg(feature = "load-onnxruntime")] crate::nonblocking::Onnxruntime::load_once() .filename(onnxruntime_dylib_path) @@ -21,12 +21,10 @@ pub async fn synthesizer_with_sample_voice_model( .await?, #[cfg(feature = "link-onnxruntime")] crate::nonblocking::Onnxruntime::init_once().await?, - crate::nonblocking::OpenJtalk::new(open_jtalk_dic_dir).await?, - &InitializeOptions { - acceleration_mode: AccelerationMode::Cpu, - ..Default::default() - }, - )?; + ) + .open_jtalk(crate::nonblocking::OpenJtalk::new(open_jtalk_dic_dir).await?) + .acceleration_mode(AccelerationMode::Cpu) + .build()?; let model = &crate::nonblocking::VoiceModelFile::open(voice_model_path).await?; syntesizer.load_voice_model(model).await?; diff --git a/crates/voicevox_core/src/__internal/interop.rs b/crates/voicevox_core/src/__internal/interop.rs index e4848de6a..fce2ad0ed 100644 --- a/crates/voicevox_core/src/__internal/interop.rs +++ b/crates/voicevox_core/src/__internal/interop.rs @@ -2,5 +2,8 @@ pub mod raii; pub use crate::{ metas::merge as merge_metas, - synthesizer::{blocking::PerformInference, MARGIN}, + synthesizer::{ + blocking::PerformInference, DEFAULT_CPU_NUM_THREADS, DEFAULT_ENABLE_INTERROGATIVE_UPSPEAK, + MARGIN, + }, }; diff --git a/crates/voicevox_core/src/blocking.rs b/crates/voicevox_core/src/blocking.rs index d45dcfe49..5e37d1792 100644 --- a/crates/voicevox_core/src/blocking.rs +++ b/crates/voicevox_core/src/blocking.rs @@ -11,3 +11,10 @@ pub mod onnxruntime { #[cfg_attr(docsrs, doc(cfg(feature = "load-onnxruntime")))] pub use crate::infer::runtimes::onnxruntime::blocking::LoadOnce; } + +pub mod synthesizer { + pub use crate::synthesizer::blocking::{Builder, Synthesis, Tts, TtsFromKana}; + + // TODO: 後で封印する + pub use crate::synthesizer::blocking::PrecomputeRender; +} diff --git a/crates/voicevox_core/src/lib.rs b/crates/voicevox_core/src/lib.rs index 629c15963..6aa121cb5 100644 --- a/crates/voicevox_core/src/lib.rs +++ b/crates/voicevox_core/src/lib.rs @@ -90,7 +90,7 @@ pub use self::{ VoiceModelMeta, }, result::Result, - synthesizer::{AccelerationMode, InitializeOptions, SynthesisOptions, TtsOptions}, + synthesizer::AccelerationMode, user_dict::{UserDictWord, UserDictWordType}, version::VERSION, voice_model::{RawVoiceModelId, VoiceModelId}, diff --git a/crates/voicevox_core/src/nonblocking.rs b/crates/voicevox_core/src/nonblocking.rs index d65a3b7c0..f65aebcb1 100644 --- a/crates/voicevox_core/src/nonblocking.rs +++ b/crates/voicevox_core/src/nonblocking.rs @@ -15,7 +15,7 @@ //! [blocking]: https://docs.rs/crate/blocking //! [pollster]: https://docs.rs/crate/pollster //! [VOICEVOX/voicevox_core#902]: https://github.com/VOICEVOX/voicevox_core/issues/902 -//! [`cpu_num_threads`]: crate::InitializeOptions::cpu_num_threads +//! [`cpu_num_threads`]: crate::nonblocking::synthesizer::Builder::cpu_num_threads pub use crate::{ engine::open_jtalk::nonblocking::OpenJtalk, @@ -28,3 +28,7 @@ pub mod onnxruntime { #[cfg_attr(docsrs, doc(cfg(feature = "load-onnxruntime")))] pub use crate::infer::runtimes::onnxruntime::nonblocking::LoadOnce; } + +pub mod synthesizer { + pub use crate::synthesizer::nonblocking::{Builder, Synthesis, Tts, TtsFromKana}; +} diff --git a/crates/voicevox_core/src/synthesizer.rs b/crates/voicevox_core/src/synthesizer.rs index c49763252..89a959ae2 100644 --- a/crates/voicevox_core/src/synthesizer.rs +++ b/crates/voicevox_core/src/synthesizer.rs @@ -32,15 +32,22 @@ use crate::{ VoiceModelMeta, }; -/// [`blocking::Synthesizer::synthesis`]および[`nonblocking::Synthesizer::synthesis`]のオプション。 -/// -/// [`blocking::Synthesizer::synthesis`]: blocking::Synthesizer::synthesis -/// [`nonblocking::Synthesizer::synthesis`]: nonblocking::Synthesizer::synthesis -#[derive(Clone)] -pub struct SynthesisOptions { - pub enable_interrogative_upspeak: bool, +pub const DEFAULT_CPU_NUM_THREADS: u16 = 0; +pub const DEFAULT_ENABLE_INTERROGATIVE_UPSPEAK: bool = true; + +struct SynthesisOptions { + enable_interrogative_upspeak: bool, } +impl Default for SynthesisOptions { + fn default() -> Self { + Self { + enable_interrogative_upspeak: DEFAULT_ENABLE_INTERROGATIVE_UPSPEAK, + } + } +} + +// FIXME: this is dead code impl AsRef for SynthesisOptions { fn as_ref(&self) -> &SynthesisOptions { self @@ -55,15 +62,11 @@ impl From<&TtsOptions> for SynthesisOptions { } } -/// [`blocking::Synthesizer::tts`]および[`nonblocking::Synthesizer::tts`]のオプション。 -/// -/// [`blocking::Synthesizer::tts`]: blocking::Synthesizer::tts -/// [`nonblocking::Synthesizer::tts`]: nonblocking::Synthesizer::tts -#[derive(Clone)] -pub struct TtsOptions { - pub enable_interrogative_upspeak: bool, +struct TtsOptions { + enable_interrogative_upspeak: bool, } +// FIXME: this is dead code impl AsRef for TtsOptions { fn as_ref(&self) -> &Self { self @@ -73,7 +76,7 @@ impl AsRef for TtsOptions { impl Default for TtsOptions { fn default() -> Self { Self { - enable_interrogative_upspeak: true, + enable_interrogative_upspeak: DEFAULT_ENABLE_INTERROGATIVE_UPSPEAK, } } } @@ -90,24 +93,18 @@ pub enum AccelerationMode { Gpu, } -/// [`blocking::Synthesizer::new`]および[`nonblocking::Synthesizer::new`]のオプション。 -/// -/// [`blocking::Synthesizer::new`]: blocking::Synthesizer::new -/// [`nonblocking::Synthesizer::new`]: nonblocking::Synthesizer::new -#[derive(Default)] -pub struct InitializeOptions { - pub acceleration_mode: AccelerationMode, +struct InitializeOptions { + acceleration_mode: AccelerationMode, + cpu_num_threads: u16, +} - /// CPU利用数を指定。0を指定すると環境に合わせたCPUが利用される。 - /// - /// # Performance - /// - /// 未調査ではあるが、[非同期版API]においては物理コアの数+1とするのが適切な可能性がある - /// ([VOICEVOX/voicevox_core#902])。 - /// - /// [非同期版API]: crate::nonblocking - /// [VOICEVOX/voicevox_core#902]: https://github.com/VOICEVOX/voicevox_core/issues/902 - pub cpu_num_threads: u16, +impl Default for InitializeOptions { + fn default() -> Self { + Self { + acceleration_mode: Default::default(), + cpu_num_threads: DEFAULT_CPU_NUM_THREADS, + } + } } trait AsyncExt: infer::AsyncExt { @@ -1304,21 +1301,22 @@ pub(crate) mod blocking { FullcontextExtractor, StyleId, VoiceModelId, VoiceModelMeta, }; - use super::{InitializeOptions, Inner, SynthesisOptions, TtsOptions}; + use super::{AccelerationMode, InitializeOptions, Inner, SynthesisOptions, TtsOptions}; pub use super::AudioFeature; /// 音声シンセサイザ。 pub struct Synthesizer(pub(super) Inner); - impl self::Synthesizer { - /// `Synthesizer`をコンストラクトする。 + impl self::Synthesizer<()> { + /// `Synthesizer`のビルダーをコンストラクトする。 /// /// # Example /// #[cfg_attr(feature = "load-onnxruntime", doc = "```")] #[cfg_attr(not(feature = "load-onnxruntime"), doc = "```compile_fail")] /// # fn main() -> anyhow::Result<()> { + /// # // FIXME: この`ONNXRUNTIME_DYLIB_PATH`はunused import /// # use test_util::{ONNXRUNTIME_DYLIB_PATH, OPEN_JTALK_DIC_DIR}; /// # /// # const ACCELERATION_MODE: AccelerationMode = AccelerationMode::Cpu; @@ -1327,7 +1325,7 @@ pub(crate) mod blocking { /// /// use voicevox_core::{ /// blocking::{Onnxruntime, OpenJtalk, Synthesizer}, - /// AccelerationMode, InitializeOptions, + /// AccelerationMode, /// }; /// /// # if cfg!(windows) { @@ -1336,26 +1334,25 @@ pub(crate) mod blocking { /// # .filename(test_util::ONNXRUNTIME_DYLIB_PATH) /// # .exec()?; /// # } - /// let mut syntesizer = Synthesizer::new( - /// Onnxruntime::load_once().exec()?, - /// Arc::new(OpenJtalk::new(OPEN_JTALK_DIC_DIR).unwrap()), - /// &InitializeOptions { - /// acceleration_mode: ACCELERATION_MODE, - /// ..Default::default() - /// }, - /// )?; + /// // FIXME: `Synthesizer`には`&mut self`なメソッドはもう無いはず + /// let mut syntesizer = Synthesizer::builder(Onnxruntime::load_once().exec()?) + /// .open_jtalk(Arc::new(OpenJtalk::new(OPEN_JTALK_DIC_DIR).unwrap())) // FIXME: `Arc`は要らないはず + /// .acceleration_mode(ACCELERATION_MODE) + /// .build()?; /// # /// # Ok(()) /// # } /// ``` - pub fn new( - onnxruntime: &'static crate::blocking::Onnxruntime, - open_jtalk: O, - options: &InitializeOptions, - ) -> crate::Result { - Inner::new(onnxruntime, open_jtalk, options).map(Self) + pub fn builder(onnxruntime: &'static crate::blocking::Onnxruntime) -> Builder<()> { + Builder { + onnxruntime, + open_jtalk: (), + options: Default::default(), + } } + } + impl self::Synthesizer { pub fn onnxruntime(&self) -> &'static crate::blocking::Onnxruntime { self.0.onnxruntime() } @@ -1394,15 +1391,17 @@ pub(crate) mod blocking { } /// AudioQueryから音声合成用の中間表現を生成する。 - pub fn precompute_render( - &self, - audio_query: &AudioQuery, + pub fn precompute_render<'a>( + &'a self, + audio_query: &'a AudioQuery, style_id: StyleId, - options: &SynthesisOptions, - ) -> crate::Result { - self.0 - .precompute_render(audio_query, style_id, options) - .block_on() + ) -> PrecomputeRender<'a, O> { + PrecomputeRender { + synthesizer: &self.0, + audio_query, + style_id, + options: Default::default(), + } } /// 中間表現から16bit PCMで音声波形を生成する。 @@ -1411,13 +1410,17 @@ pub(crate) mod blocking { } /// AudioQueryから直接WAVフォーマットで音声波形を生成する。 - pub fn synthesis( - &self, - audio_query: &AudioQuery, + pub fn synthesis<'a>( + &'a self, + audio_query: &'a AudioQuery, style_id: StyleId, - options: &SynthesisOptions, - ) -> crate::Result> { - self.0.synthesis(audio_query, style_id, options).block_on() + ) -> Synthesis<'a, O> { + Synthesis { + synthesizer: &self.0, + audio_query, + style_id, + options: Default::default(), + } } /// AquesTalk風記法からAccentPhrase (アクセント句)の配列を生成する。 @@ -1527,13 +1530,13 @@ pub(crate) mod blocking { } /// AquesTalk風記法から音声合成を行う。 - pub fn tts_from_kana( - &self, - kana: &str, - style_id: StyleId, - options: &TtsOptions, - ) -> crate::Result> { - self.0.tts_from_kana(kana, style_id, options).block_on() + pub fn tts_from_kana<'a>(&'a self, kana: &'a str, style_id: StyleId) -> TtsFromKana<'a, O> { + TtsFromKana { + synthesizer: &self.0, + kana, + style_id, + options: TtsOptions::default(), + } } } @@ -1607,13 +1610,13 @@ pub(crate) mod blocking { } /// 日本語のテキストから音声合成を行う。 - pub fn tts( - &self, - text: &str, - style_id: StyleId, - options: &TtsOptions, - ) -> crate::Result> { - self.0.tts(text, style_id, options).block_on() + pub fn tts<'a>(&'a self, text: &'a str, style_id: StyleId) -> Tts<'a, O> { + Tts { + synthesizer: &self.0, + text, + style_id, + options: TtsOptions::default(), + } } } @@ -1742,6 +1745,125 @@ pub(crate) mod blocking { .block_on() } } + + pub struct Builder { + onnxruntime: &'static crate::blocking::Onnxruntime, + open_jtalk: O, + options: InitializeOptions, + } + + impl Builder { + pub fn open_jtalk(self, open_jtalk: O2) -> Builder { + Builder { + open_jtalk, + onnxruntime: self.onnxruntime, + options: self.options, + } + } + + pub fn acceleration_mode(mut self, acceleration_mode: AccelerationMode) -> Self { + self.options.acceleration_mode = acceleration_mode; + self + } + + /// CPU利用数を指定。0を指定すると環境に合わせたCPUが利用される。 + pub fn cpu_num_threads(mut self, cpu_num_threads: u16) -> Self { + self.options.cpu_num_threads = cpu_num_threads; + self + } + + /// [`Synthesizer`]をコンストラクトする。 + pub fn build(self) -> crate::Result> { + Inner::new(self.onnxruntime, self.open_jtalk, &self.options).map(Synthesizer) + } + } + + // TODO: この`O`は削れるはず + pub struct PrecomputeRender<'a, O> { + synthesizer: &'a Inner, + audio_query: &'a AudioQuery, + style_id: StyleId, + options: SynthesisOptions, + } + + impl PrecomputeRender<'_, O> { + pub fn enable_interrogative_upspeak(mut self, enable_interrogative_upspeak: bool) -> Self { + self.options.enable_interrogative_upspeak = enable_interrogative_upspeak; + self + } + + /// 実行する。 + pub fn exec(self) -> crate::Result { + self.synthesizer + .precompute_render(self.audio_query, self.style_id, &self.options) + .block_on() + } + } + + // TODO: この`O`は削れるはず + pub struct Synthesis<'a, O> { + synthesizer: &'a Inner, + audio_query: &'a AudioQuery, + style_id: StyleId, + options: SynthesisOptions, + } + + impl Synthesis<'_, O> { + pub fn enable_interrogative_upspeak(mut self, enable_interrogative_upspeak: bool) -> Self { + self.options.enable_interrogative_upspeak = enable_interrogative_upspeak; + self + } + + /// 実行する。 + pub fn exec(self) -> crate::Result> { + self.synthesizer + .synthesis(self.audio_query, self.style_id, &self.options) + .block_on() + } + } + + // TODO: この`O`は削れるはず + pub struct TtsFromKana<'a, O> { + synthesizer: &'a Inner, + kana: &'a str, + style_id: StyleId, + options: TtsOptions, + } + + impl TtsFromKana<'_, O> { + pub fn enable_interrogative_upspeak(mut self, enable_interrogative_upspeak: bool) -> Self { + self.options.enable_interrogative_upspeak = enable_interrogative_upspeak; + self + } + + /// 実行する。 + pub fn exec(self) -> crate::Result> { + self.synthesizer + .tts_from_kana(self.kana, self.style_id, &self.options) + .block_on() + } + } + + pub struct Tts<'a, O> { + synthesizer: &'a Inner, + text: &'a str, + style_id: StyleId, + options: TtsOptions, + } + + impl Tts<'_, O> { + pub fn enable_interrogative_upspeak(mut self, enable_interrogative_upspeak: bool) -> Self { + self.options.enable_interrogative_upspeak = enable_interrogative_upspeak; + self + } + + /// 実行する。 + pub fn exec(self) -> crate::Result> { + self.synthesizer + .tts(self.text, self.style_id, &self.options) + .block_on() + } + } } pub(crate) mod nonblocking { @@ -1749,10 +1871,10 @@ pub(crate) mod nonblocking { use crate::{ asyncs::BlockingThreadPool, AccentPhrase, AudioQuery, FullcontextExtractor, Result, - StyleId, SynthesisOptions, VoiceModelId, VoiceModelMeta, + StyleId, VoiceModelId, VoiceModelMeta, }; - use super::{InitializeOptions, Inner, TtsOptions}; + use super::{AccelerationMode, InitializeOptions, Inner, SynthesisOptions, TtsOptions}; /// 音声シンセサイザ。 /// @@ -1764,8 +1886,8 @@ pub(crate) mod nonblocking { /// [`nonblocking`モジュールのドキュメント]: crate::nonblocking pub struct Synthesizer(pub(super) Inner); - impl self::Synthesizer { - /// `Synthesizer`をコンストラクトする。 + impl self::Synthesizer<()> { + /// `Synthesizer`のビルダーをコンストラクトする。 /// /// # Example /// @@ -1773,6 +1895,7 @@ pub(crate) mod nonblocking { #[cfg_attr(not(feature = "load-onnxruntime"), doc = "```compile_fail")] /// # #[pollster::main] /// # async fn main() -> anyhow::Result<()> { + /// # // FIXME: この`ONNXRUNTIME_DYLIB_PATH`はunused import /// # use test_util::{ONNXRUNTIME_DYLIB_PATH, OPEN_JTALK_DIC_DIR}; /// # /// # const ACCELERATION_MODE: AccelerationMode = AccelerationMode::Cpu; @@ -1781,7 +1904,7 @@ pub(crate) mod nonblocking { /// /// use voicevox_core::{ /// nonblocking::{Onnxruntime, OpenJtalk, Synthesizer}, - /// AccelerationMode, InitializeOptions, + /// AccelerationMode, /// }; /// /// # if cfg!(windows) { @@ -1790,28 +1913,25 @@ pub(crate) mod nonblocking { /// # .filename(test_util::ONNXRUNTIME_DYLIB_PATH) /// # .exec()?; /// # } - /// let mut syntesizer = Synthesizer::new( - /// Onnxruntime::load_once().exec().await?, - /// Arc::new(OpenJtalk::new(OPEN_JTALK_DIC_DIR).await.unwrap()), - /// &InitializeOptions { - /// acceleration_mode: ACCELERATION_MODE, - /// ..Default::default() - /// }, - /// )?; + /// // FIXME: `Synthesizer`には`&mut self`なメソッドはもう無いはず + /// let mut syntesizer = Synthesizer::builder(Onnxruntime::load_once().exec().await?) + /// .open_jtalk(Arc::new(OpenJtalk::new(OPEN_JTALK_DIC_DIR).await.unwrap())) // FIXME: `Arc`は要らないはず + /// .acceleration_mode(ACCELERATION_MODE) + /// .build()?; /// # /// # Ok(()) /// # } /// ``` - pub fn new( - onnxruntime: &'static crate::nonblocking::Onnxruntime, - open_jtalk: O, - options: &InitializeOptions, - ) -> Result { - Inner::new(&onnxruntime.0, open_jtalk, options) - .map(Into::into) - .map(Self) + pub fn builder(onnxruntime: &'static crate::nonblocking::Onnxruntime) -> Builder<()> { + Builder { + onnxruntime, + open_jtalk: (), + options: Default::default(), + } } + } + impl self::Synthesizer { pub fn onnxruntime(&self) -> &'static crate::nonblocking::Onnxruntime { crate::nonblocking::Onnxruntime::from_blocking(self.0.onnxruntime()) } @@ -1850,13 +1970,17 @@ pub(crate) mod nonblocking { } /// AudioQueryから音声合成を行う。 - pub async fn synthesis( - &self, - audio_query: &AudioQuery, + pub fn synthesis<'a>( + &'a self, + audio_query: &'a AudioQuery, style_id: StyleId, - options: &SynthesisOptions, - ) -> Result> { - self.0.synthesis(audio_query, style_id, options).await + ) -> Synthesis<'a, O> { + Synthesis { + synthesizer: &self.0, + audio_query, + style_id, + options: Default::default(), + } } /// AquesTalk風記法からAccentPhrase (アクセント句)の配列を生成する。 @@ -1955,13 +2079,13 @@ pub(crate) mod nonblocking { } /// AquesTalk風記法から音声合成を行う。 - pub async fn tts_from_kana( - &self, - kana: &str, - style_id: StyleId, - options: &TtsOptions, - ) -> Result> { - self.0.tts_from_kana(kana, style_id, options).await + pub fn tts_from_kana<'a>(&'a self, kana: &'a str, style_id: StyleId) -> TtsFromKana<'a, O> { + TtsFromKana { + synthesizer: &self.0, + kana, + style_id, + options: Default::default(), + } } } @@ -2033,13 +2157,13 @@ pub(crate) mod nonblocking { } /// 日本語のテキストから音声合成を行う。 - pub async fn tts( - &self, - text: &str, - style_id: StyleId, - options: &TtsOptions, - ) -> Result> { - self.0.tts(text, style_id, options).await + pub fn tts<'a>(&'a self, text: &'a str, style_id: StyleId) -> Tts<'a, T> { + Tts { + synthesizer: &self.0, + text, + style_id, + options: Default::default(), + } } } @@ -2049,11 +2173,115 @@ pub(crate) mod nonblocking { super::blocking::Synthesizer(self.0.into()) } } + + pub struct Builder { + onnxruntime: &'static crate::nonblocking::Onnxruntime, + open_jtalk: O, + options: InitializeOptions, + } + + impl Builder { + pub fn open_jtalk(self, open_jtalk: O2) -> Builder { + Builder { + open_jtalk, + onnxruntime: self.onnxruntime, + options: self.options, + } + } + + pub fn acceleration_mode(mut self, acceleration_mode: AccelerationMode) -> Self { + self.options.acceleration_mode = acceleration_mode; + self + } + + /// CPU利用数を指定。0を指定すると環境に合わせたCPUが利用される。 + /// + /// # Performance + /// + /// 未調査ではあるが、物理コアの数+1とするのが適切な可能性がある + /// ([VOICEVOX/voicevox_core#902])。 + /// + /// [VOICEVOX/voicevox_core#902]: https://github.com/VOICEVOX/voicevox_core/issues/902 + pub fn cpu_num_threads(mut self, cpu_num_threads: u16) -> Self { + self.options.cpu_num_threads = cpu_num_threads; + self + } + + /// [`Synthesizer`]をコンストラクトする。 + pub fn build(self) -> crate::Result> { + Inner::new(&self.onnxruntime.0, self.open_jtalk, &self.options).map(Synthesizer) + } + } + + // TODO: この`O`は削れるはず + pub struct Synthesis<'a, O> { + synthesizer: &'a Inner, + audio_query: &'a AudioQuery, + style_id: StyleId, + options: SynthesisOptions, + } + + impl Synthesis<'_, O> { + pub fn enable_interrogative_upspeak(mut self, enable_interrogative_upspeak: bool) -> Self { + self.options.enable_interrogative_upspeak = enable_interrogative_upspeak; + self + } + + /// 実行する。 + pub async fn exec(self) -> crate::Result> { + self.synthesizer + .synthesis(self.audio_query, self.style_id, &self.options) + .await + } + } + + // TODO: この`O`は削れるはず + pub struct TtsFromKana<'a, O> { + synthesizer: &'a Inner, + kana: &'a str, + style_id: StyleId, + options: TtsOptions, + } + + impl TtsFromKana<'_, O> { + pub fn enable_interrogative_upspeak(mut self, enable_interrogative_upspeak: bool) -> Self { + self.options.enable_interrogative_upspeak = enable_interrogative_upspeak; + self + } + + /// 実行する。 + pub async fn exec(self) -> crate::Result> { + self.synthesizer + .tts_from_kana(self.kana, self.style_id, &self.options) + .await + } + } + + pub struct Tts<'a, O> { + synthesizer: &'a Inner, + text: &'a str, + style_id: StyleId, + options: TtsOptions, + } + + impl Tts<'_, O> { + pub fn enable_interrogative_upspeak(mut self, enable_interrogative_upspeak: bool) -> Self { + self.options.enable_interrogative_upspeak = enable_interrogative_upspeak; + self + } + + /// 実行する。 + pub async fn exec(self) -> crate::Result> { + self.synthesizer + .tts(self.text, self.style_id, &self.options) + .await + } + } } #[cfg(test)] mod tests { - use super::{AccelerationMode, InitializeOptions}; + use super::AccelerationMode; use crate::{ asyncs::BlockingThreadPool, engine::Mora, macros::tests::assert_debug_fmt_eq, AccentPhrase, Result, StyleId, @@ -2065,16 +2293,13 @@ mod tests { #[case(Ok(()))] #[tokio::test] async fn load_model_works(#[case] expected_result_at_initialized: Result<()>) { - let syntesizer = super::nonblocking::Synthesizer::new( + let syntesizer = super::nonblocking::Synthesizer::builder( crate::nonblocking::Onnxruntime::from_test_util_data() .await .unwrap(), - (), - &InitializeOptions { - acceleration_mode: AccelerationMode::Cpu, - ..Default::default() - }, ) + .acceleration_mode(AccelerationMode::Cpu) + .build() .unwrap(); let result = syntesizer @@ -2091,16 +2316,13 @@ mod tests { #[rstest] #[tokio::test] async fn is_use_gpu_works() { - let syntesizer = super::nonblocking::Synthesizer::new( + let syntesizer = super::nonblocking::Synthesizer::builder( crate::nonblocking::Onnxruntime::from_test_util_data() .await .unwrap(), - (), - &InitializeOptions { - acceleration_mode: AccelerationMode::Cpu, - ..Default::default() - }, ) + .acceleration_mode(AccelerationMode::Cpu) + .build() .unwrap(); assert!(!syntesizer.is_gpu_mode()); } @@ -2110,16 +2332,13 @@ mod tests { #[tokio::test] async fn is_loaded_model_by_style_id_works(#[case] style_id: u32, #[case] expected: bool) { let style_id = StyleId::new(style_id); - let syntesizer = super::nonblocking::Synthesizer::new( + let syntesizer = super::nonblocking::Synthesizer::builder( crate::nonblocking::Onnxruntime::from_test_util_data() .await .unwrap(), - (), - &InitializeOptions { - acceleration_mode: AccelerationMode::Cpu, - ..Default::default() - }, ) + .acceleration_mode(AccelerationMode::Cpu) + .build() .unwrap(); assert!( !syntesizer.is_loaded_model_by_style_id(style_id), @@ -2141,16 +2360,13 @@ mod tests { #[rstest] #[tokio::test] async fn predict_duration_works() { - let syntesizer = super::nonblocking::Synthesizer::new( + let syntesizer = super::nonblocking::Synthesizer::builder( crate::nonblocking::Onnxruntime::from_test_util_data() .await .unwrap(), - (), - &InitializeOptions { - acceleration_mode: AccelerationMode::Cpu, - ..Default::default() - }, ) + .acceleration_mode(AccelerationMode::Cpu) + .build() .unwrap(); syntesizer @@ -2176,16 +2392,13 @@ mod tests { #[rstest] #[tokio::test] async fn predict_intonation_works() { - let syntesizer = super::nonblocking::Synthesizer::new( + let syntesizer = super::nonblocking::Synthesizer::builder( crate::nonblocking::Onnxruntime::from_test_util_data() .await .unwrap(), - (), - &InitializeOptions { - acceleration_mode: AccelerationMode::Cpu, - ..Default::default() - }, ) + .acceleration_mode(AccelerationMode::Cpu) + .build() .unwrap(); syntesizer .load_voice_model(&crate::nonblocking::VoiceModelFile::sample().await.unwrap()) @@ -2221,16 +2434,13 @@ mod tests { #[rstest] #[tokio::test] async fn decode_works() { - let syntesizer = super::nonblocking::Synthesizer::new( + let syntesizer = super::nonblocking::Synthesizer::builder( crate::nonblocking::Onnxruntime::from_test_util_data() .await .unwrap(), - (), - &InitializeOptions { - acceleration_mode: AccelerationMode::Cpu, - ..Default::default() - }, ) + .acceleration_mode(AccelerationMode::Cpu) + .build() .unwrap(); syntesizer .load_voice_model(&crate::nonblocking::VoiceModelFile::sample().await.unwrap()) @@ -2271,16 +2481,13 @@ mod tests { #[rstest] #[tokio::test] async fn predict_sing_f0_works() { - let syntesizer = super::nonblocking::Synthesizer::new( + let syntesizer = super::nonblocking::Synthesizer::builder( crate::nonblocking::Onnxruntime::from_test_util_data() .await .unwrap(), - (), - &InitializeOptions { - acceleration_mode: AccelerationMode::Cpu, - ..Default::default() - }, ) + .acceleration_mode(AccelerationMode::Cpu) + .build() .unwrap(); syntesizer .load_voice_model(&crate::nonblocking::VoiceModelFile::sample().await.unwrap()) @@ -2309,16 +2516,13 @@ mod tests { #[rstest] #[tokio::test] async fn predict_sing_volume_works() { - let syntesizer = super::nonblocking::Synthesizer::new( + let syntesizer = super::nonblocking::Synthesizer::builder( crate::nonblocking::Onnxruntime::from_test_util_data() .await .unwrap(), - (), - &InitializeOptions { - acceleration_mode: AccelerationMode::Cpu, - ..Default::default() - }, ) + .acceleration_mode(AccelerationMode::Cpu) + .build() .unwrap(); syntesizer .load_voice_model(&crate::nonblocking::VoiceModelFile::sample().await.unwrap()) @@ -2349,16 +2553,13 @@ mod tests { #[rstest] #[tokio::test] async fn sf_decode_works() { - let syntesizer = super::nonblocking::Synthesizer::new( + let syntesizer = super::nonblocking::Synthesizer::builder( crate::nonblocking::Onnxruntime::from_test_util_data() .await .unwrap(), - (), - &InitializeOptions { - acceleration_mode: AccelerationMode::Cpu, - ..Default::default() - }, ) + .acceleration_mode(AccelerationMode::Cpu) + .build() .unwrap(); syntesizer .load_voice_model(&crate::nonblocking::VoiceModelFile::sample().await.unwrap()) @@ -2456,18 +2657,18 @@ mod tests { #[case] expected_text_consonant_vowel_data: &TextConsonantVowelData, #[case] expected_kana_text: &str, ) { - let syntesizer = super::nonblocking::Synthesizer::new( + let syntesizer = super::nonblocking::Synthesizer::builder( crate::nonblocking::Onnxruntime::from_test_util_data() .await .unwrap(), + ) + .open_jtalk( crate::nonblocking::OpenJtalk::new(OPEN_JTALK_DIC_DIR) .await .unwrap(), - &InitializeOptions { - acceleration_mode: AccelerationMode::Cpu, - ..Default::default() - }, ) + .acceleration_mode(AccelerationMode::Cpu) + .build() .unwrap(); let model = &crate::nonblocking::VoiceModelFile::sample().await.unwrap(); @@ -2527,18 +2728,18 @@ mod tests { #[case] input: Input, #[case] expected_text_consonant_vowel_data: &TextConsonantVowelData, ) { - let syntesizer = super::nonblocking::Synthesizer::new( + let syntesizer = super::nonblocking::Synthesizer::builder( crate::nonblocking::Onnxruntime::from_test_util_data() .await .unwrap(), + ) + .open_jtalk( crate::nonblocking::OpenJtalk::new(OPEN_JTALK_DIC_DIR) .await .unwrap(), - &InitializeOptions { - acceleration_mode: AccelerationMode::Cpu, - ..Default::default() - }, ) + .acceleration_mode(AccelerationMode::Cpu) + .build() .unwrap(); let model = &crate::nonblocking::VoiceModelFile::sample().await.unwrap(); @@ -2595,18 +2796,18 @@ mod tests { #[rstest] #[tokio::test] async fn create_accent_phrases_works_for_japanese_commas_and_periods() { - let syntesizer = super::nonblocking::Synthesizer::new( + let syntesizer = super::nonblocking::Synthesizer::builder( crate::nonblocking::Onnxruntime::from_test_util_data() .await .unwrap(), + ) + .open_jtalk( crate::nonblocking::OpenJtalk::new(OPEN_JTALK_DIC_DIR) .await .unwrap(), - &InitializeOptions { - acceleration_mode: AccelerationMode::Cpu, - ..Default::default() - }, ) + .acceleration_mode(AccelerationMode::Cpu) + .build() .unwrap(); let model = &crate::nonblocking::VoiceModelFile::sample().await.unwrap(); @@ -2658,18 +2859,18 @@ mod tests { #[rstest] #[tokio::test] async fn mora_length_works() { - let syntesizer = super::nonblocking::Synthesizer::new( + let syntesizer = super::nonblocking::Synthesizer::builder( crate::nonblocking::Onnxruntime::from_test_util_data() .await .unwrap(), + ) + .open_jtalk( crate::nonblocking::OpenJtalk::new(OPEN_JTALK_DIC_DIR) .await .unwrap(), - &InitializeOptions { - acceleration_mode: AccelerationMode::Cpu, - ..Default::default() - }, ) + .acceleration_mode(AccelerationMode::Cpu) + .build() .unwrap(); let model = &crate::nonblocking::VoiceModelFile::sample().await.unwrap(); @@ -2699,18 +2900,18 @@ mod tests { #[rstest] #[tokio::test] async fn mora_pitch_works() { - let syntesizer = super::nonblocking::Synthesizer::new( + let syntesizer = super::nonblocking::Synthesizer::builder( crate::nonblocking::Onnxruntime::from_test_util_data() .await .unwrap(), + ) + .open_jtalk( crate::nonblocking::OpenJtalk::new(OPEN_JTALK_DIC_DIR) .await .unwrap(), - &InitializeOptions { - acceleration_mode: AccelerationMode::Cpu, - ..Default::default() - }, ) + .acceleration_mode(AccelerationMode::Cpu) + .build() .unwrap(); let model = &crate::nonblocking::VoiceModelFile::sample().await.unwrap(); @@ -2740,18 +2941,18 @@ mod tests { #[rstest] #[tokio::test] async fn mora_data_works() { - let syntesizer = super::nonblocking::Synthesizer::new( + let syntesizer = super::nonblocking::Synthesizer::builder( crate::nonblocking::Onnxruntime::from_test_util_data() .await .unwrap(), + ) + .open_jtalk( crate::nonblocking::OpenJtalk::new(OPEN_JTALK_DIC_DIR) .await .unwrap(), - &InitializeOptions { - acceleration_mode: AccelerationMode::Cpu, - ..Default::default() - }, ) + .acceleration_mode(AccelerationMode::Cpu) + .build() .unwrap(); let model = &crate::nonblocking::VoiceModelFile::sample().await.unwrap(); diff --git a/crates/voicevox_core_c_api/src/c_impls.rs b/crates/voicevox_core_c_api/src/c_impls.rs index bc1d89c3c..90f389799 100644 --- a/crates/voicevox_core_c_api/src/c_impls.rs +++ b/crates/voicevox_core_c_api/src/c_impls.rs @@ -11,13 +11,13 @@ use camino::Utf8Path; use duplicate::duplicate_item; use easy_ext::ext; use ref_cast::ref_cast_custom; -use voicevox_core::{InitializeOptions, Result, SpeakerMeta, VoiceModelId}; +use voicevox_core::{Result, SpeakerMeta, VoiceModelId}; use crate::{ helpers::CApiResult, object::{CApiObject, CApiObjectPtrExt as _}, - OpenJtalkRc, VoicevoxOnnxruntime, VoicevoxSynthesizer, VoicevoxUserDict, - VoicevoxVoiceModelFile, + OpenJtalkRc, VoicevoxInitializeOptions, VoicevoxOnnxruntime, VoicevoxSynthesizer, + VoicevoxUserDict, VoicevoxVoiceModelFile, }; // FIXME: 中身(Rust API)を直接操作するかラッパーメソッド越しにするのかが混在していて、一貫性を @@ -80,13 +80,16 @@ impl VoicevoxSynthesizer { pub(crate) fn new( onnxruntime: &'static VoicevoxOnnxruntime, open_jtalk: *const OpenJtalkRc, - options: &InitializeOptions, + VoicevoxInitializeOptions { + acceleration_mode, + cpu_num_threads, + }: VoicevoxInitializeOptions, ) -> Result> { - let body = voicevox_core::blocking::Synthesizer::new( - &onnxruntime.0, - open_jtalk.body().clone(), - options, - )?; + let body = voicevox_core::blocking::Synthesizer::builder(&onnxruntime.0) + .open_jtalk(open_jtalk.body().clone()) + .acceleration_mode(acceleration_mode.into()) + .cpu_num_threads(cpu_num_threads) + .build()?; Ok(::new(body)) } } diff --git a/crates/voicevox_core_c_api/src/compatible_engine.rs b/crates/voicevox_core_c_api/src/compatible_engine.rs index ab191164c..1af020299 100644 --- a/crates/voicevox_core_c_api/src/compatible_engine.rs +++ b/crates/voicevox_core_c_api/src/compatible_engine.rs @@ -117,18 +117,14 @@ fn set_message(message: &str) { pub extern "C" fn initialize(use_gpu: bool, cpu_num_threads: c_int, load_all_models: bool) -> bool { init_logger_once(); let result = (|| { - let synthesizer = voicevox_core::blocking::Synthesizer::new( - *ONNXRUNTIME, - (), - &voicevox_core::InitializeOptions { - acceleration_mode: if use_gpu { - voicevox_core::AccelerationMode::Gpu - } else { - voicevox_core::AccelerationMode::Cpu - }, - cpu_num_threads: cpu_num_threads as u16, - }, - )?; + let synthesizer = voicevox_core::blocking::Synthesizer::builder(*ONNXRUNTIME) + .acceleration_mode(if use_gpu { + voicevox_core::AccelerationMode::Gpu + } else { + voicevox_core::AccelerationMode::Cpu + }) + .cpu_num_threads(cpu_num_threads as u16) + .build()?; if load_all_models { for model in &voice_model_set().all_vvms { diff --git a/crates/voicevox_core_c_api/src/helpers.rs b/crates/voicevox_core_c_api/src/helpers.rs index 26a60d033..0867aa9b0 100644 --- a/crates/voicevox_core_c_api/src/helpers.rs +++ b/crates/voicevox_core_c_api/src/helpers.rs @@ -1,7 +1,7 @@ use easy_ext::ext; use std::{ffi::CStr, fmt::Debug, iter}; use uuid::Uuid; -use voicevox_core::{AudioQuery, UserDictWord, VoiceModelId}; +use voicevox_core::{AccelerationMode, AudioQuery, UserDictWord, VoiceModelId}; use thiserror::Error; use tracing::error; @@ -92,14 +92,6 @@ pub(crate) fn ensure_utf8(s: &CStr) -> CApiResult<&str> { s.to_str().map_err(|_| CApiError::InvalidUtf8Input) } -impl From for voicevox_core::SynthesisOptions { - fn from(options: VoicevoxSynthesisOptions) -> Self { - Self { - enable_interrogative_upspeak: options.enable_interrogative_upspeak, - } - } -} - impl From for VoicevoxAccelerationMode { fn from(mode: voicevox_core::AccelerationMode) -> Self { use voicevox_core::AccelerationMode::*; @@ -124,44 +116,27 @@ impl From for voicevox_core::AccelerationMode { impl Default for VoicevoxInitializeOptions { fn default() -> Self { - let options = voicevox_core::InitializeOptions::default(); Self { - acceleration_mode: options.acceleration_mode.into(), - cpu_num_threads: options.cpu_num_threads, - } - } -} - -impl From for voicevox_core::InitializeOptions { - fn from(value: VoicevoxInitializeOptions) -> Self { - voicevox_core::InitializeOptions { - acceleration_mode: value.acceleration_mode.into(), - cpu_num_threads: value.cpu_num_threads, + acceleration_mode: AccelerationMode::default().into(), + cpu_num_threads: voicevox_core::__internal::interop::DEFAULT_CPU_NUM_THREADS, } } } -impl From for VoicevoxTtsOptions { - fn from(options: voicevox_core::TtsOptions) -> Self { - Self { - enable_interrogative_upspeak: options.enable_interrogative_upspeak, - } - } -} - -impl From for voicevox_core::TtsOptions { - fn from(options: VoicevoxTtsOptions) -> Self { +impl Default for VoicevoxSynthesisOptions { + fn default() -> Self { Self { - enable_interrogative_upspeak: options.enable_interrogative_upspeak, + enable_interrogative_upspeak: + voicevox_core::__internal::interop::DEFAULT_ENABLE_INTERROGATIVE_UPSPEAK, } } } -impl Default for VoicevoxSynthesisOptions { +impl Default for VoicevoxTtsOptions { fn default() -> Self { - let options = voicevox_core::TtsOptions::default(); Self { - enable_interrogative_upspeak: options.enable_interrogative_upspeak, + enable_interrogative_upspeak: + voicevox_core::__internal::interop::DEFAULT_ENABLE_INTERROGATIVE_UPSPEAK, } } } diff --git a/crates/voicevox_core_c_api/src/lib.rs b/crates/voicevox_core_c_api/src/lib.rs index c8de1a3c6..38d4706b6 100644 --- a/crates/voicevox_core_c_api/src/lib.rs +++ b/crates/voicevox_core_c_api/src/lib.rs @@ -38,8 +38,7 @@ use std::sync::Once; use tracing_subscriber::fmt::format::Writer; use tracing_subscriber::EnvFilter; use uuid::Uuid; -use voicevox_core::{AccentPhrase, AudioQuery, TtsOptions, UserDictWord}; -use voicevox_core::{StyleId, SynthesisOptions}; +use voicevox_core::{AccentPhrase, AudioQuery, StyleId, UserDictWord}; fn init_logger_once() { static ONCE: Once = Once::new(); @@ -362,7 +361,7 @@ pub extern "C" fn voicevox_open_jtalk_rc_delete(open_jtalk: *mut OpenJtalkRc) { /// ハードウェアアクセラレーションモードを設定する設定値。 #[repr(i32)] -#[derive(Debug, PartialEq, Eq)] +#[derive(Debug, PartialEq, Eq, Clone, Copy)] #[allow( non_camel_case_types, reason = "実際に公開するC APIとの差異をできるだけ少なくするため" @@ -544,9 +543,7 @@ pub unsafe extern "C" fn voicevox_synthesizer_new( ) -> VoicevoxResultCode { init_logger_once(); into_result_code_with_error((|| { - let options = options.into(); - - let synthesizer = VoicevoxSynthesizer::new(onnxruntime, open_jtalk, &options)?; + let synthesizer = VoicevoxSynthesizer::new(onnxruntime, open_jtalk, options)?; out_synthesizer.write_unaligned(synthesizer); Ok(()) })()) @@ -1083,11 +1080,14 @@ pub unsafe extern "C" fn voicevox_synthesizer_synthesis( .map_err(|_| CApiError::InvalidUtf8Input)?; let audio_query: AudioQuery = serde_json::from_str(audio_query_json).map_err(CApiError::InvalidAudioQuery)?; - let wav = synthesizer.body().synthesis( - &audio_query, - StyleId::new(style_id), - &SynthesisOptions::from(options), - )?; + let VoicevoxSynthesisOptions { + enable_interrogative_upspeak, + } = options; + let wav = synthesizer + .body() + .synthesis(&audio_query, StyleId::new(style_id)) + .enable_interrogative_upspeak(enable_interrogative_upspeak) + .exec()?; U8_SLICE_OWNER.own_and_lend(wav, output_wav, output_wav_length); Ok(()) })()) @@ -1107,7 +1107,7 @@ pub struct VoicevoxTtsOptions { #[no_mangle] pub extern "C" fn voicevox_make_default_tts_options() -> VoicevoxTtsOptions { init_logger_once(); - voicevox_core::TtsOptions::default().into() + VoicevoxTtsOptions::default() } // TODO: cbindgenが`#[unsafe(no_mangle)]`に対応したら`#[no_mangle]`を置き換える @@ -1142,11 +1142,14 @@ pub unsafe extern "C" fn voicevox_synthesizer_tts_from_kana( init_logger_once(); into_result_code_with_error((|| { let kana = ensure_utf8(CStr::from_ptr(kana))?; - let output = synthesizer.body().tts_from_kana( - kana, - StyleId::new(style_id), - &TtsOptions::from(options), - )?; + let VoicevoxTtsOptions { + enable_interrogative_upspeak, + } = options; + let output = synthesizer + .body() + .tts_from_kana(kana, StyleId::new(style_id)) + .enable_interrogative_upspeak(enable_interrogative_upspeak) + .exec()?; U8_SLICE_OWNER.own_and_lend(output, output_wav, output_wav_length); Ok(()) })()) @@ -1184,10 +1187,14 @@ pub unsafe extern "C" fn voicevox_synthesizer_tts( init_logger_once(); into_result_code_with_error((|| { let text = ensure_utf8(CStr::from_ptr(text))?; - let output = - synthesizer - .body() - .tts(text, StyleId::new(style_id), &TtsOptions::from(options))?; + let VoicevoxTtsOptions { + enable_interrogative_upspeak, + } = options; + let output = synthesizer + .body() + .tts(text, StyleId::new(style_id)) + .enable_interrogative_upspeak(enable_interrogative_upspeak) + .exec()?; U8_SLICE_OWNER.own_and_lend(output, output_wav, output_wav_length); Ok(()) })()) diff --git a/crates/voicevox_core_java_api/src/synthesizer.rs b/crates/voicevox_core_java_api/src/synthesizer.rs index 0c60133da..023c5674b 100644 --- a/crates/voicevox_core_java_api/src/synthesizer.rs +++ b/crates/voicevox_core_java_api/src/synthesizer.rs @@ -20,8 +20,6 @@ unsafe extern "system" fn Java_jp_hiroshiba_voicevoxcore_blocking_Synthesizer_rs builder: JObject<'local>, ) { throw_if_err(env, (), |env| { - let mut options = voicevox_core::InitializeOptions::default(); - let acceleration_mode = env .get_field( &builder, @@ -30,11 +28,13 @@ unsafe extern "system" fn Java_jp_hiroshiba_voicevoxcore_blocking_Synthesizer_rs )? .l()?; - if !acceleration_mode.is_null() { + let acceleration_mode = if acceleration_mode.is_null() { + Default::default() + } else { let auto = enum_object!(env, "AccelerationMode", "AUTO")?; let cpu = enum_object!(env, "AccelerationMode", "CPU")?; let gpu = enum_object!(env, "AccelerationMode", "GPU")?; - options.acceleration_mode = if env.is_same_object(&acceleration_mode, auto)? { + if env.is_same_object(&acceleration_mode, auto)? { voicevox_core::AccelerationMode::Auto } else if env.is_same_object(&acceleration_mode, cpu)? { voicevox_core::AccelerationMode::Cpu @@ -42,10 +42,12 @@ unsafe extern "system" fn Java_jp_hiroshiba_voicevoxcore_blocking_Synthesizer_rs voicevox_core::AccelerationMode::Gpu } else { panic!("予期しない`AccelerationMode`です: {acceleration_mode:?}"); - }; - } - let cpu_num_threads = env.get_field(&builder, "cpuNumThreads", "I")?; - options.cpu_num_threads = cpu_num_threads.i().expect("cpuNumThreads is not integer") as u16; + } + }; + let cpu_num_threads = env + .get_field(&builder, "cpuNumThreads", "I")? + .i() + .expect("cpuNumThreads is not integer") as u16; let onnxruntime = *env .get_rust_field::<_, _, &'static voicevox_core::blocking::Onnxruntime>( @@ -55,11 +57,13 @@ unsafe extern "system" fn Java_jp_hiroshiba_voicevoxcore_blocking_Synthesizer_rs let open_jtalk = env .get_rust_field::<_, _, voicevox_core::blocking::OpenJtalk>(&open_jtalk, "handle")? .clone(); - let internal = Arc::new(voicevox_core::blocking::Synthesizer::new( - onnxruntime, - open_jtalk, - &options, - )?); + let internal = Arc::new( + voicevox_core::blocking::Synthesizer::builder(onnxruntime) + .open_jtalk(open_jtalk) + .acceleration_mode(acceleration_mode) + .cpu_num_threads(cpu_num_threads) + .build()?, + ); env.set_rust_field(&this, "handle", internal)?; Ok(()) }) @@ -424,17 +428,10 @@ unsafe extern "system" fn Java_jp_hiroshiba_voicevoxcore_blocking_Synthesizer_rs )? .clone(); - let wave = { - let options = voicevox_core::SynthesisOptions { - enable_interrogative_upspeak: enable_interrogative_upspeak != 0, - // ..Default::default() - }; - internal.synthesis( - &audio_query, - voicevox_core::StyleId::new(style_id), - &options, - )? - }; + let wave = internal + .synthesis(&audio_query, voicevox_core::StyleId::new(style_id)) + .enable_interrogative_upspeak(enable_interrogative_upspeak != 0) + .exec()?; let j_bytes = env.byte_array_from_slice(&wave)?; @@ -463,13 +460,10 @@ unsafe extern "system" fn Java_jp_hiroshiba_voicevoxcore_blocking_Synthesizer_rs )? .clone(); - let wave = { - let options = voicevox_core::TtsOptions { - enable_interrogative_upspeak: enable_interrogative_upspeak != 0, - // ..Default::default() - }; - internal.tts_from_kana(&kana, voicevox_core::StyleId::new(style_id), &options)? - }; + let wave = internal + .tts_from_kana(&kana, voicevox_core::StyleId::new(style_id)) + .enable_interrogative_upspeak(enable_interrogative_upspeak != 0) + .exec()?; let j_bytes = env.byte_array_from_slice(&wave)?; @@ -496,13 +490,10 @@ unsafe extern "system" fn Java_jp_hiroshiba_voicevoxcore_blocking_Synthesizer_rs )? .clone(); - let wave = { - let options = voicevox_core::TtsOptions { - enable_interrogative_upspeak: enable_interrogative_upspeak != 0, - // ..Default::default() - }; - internal.tts(&text, voicevox_core::StyleId::new(style_id), &options)? - }; + let wave = internal + .tts(&text, voicevox_core::StyleId::new(style_id)) + .enable_interrogative_upspeak(enable_interrogative_upspeak != 0) + .exec()?; let j_bytes = env.byte_array_from_slice(&wave)?; diff --git a/crates/voicevox_core_python_api/src/lib.rs b/crates/voicevox_core_python_api/src/lib.rs index 778e9c39d..fc12a9712 100644 --- a/crates/voicevox_core_python_api/src/lib.rs +++ b/crates/voicevox_core_python_api/src/lib.rs @@ -299,10 +299,7 @@ mod blocking { Py, PyAny, PyObject, PyRef, PyResult, Python, }; use uuid::Uuid; - use voicevox_core::{ - AccelerationMode, AudioQuery, InitializeOptions, StyleId, SynthesisOptions, TtsOptions, - UserDictWord, - }; + use voicevox_core::{AccelerationMode, AudioQuery, StyleId, UserDictWord}; use crate::{ convert::VoicevoxCoreResultExt as _, Closable, SingleTasked, VoiceModelFilePyFields, @@ -484,8 +481,8 @@ mod blocking { #[pyo3(signature =( onnxruntime, open_jtalk, - acceleration_mode = InitializeOptions::default().acceleration_mode, - cpu_num_threads = InitializeOptions::default().cpu_num_threads, + acceleration_mode = Default::default(), + cpu_num_threads = voicevox_core::__internal::interop::DEFAULT_CPU_NUM_THREADS, ))] fn new( onnxruntime: Onnxruntime, @@ -495,15 +492,12 @@ mod blocking { cpu_num_threads: u16, py: Python<'_>, ) -> PyResult { - let inner = voicevox_core::blocking::Synthesizer::new( - onnxruntime.0, - open_jtalk.open_jtalk.clone(), - &InitializeOptions { - acceleration_mode, - cpu_num_threads, - }, - ) - .into_py_result(py)?; + let inner = voicevox_core::blocking::Synthesizer::builder(onnxruntime.0) + .open_jtalk(open_jtalk.open_jtalk.clone()) + .acceleration_mode(acceleration_mode) + .cpu_num_threads(cpu_num_threads) + .build() + .into_py_result(py)?; Ok(Self { synthesizer: Closable::new(inner), }) @@ -690,7 +684,8 @@ mod blocking { #[pyo3(signature=( audio_query, style_id, - enable_interrogative_upspeak = TtsOptions::default().enable_interrogative_upspeak + enable_interrogative_upspeak = + voicevox_core::__internal::interop::DEFAULT_ENABLE_INTERROGATIVE_UPSPEAK, ))] fn precompute_render( &self, @@ -702,13 +697,9 @@ mod blocking { let audio = self .synthesizer .read()? - .precompute_render( - &audio_query, - StyleId::new(style_id), - &SynthesisOptions { - enable_interrogative_upspeak, - }, - ) + .precompute_render(&audio_query, StyleId::new(style_id)) + .enable_interrogative_upspeak(enable_interrogative_upspeak) + .exec() .into_py_result(py)?; Ok(AudioFeature { audio }) } @@ -742,7 +733,8 @@ mod blocking { #[pyo3(signature=( audio_query, style_id, - enable_interrogative_upspeak = TtsOptions::default().enable_interrogative_upspeak + enable_interrogative_upspeak = + voicevox_core::__internal::interop::DEFAULT_ENABLE_INTERROGATIVE_UPSPEAK, ))] fn synthesis<'py>( &self, @@ -754,13 +746,9 @@ mod blocking { let wav = &self .synthesizer .read()? - .synthesis( - &audio_query, - StyleId::new(style_id), - &SynthesisOptions { - enable_interrogative_upspeak, - }, - ) + .synthesis(&audio_query, StyleId::new(style_id)) + .enable_interrogative_upspeak(enable_interrogative_upspeak) + .exec() .into_py_result(py)?; Ok(PyBytes::new(py, wav)) } @@ -768,7 +756,8 @@ mod blocking { #[pyo3(signature=( kana, style_id, - enable_interrogative_upspeak = TtsOptions::default().enable_interrogative_upspeak + enable_interrogative_upspeak = + voicevox_core::__internal::interop::DEFAULT_ENABLE_INTERROGATIVE_UPSPEAK, ))] fn tts_from_kana<'py>( &self, @@ -778,13 +767,12 @@ mod blocking { py: Python<'py>, ) -> PyResult<&'py PyBytes> { let style_id = StyleId::new(style_id); - let options = &TtsOptions { - enable_interrogative_upspeak, - }; let wav = &self .synthesizer .read()? - .tts_from_kana(kana, style_id, options) + .tts_from_kana(kana, style_id) + .enable_interrogative_upspeak(enable_interrogative_upspeak) + .exec() .into_py_result(py)?; Ok(PyBytes::new(py, wav)) } @@ -792,7 +780,8 @@ mod blocking { #[pyo3(signature=( text, style_id, - enable_interrogative_upspeak = TtsOptions::default().enable_interrogative_upspeak + enable_interrogative_upspeak = + voicevox_core::__internal::interop::DEFAULT_ENABLE_INTERROGATIVE_UPSPEAK, ))] fn tts<'py>( &self, @@ -802,13 +791,12 @@ mod blocking { py: Python<'py>, ) -> PyResult<&'py PyBytes> { let style_id = StyleId::new(style_id); - let options = &TtsOptions { - enable_interrogative_upspeak, - }; let wav = &self .synthesizer .read()? - .tts(text, style_id, options) + .tts(text, style_id) + .enable_interrogative_upspeak(enable_interrogative_upspeak) + .exec() .into_py_result(py)?; Ok(PyBytes::new(py, wav)) } @@ -899,10 +887,7 @@ mod asyncio { Py, PyAny, PyErr, PyObject, PyRef, PyResult, Python, ToPyObject as _, }; use uuid::Uuid; - use voicevox_core::{ - AccelerationMode, AudioQuery, InitializeOptions, StyleId, SynthesisOptions, TtsOptions, - UserDictWord, - }; + use voicevox_core::{AccelerationMode, AudioQuery, StyleId, UserDictWord}; use crate::{convert::VoicevoxCoreResultExt as _, Closable, Tokio, VoiceModelFilePyFields}; @@ -1092,8 +1077,8 @@ mod asyncio { #[pyo3(signature =( onnxruntime, open_jtalk, - acceleration_mode = InitializeOptions::default().acceleration_mode, - cpu_num_threads = InitializeOptions::default().cpu_num_threads, + acceleration_mode = Default::default(), + cpu_num_threads = voicevox_core::__internal::interop::DEFAULT_CPU_NUM_THREADS, ))] fn new( onnxruntime: Onnxruntime, @@ -1102,14 +1087,11 @@ mod asyncio { acceleration_mode: AccelerationMode, cpu_num_threads: u16, ) -> PyResult { - let synthesizer = voicevox_core::nonblocking::Synthesizer::new( - onnxruntime.0, - open_jtalk.open_jtalk.clone(), - &InitializeOptions { - acceleration_mode, - cpu_num_threads, - }, - ); + let synthesizer = voicevox_core::nonblocking::Synthesizer::builder(onnxruntime.0) + .open_jtalk(open_jtalk.open_jtalk.clone()) + .acceleration_mode(acceleration_mode) + .cpu_num_threads(cpu_num_threads) + .build(); let synthesizer = Python::with_gil(|py| synthesizer.into_py_result(py))?; let synthesizer = Closable::new(synthesizer).into(); Ok(Self { synthesizer }) @@ -1360,7 +1342,12 @@ mod asyncio { ) } - #[pyo3(signature=(audio_query,style_id,enable_interrogative_upspeak = TtsOptions::default().enable_interrogative_upspeak))] + #[pyo3(signature=( + audio_query, + style_id, + enable_interrogative_upspeak = + voicevox_core::__internal::interop::DEFAULT_ENABLE_INTERROGATIVE_UPSPEAK, + ))] fn synthesis<'py>( &self, #[pyo3(from_py_with = "crate::convert::from_dataclass")] audio_query: AudioQuery, @@ -1375,13 +1362,9 @@ mod asyncio { async move { let wav = synthesizer .read()? - .synthesis( - &audio_query, - StyleId::new(style_id), - &SynthesisOptions { - enable_interrogative_upspeak, - }, - ) + .synthesis(&audio_query, StyleId::new(style_id)) + .enable_interrogative_upspeak(enable_interrogative_upspeak) + .exec() .await; Python::with_gil(|py| { let wav = wav.into_py_result(py)?; @@ -1394,7 +1377,8 @@ mod asyncio { #[pyo3(signature=( kana, style_id, - enable_interrogative_upspeak = TtsOptions::default().enable_interrogative_upspeak + enable_interrogative_upspeak = + voicevox_core::__internal::interop::DEFAULT_ENABLE_INTERROGATIVE_UPSPEAK, ))] fn tts_from_kana<'py>( &self, @@ -1404,9 +1388,6 @@ mod asyncio { py: Python<'py>, ) -> PyResult<&'py PyAny> { let style_id = StyleId::new(style_id); - let options = TtsOptions { - enable_interrogative_upspeak, - }; let synthesizer = self.synthesizer.clone(); let kana = kana.to_owned(); pyo3_asyncio::tokio::future_into_py_with_locals( @@ -1415,7 +1396,9 @@ mod asyncio { async move { let wav = synthesizer .read()? - .tts_from_kana(&kana, style_id, &options) + .tts_from_kana(&kana, style_id) + .enable_interrogative_upspeak(enable_interrogative_upspeak) + .exec() .await; Python::with_gil(|py| { @@ -1429,7 +1412,8 @@ mod asyncio { #[pyo3(signature=( text, style_id, - enable_interrogative_upspeak = TtsOptions::default().enable_interrogative_upspeak + enable_interrogative_upspeak = + voicevox_core::__internal::interop::DEFAULT_ENABLE_INTERROGATIVE_UPSPEAK, ))] fn tts<'py>( &self, @@ -1439,16 +1423,18 @@ mod asyncio { py: Python<'py>, ) -> PyResult<&'py PyAny> { let style_id = StyleId::new(style_id); - let options = TtsOptions { - enable_interrogative_upspeak, - }; let synthesizer = self.synthesizer.clone(); let text = text.to_owned(); pyo3_asyncio::tokio::future_into_py_with_locals( py, pyo3_asyncio::tokio::get_current_locals(py)?, async move { - let wav = synthesizer.read()?.tts(&text, style_id, &options).await; + let wav = synthesizer + .read()? + .tts(&text, style_id) + .enable_interrogative_upspeak(enable_interrogative_upspeak) + .exec() + .await; Python::with_gil(|py| { let wav = wav.into_py_result(py)?;