diff --git a/crates/voicevox_core/src/devices.rs b/crates/voicevox_core/src/devices.rs index 140105962..dfe8d7e64 100644 --- a/crates/voicevox_core/src/devices.rs +++ b/crates/voicevox_core/src/devices.rs @@ -1,11 +1,10 @@ -use derive_getters::Getters; use serde::{Deserialize, Serialize}; /// このライブラリで利用可能なデバイスの情報。 /// /// あくまで本ライブラリが対応しているデバイスの情報であることに注意。GPUが使える環境ではなかったと /// しても`cuda`や`dml`は`true`を示しうる。 -#[derive(Getters, Debug, Serialize, Deserialize)] +#[derive(Debug, Serialize, Deserialize)] pub struct SupportedDevices { /// CPUが利用可能。 /// diff --git a/crates/voicevox_core/src/engine/full_context_label.rs b/crates/voicevox_core/src/engine/full_context_label.rs index 4f95abbf2..92617a8c1 100644 --- a/crates/voicevox_core/src/engine/full_context_label.rs +++ b/crates/voicevox_core/src/engine/full_context_label.rs @@ -88,14 +88,14 @@ fn generate_accent_phrases( let pause_mora = if ap_curr.accent_phrase_position_backward == 1 && bg_curr.breath_group_position_backward != 1 { - Some(crate::Mora::new( - "、".into(), - None, - None, - "pau".into(), - 0., - 0., - )) + Some(crate::Mora { + text: "、".into(), + consonant: None, + consonant_length: None, + vowel: "pau".into(), + vowel_length: 0., + pitch: 0., + }) } else { None }; @@ -103,12 +103,12 @@ fn generate_accent_phrases( // workaround for VOICEVOX/voicevox_engine#55 let accent = usize::from(ap_curr.accent_position).min(moras.len()); - accent_phrases.push(AccentPhrase::new( + accent_phrases.push(AccentPhrase { moras, accent, pause_mora, - ap_curr.is_interrogative, - )) + is_interrogative: ap_curr.is_interrogative, + }) } Ok(accent_phrases) } @@ -153,15 +153,15 @@ fn generate_moras(accent_phrase: &[Label]) -> std::result::Result, vowel: &Label) -> crate::Mora { let consonant_phoneme = consonant.and_then(|c| c.phoneme.c.to_owned()); - let vowel_phoneme = vowel.phoneme.c.as_deref().unwrap(); - crate::Mora::new( - mora_to_text(consonant_phoneme.as_deref(), vowel_phoneme), - consonant_phoneme, - consonant.and(Some(0.0)), - vowel_phoneme.to_string(), - 0.0, - 0.0, - ) + let vowel = vowel.phoneme.c.clone().unwrap(); + crate::Mora { + text: mora_to_text(consonant_phoneme.as_deref(), &vowel), + consonant: consonant_phoneme, + consonant_length: consonant.and(Some(0.0)), + vowel, + vowel_length: 0.0, + pitch: 0.0, + } } pub fn mora_to_text(consonant: Option<&str>, vowel: &str) -> String { @@ -197,14 +197,14 @@ mod tests { use jlabel::Label; fn mora(text: &str, consonant: Option<&str>, vowel: &str) -> Mora { - Mora::new( - text.into(), - consonant.map(|c| c.into()), - consonant.and(Some(0.0)), - vowel.into(), - 0.0, - 0.0, - ) + Mora { + text: text.into(), + consonant: consonant.map(|c| c.into()), + consonant_length: consonant.and(Some(0.0)), + vowel: vowel.into(), + vowel_length: 0.0, + pitch: 0.0, + } } #[template] @@ -218,12 +218,12 @@ mod tests { "y^e-sil+xx=xx/A:xx+xx+xx/B:xx-xx_xx/C:xx_xx+xx/D:xx+xx_xx/E:1_1!0_xx-xx/F:xx_xx#xx_xx@xx_xx|xx_xx/G:xx_xx%xx_xx_xx/H:1_1/I:xx-xx@xx+xx&xx-xx|xx+xx/J:xx_xx/K:1+1-1", ], &[ - AccentPhrase::new( - vec![mora("イェ", Some("y"), "e")], - 1, - None, - false, - ) + AccentPhrase { + moras: vec![mora("イェ", Some("y"), "e")], + accent: 1, + pause_mora: None, + is_interrogative: false, + } ] )] #[case( @@ -236,16 +236,16 @@ mod tests { "N^cl-sil+xx=xx/A:xx+xx+xx/B:09-xx_xx/C:xx_xx+xx/D:xx+xx_xx/E:3_3!0_xx-xx/F:xx_xx#xx_xx@xx_xx|xx_xx/G:xx_xx%xx_xx_xx/H:1_3/I:xx-xx@xx+xx&xx-xx|xx+xx/J:xx_xx/K:1+1-3", ], &[ - AccentPhrase::new( - vec![ + AccentPhrase { + moras: vec![ mora("ン", None, "N"), mora("ン", None, "N"), mora("ッ", None, "cl"), ], - 3, - None, - false, - ), + accent: 3, + pause_mora: None, + is_interrogative: false, + }, ] )] #[case( @@ -271,28 +271,28 @@ mod tests { "s^U-sil+xx=xx/A:xx+xx+xx/B:10-7_2/C:xx_xx+xx/D:xx+xx_xx/E:5_1!0_xx-xx/F:xx_xx#xx_xx@xx_xx|xx_xx/G:xx_xx%xx_xx_xx/H:2_8/I:xx-xx@xx+xx&xx-xx|xx+xx/J:xx_xx/K:1+2-8", ], &[ - AccentPhrase::new( - vec![ + AccentPhrase { + moras: vec![ mora("コ", Some("k"), "o"), mora("レ", Some("r"), "e"), mora("ワ", Some("w"), "a"), ], - 3, - None, - false, - ), - AccentPhrase::new( - vec![ + accent: 3, + pause_mora: None, + is_interrogative: false, + }, + AccentPhrase { + moras: vec![ mora("テ", Some("t"), "e"), mora("ス", Some("s"), "U"), mora("ト", Some("t"), "o"), mora("デ", Some("d"), "e"), mora("ス", Some("s"), "U"), ], - 1, - None, - false, - ), + accent: 1, + pause_mora: None, + is_interrogative: false, + }, ] )] #[case( @@ -324,46 +324,46 @@ mod tests { "k^u-sil+xx=xx/A:xx+xx+xx/B:05-xx_xx/C:xx_xx+xx/D:xx+xx_xx/E:4_2!1_xx-xx/F:xx_xx#xx_xx@xx_xx|xx_xx/G:xx_xx%xx_xx_xx/H:1_4/I:xx-xx@xx+xx&xx-xx|xx+xx/J:xx_xx/K:4+4-12", ], &[ - AccentPhrase::new( - vec![ + AccentPhrase { + moras: vec![ mora("イ", None, "i"), mora("チ", Some("ch"), "i"), ], - 2, - Some(mora("、", None, "pau")), - false, - ), - AccentPhrase::new( - vec![ + accent: 2, + pause_mora: Some(mora("、", None, "pau")), + is_interrogative: false, + }, + AccentPhrase { + moras: vec![ mora("セ", Some("s"), "e"), mora("ン", None, "N"), ], - 1, - Some(mora("、", None, "pau")), - false, - ), - AccentPhrase::new( - vec![ + accent: 1, + pause_mora: Some(mora("、", None, "pau")), + is_interrogative: false, + }, + AccentPhrase { + moras: vec![ mora("ヒャ", Some("hy"), "a"), mora("ク", Some("k"), "u"), mora("マ", Some("m"), "a"), mora("ン", None, "N"), ], - 3, - Some(mora("、", None, "pau")), - false, - ), - AccentPhrase::new( - vec![ + accent: 3, + pause_mora: Some(mora("、", None, "pau")), + is_interrogative: false, + }, + AccentPhrase { + moras: vec![ mora("イ", None, "i"), mora("チ", Some("ch"), "i"), mora("オ", None, "o"), mora("ク", Some("k"), "u"), ], - 2, - None, - true, - ), + accent: 2, + pause_mora: None, + is_interrogative: true, + }, ] )] #[case( @@ -386,33 +386,33 @@ mod tests { "a^a-sil+xx=xx/A:xx+xx+xx/B:09-xx_xx/C:xx_xx+xx/D:xx+xx_xx/E:1_1!0_xx-xx/F:xx_xx#xx_xx@xx_xx|xx_xx/G:xx_xx%xx_xx_xx/H:2_3/I:xx-xx@xx+xx&xx-xx|xx+xx/J:xx_xx/K:2+3-8", ], &[ - AccentPhrase::new( - vec![ + AccentPhrase { + moras: vec![ mora("クヮ", Some("kw"), "a"), mora("ル", Some("r"), "u"), mora("テ", Some("t"), "e"), mora("ッ", None, "cl"), mora("ト", Some("t"), "o"), ], - 3, - Some(mora("、", None, "pau")), - false, - ), - AccentPhrase::new( - vec![ + accent: 3, + pause_mora: Some(mora("、", None, "pau")), + is_interrogative: false, + }, + AccentPhrase { + moras: vec![ mora("ア", None, "a"), mora("ア", None, "a"), ], - 1, - None, - false, - ), - AccentPhrase::new( - vec![mora("ア", None, "a")], - 1, - None, - false, - ), + accent: 1, + pause_mora: None, + is_interrogative: false, + }, + AccentPhrase { + moras: vec![mora("ア", None, "a")], + accent: 1, + pause_mora: None, + is_interrogative: false, + }, ] )] fn label_cases( diff --git a/crates/voicevox_core/src/engine/kana_parser.rs b/crates/voicevox_core/src/engine/kana_parser.rs index 42f17dc63..9397376f6 100644 --- a/crates/voicevox_core/src/engine/kana_parser.rs +++ b/crates/voicevox_core/src/engine/kana_parser.rs @@ -27,26 +27,27 @@ static TEXT2MORA_WITH_UNVOICE: Lazy> = Lazy::new(|| { let consonant_length = if consonant.is_some() { Some(0.0) } else { None }; if ["a", "i", "u", "e", "o"].contains(vowel) { - let upper_vowel = vowel.to_uppercase(); - let unvoice_mora = Mora::new( - text.to_string(), - consonant.clone(), + let vowel = vowel.to_uppercase(); + + let unvoice_mora = Mora { + text: text.to_string(), + consonant: consonant.clone(), consonant_length, - upper_vowel, - 0., - 0., - ); + vowel, + vowel_length: 0., + pitch: 0., + }; text2mora_with_unvoice.insert(UNVOICE_SYMBOL.to_string() + text, unvoice_mora); } - let mora = Mora::new( - text.to_string(), + let mora = Mora { + text: text.to_string(), consonant, consonant_length, - vowel.to_string(), - 0., - 0., - ); + vowel: vowel.to_string(), + vowel_length: 0., + pitch: 0., + }; text2mora_with_unvoice.insert(text.to_string(), mora); } text2mora_with_unvoice @@ -107,7 +108,12 @@ fn text_to_accent_phrase(phrase: &str) -> KanaParseResult { "accent not found in accent phrase: {phrase}" ))); } - Ok(AccentPhrase::new(moras, accent_index.unwrap(), None, false)) + Ok(AccentPhrase { + moras, + accent: accent_index.unwrap(), + pause_mora: None, + is_interrogative: false, + }) } pub(crate) fn parse_kana(text: &str) -> KanaParseResult> { @@ -137,14 +143,14 @@ pub(crate) fn parse_kana(text: &str) -> KanaParseResult> { let accent_phrase = { let mut accent_phrase = text_to_accent_phrase(&phrase)?; if letter == PAUSE_DELIMITER { - accent_phrase.set_pause_mora(Some(Mora::new( - PAUSE_DELIMITER.to_string(), - None, - None, - "pau".to_string(), - 0., - 0., - ))); + accent_phrase.set_pause_mora(Some(Mora { + text: PAUSE_DELIMITER.to_string(), + consonant: None, + consonant_length: None, + vowel: "pau".to_string(), + vowel_length: 0., + pitch: 0., + })); } accent_phrase.set_is_interrogative(is_interrogative); accent_phrase @@ -161,20 +167,19 @@ pub(crate) fn parse_kana(text: &str) -> KanaParseResult> { pub(crate) fn create_kana(accent_phrases: &[AccentPhrase]) -> String { let mut text = String::new(); for phrase in accent_phrases { - let moras = phrase.moras(); - for (index, mora) in moras.iter().enumerate() { - if ["A", "E", "I", "O", "U"].contains(&(*mora.vowel()).as_ref()) { + for (index, mora) in phrase.moras.iter().enumerate() { + if ["A", "E", "I", "O", "U"].contains(&&*mora.vowel) { text.push(UNVOICE_SYMBOL); } - text.push_str(mora.text()); - if index + 1 == *phrase.accent() { + text.push_str(&mora.text); + if index + 1 == phrase.accent { text.push(ACCENT_SYMBOL); } } - if *phrase.is_interrogative() { + if phrase.is_interrogative { text.push(WIDE_INTERROGATION_MARK); } - text.push(if phrase.pause_mora().is_some() { + text.push(if phrase.pause_mora.is_some() { PAUSE_DELIMITER } else { NOPAUSE_DELIMITER @@ -207,10 +212,10 @@ mod tests { assert_eq!(mora.is_some(), res.is_some()); if let Some(res) = res { let mut m = String::new(); - if let Some(ref c) = *res.consonant() { + if let Some(c) = &res.consonant { m.push_str(c); } - m.push_str(res.vowel()); + m.push_str(&res.vowel); assert_eq!(m, mora.unwrap()); } } diff --git a/crates/voicevox_core/src/engine/model.rs b/crates/voicevox_core/src/engine/model.rs index 09f53b6ee..20203feb3 100644 --- a/crates/voicevox_core/src/engine/model.rs +++ b/crates/voicevox_core/src/engine/model.rs @@ -1,38 +1,36 @@ -use derive_getters::Getters; -use derive_new::new; use serde::{Deserialize, Serialize}; /* 各フィールドのjsonフィールド名はsnake_caseとする*/ /// モーラ(子音+母音)ごとの情報。 -#[derive(Clone, Debug, new, Getters, Deserialize, Serialize, PartialEq)] +#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)] pub struct Mora { /// 文字。 - text: String, + pub text: String, /// 子音の音素。 - consonant: Option, + pub consonant: Option, /// 子音の音長。 - consonant_length: Option, + pub consonant_length: Option, /// 母音の音素。 - vowel: String, + pub vowel: String, /// 母音の音長。 - vowel_length: f32, + pub vowel_length: f32, /// 音高。 - pitch: f32, + pub pitch: f32, } /// AccentPhrase (アクセント句ごとの情報)。 -#[derive(Clone, Debug, new, Getters, Deserialize, Serialize, PartialEq)] +#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)] pub struct AccentPhrase { /// モーラの配列。 - moras: Vec, + pub moras: Vec, /// アクセント箇所。 - accent: usize, + pub accent: usize, /// 後ろに無音を付けるかどうか。 - pause_mora: Option, + pub pause_mora: Option, /// 疑問系かどうか。 #[serde(default)] - is_interrogative: bool, + pub is_interrogative: bool, } impl AccentPhrase { @@ -46,34 +44,33 @@ impl AccentPhrase { } /// AudioQuery (音声合成用のクエリ)。 -#[allow(clippy::too_many_arguments)] -#[derive(Clone, new, Getters, Deserialize, Serialize)] +#[derive(Clone, Deserialize, Serialize)] pub struct AudioQuery { /// アクセント句の配列。 - accent_phrases: Vec, + pub accent_phrases: Vec, /// 全体の話速。 - speed_scale: f32, + pub speed_scale: f32, /// 全体の音高。 - pitch_scale: f32, + pub pitch_scale: f32, /// 全体の抑揚。 - intonation_scale: f32, + pub intonation_scale: f32, /// 全体の音量。 - volume_scale: f32, + pub volume_scale: f32, /// 音声の前の無音時間。 - pre_phoneme_length: f32, + pub pre_phoneme_length: f32, /// 音声の後の無音時間。 - post_phoneme_length: f32, + pub post_phoneme_length: f32, /// 音声データの出力サンプリングレート。 - output_sampling_rate: u32, + pub output_sampling_rate: u32, /// 音声データをステレオ出力するか否か。 - output_stereo: bool, + pub output_stereo: bool, /// \[読み取り専用\] AquesTalk風記法。 /// /// [`Synthesizer::audio_query`]が返すもののみ`Some`となる。入力としてのAudioQueryでは無視され /// る。 /// - /// [`Synthesizer::audio_query`]: crate::Synthesizer::audio_query - kana: Option, + /// [`Synthesizer::audio_query`]: crate::blocking::Synthesizer::audio_query + pub kana: Option, } impl AudioQuery { @@ -92,8 +89,18 @@ mod tests { #[rstest] fn check_audio_query_model_json_field_snake_case() { - let audio_query_model = - AudioQuery::new(vec![], 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, false, None); + let audio_query_model = AudioQuery { + accent_phrases: vec![], + speed_scale: 0.0, + pitch_scale: 0.0, + intonation_scale: 0.0, + volume_scale: 0.0, + pre_phoneme_length: 0.0, + post_phoneme_length: 0.0, + output_sampling_rate: 0, + output_stereo: false, + kana: None, + }; let val = serde_json::to_value(audio_query_model).unwrap(); check_json_field_snake_case(&val); } diff --git a/crates/voicevox_core/src/metas.rs b/crates/voicevox_core/src/metas.rs index b9f274c48..1fb4a7f9d 100644 --- a/crates/voicevox_core/src/metas.rs +++ b/crates/voicevox_core/src/metas.rs @@ -1,6 +1,5 @@ use std::fmt::{Debug, Display}; -use derive_getters::Getters; use derive_new::new; use indexmap::IndexMap; use itertools::Itertools as _; @@ -102,20 +101,20 @@ impl Display for StyleVersion { pub type VoiceModelMeta = Vec; /// **話者**(_speaker_)のメタ情報。 -#[derive(Deserialize, Serialize, Getters, Clone)] +#[derive(Deserialize, Serialize, Clone)] pub struct SpeakerMeta { /// 話者名。 - name: String, + pub name: String, /// 話者に属するスタイル。 - styles: Vec, + pub styles: Vec, /// 話者のバージョン。 - version: StyleVersion, + pub version: StyleVersion, /// 話者のUUID。 - speaker_uuid: String, + pub speaker_uuid: String, /// 話者の順番。 /// /// `SpeakerMeta`の列は、この値に対して昇順に並んでいるべきである。 - order: Option, + pub order: Option, } impl SpeakerMeta { @@ -161,19 +160,19 @@ impl SpeakerMeta { } /// **スタイル**(_style_)のメタ情報。 -#[derive(Deserialize, Serialize, Getters, Clone)] +#[derive(Deserialize, Serialize, Clone)] pub struct StyleMeta { /// スタイルID。 - id: StyleId, + pub id: StyleId, /// スタイル名。 - name: String, + pub name: String, /// スタイルに対応するモデルの種類。 #[serde(default)] - r#type: StyleType, + pub r#type: StyleType, /// スタイルの順番。 /// /// [`SpeakerMeta::styles`]は、この値に対して昇順に並んでいるべきである。 - order: Option, + pub order: Option, } /// **スタイル**(_style_)に対応するモデルの種類。 diff --git a/crates/voicevox_core/src/status.rs b/crates/voicevox_core/src/status.rs index 475031f1c..8c75d64d9 100644 --- a/crates/voicevox_core/src/status.rs +++ b/crates/voicevox_core/src/status.rs @@ -149,9 +149,10 @@ impl LoadedModels { .0 .iter() .find(|(_, LoadedModel { metas, .. })| { - metas.iter().flat_map(SpeakerMeta::styles).any(|style| { - *style.id() == style_id && D::style_types().contains(style.r#type()) - }) + metas + .iter() + .flat_map(|SpeakerMeta { styles, .. }| styles) + .any(|style| style.id == style_id && D::style_types().contains(&style.r#type)) }) .ok_or(ErrorRepr::StyleNotFound { style_id, @@ -200,7 +201,7 @@ impl LoadedModels { } fn contains_style(&self, style_id: StyleId) -> bool { - self.styles().any(|style| *style.id() == style_id) + self.styles().any(|style| style.id == style_id) } /// 音声モデルを受け入れ可能かをチェックする。 @@ -232,22 +233,21 @@ impl LoadedModels { let loaded = self.speakers(); let external = model_header.metas.iter(); for (loaded, external) in iproduct!(loaded, external) { - if loaded.speaker_uuid() == external.speaker_uuid() { + if loaded.speaker_uuid == external.speaker_uuid { loaded.warn_diff_except_styles(external); } } - let loaded = self.styles(); + let loaded = self.styles().map(|&StyleMeta { id, .. }| id); let external = model_header .metas .iter() - .flat_map(|speaker| speaker.styles()); - if let Some((style, _)) = - iproduct!(loaded, external).find(|(loaded, external)| loaded.id() == external.id()) + .flat_map(|speaker| &speaker.styles) + .map(|&StyleMeta { id, .. }| id); + if let Some((id, _)) = + iproduct!(loaded, external).find(|(loaded, external)| loaded == external) { - return Err(error(LoadModelErrorKind::StyleAlreadyLoaded { - id: *style.id(), - })); + return Err(error(LoadModelErrorKind::StyleAlreadyLoaded { id })); } Ok(()) } @@ -282,7 +282,8 @@ impl LoadedModels { } fn styles(&self) -> impl Iterator { - self.speakers().flat_map(|speaker| speaker.styles()) + self.speakers() + .flat_map(|SpeakerMeta { styles, .. }| styles) } } diff --git a/crates/voicevox_core/src/synthesizer.rs b/crates/voicevox_core/src/synthesizer.rs index 4f9576500..a11af2d5b 100644 --- a/crates/voicevox_core/src/synthesizer.rs +++ b/crates/voicevox_core/src/synthesizer.rs @@ -155,9 +155,9 @@ pub(crate) mod blocking { let supported_devices = onnxruntime.supported_devices()?; if cfg!(feature = "directml") { - *supported_devices.dml() + supported_devices.dml } else { - *supported_devices.cuda() + supported_devices.cuda } } AccelerationMode::Cpu => false, @@ -198,9 +198,9 @@ pub(crate) mod blocking { let supported_devices = onnxruntime.supported_devices()?; if cfg!(feature = "directml") { - Ok(*supported_devices.dml()) + Ok(supported_devices.dml) } else { - Ok(*supported_devices.cuda()) + Ok(supported_devices.cuda) } } } @@ -247,38 +247,44 @@ pub(crate) mod blocking { style_id: StyleId, options: &SynthesisOptions, ) -> Result> { - let speed_scale = *audio_query.speed_scale(); - let pitch_scale = *audio_query.pitch_scale(); - let intonation_scale = *audio_query.intonation_scale(); - let pre_phoneme_length = *audio_query.pre_phoneme_length(); - let post_phoneme_length = *audio_query.post_phoneme_length(); + let AudioQuery { + accent_phrases, + speed_scale, + pitch_scale, + intonation_scale, + pre_phoneme_length, + post_phoneme_length, + .. + } = audio_query; let accent_phrases = if options.enable_interrogative_upspeak { - adjust_interrogative_accent_phrases(audio_query.accent_phrases().as_slice()) + adjust_interrogative_accent_phrases(accent_phrases) } else { - audio_query.accent_phrases().clone() + accent_phrases.clone() }; let (flatten_moras, phoneme_data_list) = initial_process(&accent_phrases); - let mut phoneme_length_list = vec![pre_phoneme_length]; + let mut phoneme_length_list = vec![*pre_phoneme_length]; let mut f0_list = vec![0.]; let mut voiced_list = vec![false]; { let mut sum_of_f0_bigger_than_zero = 0.; let mut count_of_f0_bigger_than_zero = 0; - for mora in flatten_moras { - let consonant_length = *mora.consonant_length(); - let vowel_length = *mora.vowel_length(); - let pitch = *mora.pitch(); - + for Mora { + consonant_length, + vowel_length, + pitch, + .. + } in flatten_moras + { if let Some(consonant_length) = consonant_length { phoneme_length_list.push(consonant_length); } phoneme_length_list.push(vowel_length); - let f0_single = pitch * 2.0_f32.powf(pitch_scale); + let f0_single = pitch * 2.0_f32.powf(*pitch_scale); f0_list.push(f0_single); let bigger_than_zero = f0_single > 0.; @@ -289,7 +295,7 @@ pub(crate) mod blocking { count_of_f0_bigger_than_zero += 1; } } - phoneme_length_list.push(post_phoneme_length); + phoneme_length_list.push(*post_phoneme_length); f0_list.push(0.); voiced_list.push(false); let mean_f0 = sum_of_f0_bigger_than_zero / (count_of_f0_bigger_than_zero as f32); @@ -356,23 +362,23 @@ pub(crate) mod blocking { ) -> Vec { accent_phrases .iter() - .map(|accent_phrase| { - AccentPhrase::new( - adjust_interrogative_moras(accent_phrase), - *accent_phrase.accent(), - accent_phrase.pause_mora().clone(), - *accent_phrase.is_interrogative(), - ) + .map(|accent_phrase| AccentPhrase { + moras: adjust_interrogative_moras(accent_phrase), + ..accent_phrase.clone() }) .collect() } - fn adjust_interrogative_moras(accent_phrase: &AccentPhrase) -> Vec { - let moras = accent_phrase.moras(); - if *accent_phrase.is_interrogative() && !moras.is_empty() { + fn adjust_interrogative_moras( + AccentPhrase { + moras, + is_interrogative, + .. + }: &AccentPhrase, + ) -> Vec { + if *is_interrogative && !moras.is_empty() { let last_mora = moras.last().unwrap(); - let last_mora_pitch = *last_mora.pitch(); - if last_mora_pitch != 0.0 { + if last_mora.pitch != 0.0 { let mut new_moras: Vec = Vec::with_capacity(moras.len() + 1); new_moras.extend_from_slice(moras.as_slice()); let interrogative_mora = make_interrogative_mora(last_mora); @@ -388,23 +394,27 @@ pub(crate) mod blocking { const ADJUST_PITCH: f32 = 0.3; const MAX_PITCH: f32 = 6.5; - let pitch = (*last_mora.pitch() + ADJUST_PITCH).min(MAX_PITCH); + let pitch = (last_mora.pitch + ADJUST_PITCH).min(MAX_PITCH); - Mora::new( - mora_to_text(None, last_mora.vowel()), - None, - None, - last_mora.vowel().clone(), - FIX_VOWEL_LENGTH, + Mora { + text: mora_to_text(None, &last_mora.vowel), + consonant: None, + consonant_length: None, + vowel: last_mora.vowel.clone(), + vowel_length: FIX_VOWEL_LENGTH, pitch, - ) + } } - fn to_wav(wave: &[f32], audio_query: &AudioQuery) -> Vec { - let volume_scale = *audio_query.volume_scale(); - let output_stereo = *audio_query.output_stereo(); - let output_sampling_rate = *audio_query.output_sampling_rate(); - + fn to_wav( + wave: &[f32], + &AudioQuery { + volume_scale, + output_sampling_rate, + output_stereo, + .. + }: &AudioQuery, + ) -> Vec { // TODO: 44.1kHzなどの対応 let num_channels: u16 = if output_stereo { 2 } else { 1 }; @@ -509,41 +519,32 @@ pub(crate) mod blocking { let mut index = 0; let new_accent_phrases = accent_phrases .iter() - .map(|accent_phrase| { - AccentPhrase::new( - accent_phrase - .moras() - .iter() - .map(|mora| { - let new_mora = Mora::new( - mora.text().clone(), - mora.consonant().clone(), - mora.consonant().as_ref().map(|_| { - phoneme_length[vowel_indexes_data[index + 1] as usize - 1] - }), - mora.vowel().clone(), - phoneme_length[vowel_indexes_data[index + 1] as usize], - *mora.pitch(), - ); - index += 1; - new_mora - }) - .collect(), - *accent_phrase.accent(), - accent_phrase.pause_mora().as_ref().map(|pause_mora| { - let new_pause_mora = Mora::new( - pause_mora.text().clone(), - pause_mora.consonant().clone(), - *pause_mora.consonant_length(), - pause_mora.vowel().clone(), - phoneme_length[vowel_indexes_data[index + 1] as usize], - *pause_mora.pitch(), - ); + .map(|accent_phrase| AccentPhrase { + moras: accent_phrase + .moras + .iter() + .map(|mora| { + let new_mora = Mora { + consonant_length: mora.consonant.as_ref().map(|_| { + phoneme_length[vowel_indexes_data[index + 1] as usize - 1] + }), + vowel_length: phoneme_length + [vowel_indexes_data[index + 1] as usize], + ..mora.clone() + }; index += 1; - new_pause_mora - }), - *accent_phrase.is_interrogative(), - ) + new_mora + }) + .collect(), + pause_mora: accent_phrase.pause_mora.as_ref().map(|pause_mora| { + let new_pause_mora = Mora { + vowel_length: phoneme_length[vowel_indexes_data[index + 1] as usize], + ..pause_mora.clone() + }; + index += 1; + new_pause_mora + }), + ..accent_phrase.clone() }) .collect(); @@ -563,10 +564,10 @@ pub(crate) mod blocking { let mut base_start_accent_phrase_list = vec![0]; let mut base_end_accent_phrase_list = vec![0]; for accent_phrase in accent_phrases { - let mut accent = usize::from(*accent_phrase.accent() != 1); + let mut accent = usize::from(accent_phrase.accent != 1); create_one_accent_list(&mut base_start_accent_list, accent_phrase, accent as i32); - accent = *accent_phrase.accent() - 1; + accent = accent_phrase.accent - 1; create_one_accent_list(&mut base_end_accent_list, accent_phrase, accent as i32); create_one_accent_list(&mut base_start_accent_phrase_list, accent_phrase, 0); create_one_accent_list(&mut base_end_accent_phrase_list, accent_phrase, -1); @@ -625,39 +626,28 @@ pub(crate) mod blocking { let mut index = 0; let new_accent_phrases = accent_phrases .iter() - .map(|accent_phrase| { - AccentPhrase::new( - accent_phrase - .moras() - .iter() - .map(|mora| { - let new_mora = Mora::new( - mora.text().clone(), - mora.consonant().clone(), - *mora.consonant_length(), - mora.vowel().clone(), - *mora.vowel_length(), - f0_list[index + 1], - ); - index += 1; - new_mora - }) - .collect(), - *accent_phrase.accent(), - accent_phrase.pause_mora().as_ref().map(|pause_mora| { - let new_pause_mora = Mora::new( - pause_mora.text().clone(), - pause_mora.consonant().clone(), - *pause_mora.consonant_length(), - pause_mora.vowel().clone(), - *pause_mora.vowel_length(), - f0_list[index + 1], - ); + .map(|accent_phrase| AccentPhrase { + moras: accent_phrase + .moras + .iter() + .map(|mora| { + let new_mora = Mora { + pitch: f0_list[index + 1], + ..mora.clone() + }; index += 1; - new_pause_mora - }), - *accent_phrase.is_interrogative(), - ) + new_mora + }) + .collect(), + pause_mora: accent_phrase.pause_mora.as_ref().map(|pause_mora| { + let new_pause_mora = Mora { + pitch: f0_list[index + 1], + ..pause_mora.clone() + }; + index += 1; + new_pause_mora + }), + ..accent_phrase.clone() }) .collect(); @@ -670,17 +660,16 @@ pub(crate) mod blocking { ) { let mut one_accent_list: Vec = Vec::new(); - for (i, mora) in accent_phrase.moras().iter().enumerate() { + for (i, mora) in accent_phrase.moras.iter().enumerate() { let value = (i as i32 == point - || (point < 0 - && i == (accent_phrase.moras().len() as i32 + point) as usize)) + || (point < 0 && i == (accent_phrase.moras.len() as i32 + point) as usize)) .into(); one_accent_list.push(value); - if mora.consonant().is_some() { + if mora.consonant.is_some() { one_accent_list.push(value); } } - if accent_phrase.pause_mora().is_some() { + if accent_phrase.pause_mora.is_some() { one_accent_list.push(0); } accent_list.extend(one_accent_list) @@ -1036,10 +1025,10 @@ pub(crate) mod blocking { let mut phoneme_strings = vec!["pau".to_string()]; for mora in flatten_moras.iter() { - if let Some(consonant) = mora.consonant() { + if let Some(consonant) = &mora.consonant { phoneme_strings.push(consonant.clone()) } - phoneme_strings.push(mora.vowel().clone()); + phoneme_strings.push(mora.vowel.clone()); } phoneme_strings.push("pau".to_string()); @@ -1050,12 +1039,14 @@ pub(crate) mod blocking { fn to_flatten_moras(accent_phrases: &[AccentPhrase]) -> Vec { let mut flatten_moras = Vec::new(); - for accent_phrase in accent_phrases { - let moras = accent_phrase.moras(); + for AccentPhrase { + moras, pause_mora, .. + } in accent_phrases + { for mora in moras { flatten_moras.push(mora.clone()); } - if let Some(pause_mora) = accent_phrase.pause_mora() { + if let Some(pause_mora) = pause_mora { flatten_moras.push(pause_mora.clone()); } } @@ -1112,18 +1103,18 @@ pub(crate) mod blocking { impl AudioQuery { fn from_accent_phrases(accent_phrases: Vec) -> Self { let kana = create_kana(&accent_phrases); - Self::new( + Self { accent_phrases, - 1., - 0., - 1., - 1., - 0.1, - 0.1, - DEFAULT_SAMPLING_RATE, - false, - Some(kana), - ) + speed_scale: 1., + pitch_scale: 0., + intonation_scale: 1., + volume_scale: 1., + pre_phoneme_length: 0.1, + post_phoneme_length: 0.1, + output_sampling_rate: DEFAULT_SAMPLING_RATE, + output_stereo: false, + kana: Some(kana), + } } } } @@ -1594,41 +1585,39 @@ mod tests { .unwrap(); assert_eq!( - query.accent_phrases().len(), + query.accent_phrases.len(), expected_text_consonant_vowel_data.len() ); - for (accent_phrase, (text_consonant_vowel_slice, accent_pos)) in - std::iter::zip(query.accent_phrases(), expected_text_consonant_vowel_data) - { - assert_eq!( - accent_phrase.moras().len(), - text_consonant_vowel_slice.len() - ); - assert_eq!(accent_phrase.accent(), accent_pos); + for (accent_phrase, (text_consonant_vowel_slice, accent_pos)) in std::iter::zip( + query.accent_phrases, + expected_text_consonant_vowel_data.iter().copied(), + ) { + assert_eq!(accent_phrase.moras.len(), text_consonant_vowel_slice.len()); + assert_eq!(accent_phrase.accent, accent_pos); - for (mora, (text, consonant, vowel)) in - std::iter::zip(accent_phrase.moras(), *text_consonant_vowel_slice) - { - assert_eq!(mora.text(), text); + for (mora, (text, consonant, vowel)) in std::iter::zip( + accent_phrase.moras, + text_consonant_vowel_slice.iter().copied(), + ) { + assert_eq!(mora.text, text); // NOTE: 子音の長さが必ず非ゼロになるテストケースを想定している assert_ne!( - mora.consonant_length(), - &Some(0.), + mora.consonant_length, + Some(0.), "expected mora.consonant_length is not Some(0.0), but got Some(0.0)." ); - assert_eq!(mora.consonant(), &Some(consonant.to_string())); - assert_eq!(mora.vowel(), vowel); + assert_eq!(mora.consonant, Some(consonant.to_string())); + assert_eq!(mora.vowel, vowel); // NOTE: 母音の長さが必ず非ゼロになるテストケースを想定している assert_ne!( - mora.vowel_length(), - &0., + mora.vowel_length, 0., "expected mora.vowel_length is not 0.0, but got 0.0." ); } } - assert_eq!(query.kana().as_deref(), Some(expected_kana_text)); + assert_eq!(query.kana.as_deref(), Some(expected_kana_text)); } #[rstest] @@ -1675,31 +1664,29 @@ mod tests { expected_text_consonant_vowel_data.len() ); - for (accent_phrase, (text_consonant_vowel_slice, accent_pos)) in - std::iter::zip(accent_phrases, expected_text_consonant_vowel_data) - { - assert_eq!( - accent_phrase.moras().len(), - text_consonant_vowel_slice.len() - ); - assert_eq!(accent_phrase.accent(), accent_pos); + for (accent_phrase, (text_consonant_vowel_slice, accent_pos)) in std::iter::zip( + accent_phrases, + expected_text_consonant_vowel_data.iter().copied(), + ) { + assert_eq!(accent_phrase.moras.len(), text_consonant_vowel_slice.len()); + assert_eq!(accent_phrase.accent, accent_pos); - for (mora, (text, consonant, vowel)) in - std::iter::zip(accent_phrase.moras(), *text_consonant_vowel_slice) - { - assert_eq!(mora.text(), text); + for (mora, (text, consonant, vowel)) in std::iter::zip( + accent_phrase.moras, + text_consonant_vowel_slice.iter().copied(), + ) { + assert_eq!(mora.text, text); // NOTE: 子音の長さが必ず非ゼロになるテストケースを想定している assert_ne!( - mora.consonant_length(), - &Some(0.), + mora.consonant_length, + Some(0.), "expected mora.consonant_length is not Some(0.0), but got Some(0.0)." ); - assert_eq!(mora.consonant(), &Some(consonant.to_string())); - assert_eq!(mora.vowel(), vowel); + assert_eq!(mora.consonant, Some(consonant.to_string())); + assert_eq!(mora.vowel, vowel); // NOTE: 母音の長さが必ず非ゼロになるテストケースを想定している assert_ne!( - mora.vowel_length(), - &0., + mora.vowel_length, 0., "expected mora.vowel_length is not 0.0, but got 0.0." ); } @@ -1736,36 +1723,35 @@ mod tests { // AccentPhraseの pause_mora に期待する値をテスト assert!( - accent_phrases[0].pause_mora().is_some(), - "accent_phrases[0].pause_mora() is None" + accent_phrases[0].pause_mora.is_some(), + "accent_phrases[0].pause_mora is None" ); assert!( - accent_phrases[1].pause_mora().is_some(), - "accent_phrases[1].pause_mora() is None" + accent_phrases[1].pause_mora.is_some(), + "accent_phrases[1].pause_mora is None" ); assert!( - accent_phrases[2].pause_mora().is_some(), - "accent_phrases[2].pause_mora() is None" + accent_phrases[2].pause_mora.is_some(), + "accent_phrases[2].pause_mora is None" ); assert!( - accent_phrases[3].pause_mora().is_some(), - "accent_phrases[3].pause_mora() is None" + accent_phrases[3].pause_mora.is_some(), + "accent_phrases[3].pause_mora is None" ); assert!( - accent_phrases[4].pause_mora().is_none(), // 文末の句読点は削除される - "accent_phrases[4].pause_mora() is not None" + accent_phrases[4].pause_mora.is_none(), // 文末の句読点は削除される + "accent_phrases[4].pause_mora is not None" ); for accent_phrase in accent_phrases.iter().take(4) { - let pause_mora = accent_phrase.pause_mora().clone().unwrap(); - assert_eq!(pause_mora.text(), "、"); - assert_eq!(pause_mora.consonant(), &None); - assert_eq!(pause_mora.consonant_length(), &None); - assert_eq!(pause_mora.vowel(), "pau"); + let pause_mora = accent_phrase.pause_mora.clone().unwrap(); + assert_eq!(pause_mora.text, "、"); + assert_eq!(pause_mora.consonant, None); + assert_eq!(pause_mora.consonant_length, None); + assert_eq!(pause_mora.vowel, "pau"); assert_ne!( - pause_mora.vowel_length(), - &0.0, - "pause_mora.vowel_length() should not be 0.0" + pause_mora.vowel_length, 0.0, + "pause_mora.vowel_length should not be 0.0", ); } } @@ -1805,9 +1791,9 @@ mod tests { any_mora_param_changed( &accent_phrases, &modified_accent_phrases, - Mora::vowel_length + |Mora { vowel_length, .. }| vowel_length, ), - "mora_length() does not work: mora.vowel_length() is not changed." + "mora_length() does not work: mora.vowel_length is not changed.", ); } @@ -1843,8 +1829,12 @@ mod tests { // NOTE: 一つでも音高が変わっていれば、動作しているとみなす assert!( - any_mora_param_changed(&accent_phrases, &modified_accent_phrases, Mora::pitch), - "mora_pitch() does not work: mora.pitch() is not changed." + any_mora_param_changed( + &accent_phrases, + &modified_accent_phrases, + |Mora { pitch, .. }| pitch + ), + "mora_pitch() does not work: mora.pitch is not changed.", ); } @@ -1880,17 +1870,21 @@ mod tests { // NOTE: 一つでも音高が変わっていれば、動作しているとみなす assert!( - any_mora_param_changed(&accent_phrases, &modified_accent_phrases, Mora::pitch), - "mora_data() does not work: mora.pitch() is not changed." + any_mora_param_changed( + &accent_phrases, + &modified_accent_phrases, + |Mora { pitch, .. }| pitch, + ), + "mora_data() does not work: mora.pitch is not changed.", ); // NOTE: 一つでも母音の長さが変わっていれば、動作しているとみなす assert!( any_mora_param_changed( &accent_phrases, &modified_accent_phrases, - Mora::vowel_length + |Mora { vowel_length, .. }| vowel_length, ), - "mora_data() does not work: mora.vowel_length() is not changed." + "mora_data() does not work: mora.vowel_length is not changed.", ); } @@ -1900,7 +1894,7 @@ mod tests { param: fn(&Mora) -> &T, ) -> bool { std::iter::zip(before, after) - .flat_map(move |(before, after)| std::iter::zip(before.moras(), after.moras())) + .flat_map(|(before, after)| std::iter::zip(&before.moras, &after.moras)) .any(|(before, after)| param(before) != param(after)) } diff --git a/crates/voicevox_core/src/user_dict/word.rs b/crates/voicevox_core/src/user_dict/word.rs index 7ed98a949..96a47dcc4 100644 --- a/crates/voicevox_core/src/user_dict/word.rs +++ b/crates/voicevox_core/src/user_dict/word.rs @@ -5,25 +5,24 @@ use crate::{ priority2cost, MAX_PRIORITY, MIN_PRIORITY, PART_OF_SPEECH_DETAIL, }, }; -use derive_getters::Getters; use once_cell::sync::Lazy; use regex::Regex; use serde::{de::Error as _, Deserialize, Serialize}; use std::ops::RangeToInclusive; /// ユーザー辞書の単語。 -#[derive(Clone, Debug, Getters, Serialize)] +#[derive(Clone, Debug, Serialize)] pub struct UserDictWord { /// 単語の表記。 - pub surface: String, + surface: String, /// 単語の読み。 - pub pronunciation: String, + pronunciation: String, /// アクセント型。 - pub accent_type: usize, + accent_type: usize, /// 単語の種類。 - pub word_type: UserDictWordType, + word_type: UserDictWordType, /// 単語の優先度。 - pub priority: u32, + priority: u32, /// モーラ数。 mora_count: usize, @@ -127,6 +126,31 @@ impl UserDictWord { mora_count, }) } + + /// 単語の表記。 + pub fn surface(&self) -> &str { + &self.surface + } + + /// 単語の読み。 + pub fn pronunciation(&self) -> &str { + &self.pronunciation + } + + /// アクセント型。 + pub fn accent_type(&self) -> usize { + self.accent_type + } + + /// 単語の種類。 + pub fn word_type(&self) -> UserDictWordType { + self.word_type + } + + /// 単語の優先度。 + pub fn priority(&self) -> u32 { + self.priority + } } /// カタカナの文字列が発音として有効かどうかを判定する。 @@ -203,7 +227,7 @@ pub(crate) fn to_zenkaku(surface: &str) -> String { .collect() } /// ユーザー辞書の単語の種類。 -#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Hash)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize, Hash)] #[serde(rename_all = "SCREAMING_SNAKE_CASE")] pub enum UserDictWordType { /// 固有名詞。 diff --git a/crates/voicevox_core/src/voice_model.rs b/crates/voicevox_core/src/voice_model.rs index f5e862854..027747ab7 100644 --- a/crates/voicevox_core/src/voice_model.rs +++ b/crates/voicevox_core/src/voice_model.rs @@ -3,9 +3,7 @@ //! VVM ファイルの定義と形式は[ドキュメント](../../../docs/vvm.md)を参照。 use anyhow::anyhow; -use derive_getters::Getters; use derive_more::From; -use derive_new::new; use easy_ext::ext; use enum_map::EnumMap; use itertools::Itertools as _; @@ -41,15 +39,16 @@ pub(crate) type ModelBytesWithInnerVoiceIdsByDomain = Hash, PartialOrd, Deserialize, - new, - Getters, derive_more::Display, Debug, From, )] -#[serde(transparent)] -pub struct VoiceModelId { - raw_voice_model_id: RawVoiceModelId, +pub struct VoiceModelId(RawVoiceModelId); + +impl VoiceModelId { + pub fn raw_voice_model_id(self) -> RawVoiceModelId { + self.0 + } } // FIXME: "header"といいつつ、VVMのファイルパスを持っている状態になっている。 @@ -106,9 +105,8 @@ impl ManifestDomains { fn check_acceptable(&self, metas: &[SpeakerMeta]) -> std::result::Result<(), StyleType> { let err = metas .iter() - .flat_map(SpeakerMeta::styles) - .map(StyleMeta::r#type) - .copied() + .flat_map(|SpeakerMeta { styles, .. }| styles) + .map(|StyleMeta { r#type, .. }| *r#type) .unique() .find(|&style_type| !self.accepts(style_type)); @@ -153,6 +151,7 @@ pub(crate) mod blocking { use ouroboros::self_referencing; use rayon::iter::{IntoParallelIterator as _, ParallelIterator as _}; use serde::de::DeserializeOwned; + use uuid::Uuid; use crate::{ error::{LoadModelError, LoadModelErrorKind, LoadModelResult}, @@ -288,8 +287,8 @@ pub(crate) mod blocking { #[ext(IdRef)] pub impl VoiceModel { - fn id_ref(&self) -> &VoiceModelId { - &self.header.manifest.id + fn id_ref(&self) -> &Uuid { + &self.header.manifest.id.0 } } } diff --git a/crates/voicevox_core_c_api/src/compatible_engine.rs b/crates/voicevox_core_c_api/src/compatible_engine.rs index bd66210e2..70fa83710 100644 --- a/crates/voicevox_core_c_api/src/compatible_engine.rs +++ b/crates/voicevox_core_c_api/src/compatible_engine.rs @@ -51,8 +51,8 @@ static VOICE_MODEL_SET: Lazy = Lazy::new(|| { let mut style_model_map = BTreeMap::default(); for vvm in all_vvms.iter() { for meta in vvm.metas().iter() { - for style in meta.styles().iter() { - style_model_map.insert(*style.id(), vvm.id()); + for style in meta.styles.iter() { + style_model_map.insert(style.id, vvm.id()); } } } diff --git a/crates/voicevox_core_c_api/src/lib.rs b/crates/voicevox_core_c_api/src/lib.rs index 3904698fc..38c06cd4f 100644 --- a/crates/voicevox_core_c_api/src/lib.rs +++ b/crates/voicevox_core_c_api/src/lib.rs @@ -449,7 +449,7 @@ pub unsafe extern "C" fn voicevox_voice_model_new_from_path( #[no_mangle] pub extern "C" fn voicevox_voice_model_id(model: &VoicevoxVoiceModel) -> VoicevoxVoiceModelId<'_> { init_logger_once(); - model.model.id_ref().raw_voice_model_id().as_bytes() + model.model.id_ref().as_bytes() } /// ::VoicevoxVoiceModel からメタ情報を取得する。 @@ -1281,9 +1281,9 @@ pub extern "C" fn voicevox_user_dict_word_make( VoicevoxUserDictWord { surface, pronunciation, - accent_type: UserDictWord::default().accent_type, - word_type: UserDictWord::default().word_type.into(), - priority: UserDictWord::default().priority, + accent_type: UserDictWord::default().accent_type(), + word_type: UserDictWord::default().word_type().into(), + priority: UserDictWord::default().priority(), } } diff --git a/crates/voicevox_core_java_api/src/voice_model.rs b/crates/voicevox_core_java_api/src/voice_model.rs index 546ab9bf6..1ea90ba8c 100644 --- a/crates/voicevox_core_java_api/src/voice_model.rs +++ b/crates/voicevox_core_java_api/src/voice_model.rs @@ -35,7 +35,7 @@ unsafe extern "system" fn Java_jp_hiroshiba_voicevoxcore_VoiceModel_rsGetId<'loc .get_rust_field::<_, _, Arc>(&this, "handle")? .clone(); - let id = env.new_uuid(*internal.id().raw_voice_model_id())?; + let id = env.new_uuid(internal.id().raw_voice_model_id())?; Ok(id.into_raw()) }) diff --git a/crates/voicevox_core_python_api/src/lib.rs b/crates/voicevox_core_python_api/src/lib.rs index e301f1042..001df0713 100644 --- a/crates/voicevox_core_python_api/src/lib.rs +++ b/crates/voicevox_core_python_api/src/lib.rs @@ -173,7 +173,7 @@ mod blocking { #[getter] fn id(&self, py: Python<'_>) -> PyResult { - let id = *self.model.id().raw_voice_model_id(); + let id = self.model.id().raw_voice_model_id(); crate::convert::to_py_uuid(py, id) } @@ -676,7 +676,7 @@ mod asyncio { #[getter] fn id(&self, py: Python<'_>) -> PyResult { - let id = *self.model.id().raw_voice_model_id(); + let id = self.model.id().raw_voice_model_id(); crate::convert::to_py_uuid(py, id) }