Skip to content

Commit

Permalink
metas出力時に話者情報をマージする
Browse files Browse the repository at this point in the history
  • Loading branch information
qryxip committed Jan 21, 2024
1 parent 4e13bca commit 7d0aa00
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 19 deletions.
2 changes: 1 addition & 1 deletion crates/voicevox_core/src/__internal/interop.rs
Original file line number Diff line number Diff line change
@@ -1 +1 @@
pub use crate::synthesizer::blocking::PerformInference;
pub use crate::{metas::merge as merge_metas, synthesizer::blocking::PerformInference};
44 changes: 27 additions & 17 deletions crates/voicevox_core/src/infer/status.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use crate::{
error::{ErrorRepr, LoadModelError, LoadModelErrorKind, LoadModelResult},
infer::{InferenceOperation, ParamInfo},
manifest::ModelInnerId,
metas::{SpeakerMeta, StyleId, StyleMeta, VoiceModelMeta},
metas::{self, SpeakerMeta, StyleId, StyleMeta, VoiceModelMeta},
voice_model::{VoiceModelHeader, VoiceModelId},
Result,
};
Expand Down Expand Up @@ -130,11 +130,7 @@ struct LoadedModel<R: InferenceRuntime, D: InferenceDomain> {

impl<R: InferenceRuntime, D: InferenceDomain> LoadedModels<R, D> {
fn metas(&self) -> VoiceModelMeta {
self.0
.values()
.flat_map(|LoadedModel { metas, .. }| metas)
.cloned()
.collect()
metas::merge(self.0.values().flat_map(|LoadedModel { metas, .. }| metas))
}

fn ids_for(&self, style_id: StyleId) -> Result<(VoiceModelId, ModelInnerId)> {
Expand Down Expand Up @@ -184,20 +180,33 @@ impl<R: InferenceRuntime, D: InferenceDomain> LoadedModels<R, D> {
///
/// # Errors
///
/// 音声モデルIDかスタイルIDが`model_header`と重複するとき、エラーを返す。
/// 次の場合にエラーを返す。
///
/// - 音声モデルIDかスタイルIDが`model_header`と重複するとき
/// - 同じ`speaker_uuid`で、スタイル以外でプロパティが異なっている話者があるとき
fn ensure_acceptable(&self, model_header: &VoiceModelHeader) -> LoadModelResult<()> {
let loaded = self.styles();
let external = model_header
.metas
.iter()
.flat_map(|speaker| speaker.styles());

let error = |context| LoadModelError {
path: model_header.path.clone(),
context,
source: None,
};

let loaded = self.speakers();
let external = model_header.metas.iter();
if let Some((_loaded, _external)) =
iproduct!(loaded, external).find(|(loaded, external)| {
loaded.speaker_uuid() == external.speaker_uuid()
&& !loaded.eq_except_styles(external)
})
{
todo!("same `speaker_uuid` but different properties");
}

let loaded = self.styles();
let external = model_header
.metas
.iter()
.flat_map(|speaker| speaker.styles());
if self.0.contains_key(&model_header.id) {
return Err(error(LoadModelErrorKind::ModelAlreadyLoaded {
id: model_header.id.clone(),
Expand Down Expand Up @@ -242,11 +251,12 @@ impl<R: InferenceRuntime, D: InferenceDomain> LoadedModels<R, D> {
Ok(())
}

fn speakers(&self) -> impl Iterator<Item = &SpeakerMeta> {
self.0.values().flat_map(|LoadedModel { metas, .. }| metas)
}

fn styles(&self) -> impl Iterator<Item = &StyleMeta> {
self.0
.values()
.flat_map(|LoadedModel { metas, .. }| metas)
.flat_map(|speaker| speaker.styles())
self.speakers().flat_map(|speaker| speaker.styles())
}
}

Expand Down
41 changes: 41 additions & 0 deletions crates/voicevox_core/src/metas.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,29 @@ use std::fmt::Display;

use derive_getters::Getters;
use derive_new::new;
use itertools::Itertools as _;
use serde::{Deserialize, Serialize};

pub fn merge<'a>(metas: impl IntoIterator<Item = &'a SpeakerMeta>) -> Vec<SpeakerMeta> {
metas
.into_iter()
.into_grouping_map_by(|speaker| &speaker.speaker_uuid)
.aggregate::<_, SpeakerMeta>(|acc, _, speaker| {
Some(
acc.map(|mut acc| {
acc.styles.extend(speaker.styles.clone());
acc
})
.unwrap_or_else(|| speaker.clone()),
)
})
.into_values()
.sorted_by_key(|SpeakerMeta { styles, .. }| {
styles.iter().map(|&StyleMeta { id, .. }| id).min()
})
.collect()
}

/// [`StyleId`]の実体。
///
/// [`StyleId`]: StyleId
Expand Down Expand Up @@ -67,6 +88,26 @@ pub struct SpeakerMeta {
speaker_uuid: String,
}

impl SpeakerMeta {
pub(crate) fn eq_except_styles(&self, other: &Self) -> bool {
let Self {
name: name1,
styles: _,
version: version1,
speaker_uuid: speaker_uuid1,
} = self;

let Self {
name: name2,
styles: _,
version: version2,
speaker_uuid: speaker_uuid2,
} = other;

(name1, version1, speaker_uuid1) == (name2, version2, speaker_uuid2)
}
}

/// **スタイル**(_style_)のメタ情報。
#[derive(Deserialize, Serialize, Getters, Clone)]
pub struct StyleMeta {
Expand Down
4 changes: 3 additions & 1 deletion crates/voicevox_core_c_api/src/compatible_engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,9 @@ static VOICE_MODEL_SET: Lazy<VoiceModelSet> = Lazy::new(|| {
.iter()
.map(|vvm| (vvm.id().clone(), vvm.clone()))
.collect();
let metas: Vec<_> = all_vvms.iter().flat_map(|vvm| vvm.metas()).collect();
let metas = voicevox_core::__internal::interop::merge_metas(
all_vvms.iter().flat_map(|vvm| vvm.metas()),
);
let mut style_model_map = BTreeMap::default();
for vvm in all_vvms.iter() {
for meta in vvm.metas().iter() {
Expand Down

0 comments on commit 7d0aa00

Please sign in to comment.