diff --git a/crates/voicevox_core/src/metas.rs b/crates/voicevox_core/src/metas.rs index 97c3922c7..7f7b7b4e1 100644 --- a/crates/voicevox_core/src/metas.rs +++ b/crates/voicevox_core/src/metas.rs @@ -111,6 +111,9 @@ pub struct SpeakerMeta { pub version: StyleVersion, /// 話者のUUID。 pub speaker_uuid: String, + /// 話者の対応機能。 + #[serde(default)] + pub supported_features: SpeakerSupportedFeatures, /// 話者の順番。 /// /// `SpeakerMeta`の列は、この値に対して昇順に並んでいるべきである。 @@ -127,6 +130,7 @@ impl SpeakerMeta { styles: _, version: version1, speaker_uuid: speaker_uuid1, + supported_features: supported_features1, order: order1, } = self; @@ -135,6 +139,7 @@ impl SpeakerMeta { styles: _, version: version2, speaker_uuid: speaker_uuid2, + supported_features: supported_features2, order: order2, } = other; @@ -144,6 +149,12 @@ impl SpeakerMeta { warn_diff(speaker_uuid1, "name", name1, name2); warn_diff(speaker_uuid1, "version", version1, version2); + warn_diff( + speaker_uuid1, + "supported_features", + supported_features1, + supported_features2, + ); warn_diff(speaker_uuid1, "order", order1, order2); fn warn_diff( @@ -207,6 +218,29 @@ pub enum StyleType { Sing, } +/// 話者の対応機能。 +#[derive(Default, Deserialize, Serialize, Clone, PartialEq, Debug)] +pub struct SpeakerSupportedFeatures { + /// モーフィング機能への対応。 + #[serde(default)] + pub permitted_synthesis_morphing: SpeakerSupportPermittedSynthesisMorphing, +} + +/// モーフィング機能への対応。 +#[derive(Deserialize, Serialize, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug)] +#[serde(rename_all = "SCREAMING_SNAKE_CASE")] +pub enum SpeakerSupportPermittedSynthesisMorphing { + /// 全て許可。 + All, + + /// 同じ話者内でのみ許可。 + SelfOnly, + + /// 全て禁止。 + #[default] + Nothing, +} + #[cfg(test)] mod tests { use std::sync::LazyLock; @@ -229,6 +263,9 @@ mod tests { ], "version": "0.0.0", "speaker_uuid": "f34ab151-c0f5-4e0a-9ad2-51ce30dba24d", + "supported_features": { + "permitted_synthesis_morphing": "SELF_ONLY" + }, "order": 1 }, { @@ -243,6 +280,9 @@ mod tests { ], "version": "0.0.0", "speaker_uuid": "d6fd707c-a451-48e9-8f00-fe9ee3bf6264", + "supported_features": { + "permitted_synthesis_morphing": "SELF_ONLY" + }, "order": 0 }, { @@ -263,6 +303,9 @@ mod tests { ], "version": "0.0.0", "speaker_uuid": "d6fd707c-a451-48e9-8f00-fe9ee3bf6264", + "supported_features": { + "permitted_synthesis_morphing": "SELF_ONLY" + }, "order": 0 } ]) @@ -294,6 +337,9 @@ mod tests { ], "version": "0.0.0", "speaker_uuid": "d6fd707c-a451-48e9-8f00-fe9ee3bf6264", + "supported_features": { + "permitted_synthesis_morphing": "SELF_ONLY" + }, "order": 0 }, { @@ -308,6 +354,9 @@ mod tests { ], "version": "0.0.0", "speaker_uuid": "f34ab151-c0f5-4e0a-9ad2-51ce30dba24d", + "supported_features": { + "permitted_synthesis_morphing": "SELF_ONLY" + }, "order": 1 } ]) diff --git a/crates/voicevox_core_c_api/tests/e2e/snapshots.toml b/crates/voicevox_core_c_api/tests/e2e/snapshots.toml index 87a704af4..d3d2fc6fb 100644 --- a/crates/voicevox_core_c_api/tests/e2e/snapshots.toml +++ b/crates/voicevox_core_c_api/tests/e2e/snapshots.toml @@ -13,6 +13,9 @@ metas = ''' ], "version": "0.0.1", "speaker_uuid": "574bc678-8370-44be-b941-08e46e7b47d7", + "supported_features": { + "permitted_synthesis_morphing": "NOTHING" + }, "order": null }, { @@ -27,6 +30,9 @@ metas = ''' ], "version": "0.0.1", "speaker_uuid": "dd9ccd75-75f6-40ce-a3db-960cbed2e905", + "supported_features": { + "permitted_synthesis_morphing": "ALL" + }, "order": null }, { @@ -47,6 +53,9 @@ metas = ''' ], "version": "0.0.1", "speaker_uuid": "5d3d9aa9-88e5-4a96-8ef7-f13a3cad1cb3", + "supported_features": { + "permitted_synthesis_morphing": "SELF_ONLY" + }, "order": null }, { @@ -67,6 +76,9 @@ metas = ''' ], "version": "0.0.1", "speaker_uuid": "32478dc2-4c8b-44f7-b041-c836e0df6d56", + "supported_features": { + "permitted_synthesis_morphing": "NOTHING" + }, "order": null } ]''' @@ -159,6 +171,9 @@ metas = ''' ], "version": "0.0.1", "speaker_uuid": "574bc678-8370-44be-b941-08e46e7b47d7", + "supported_features": { + "permitted_synthesis_morphing": "NOTHING" + }, "order": null }, { @@ -173,6 +188,9 @@ metas = ''' ], "version": "0.0.1", "speaker_uuid": "dd9ccd75-75f6-40ce-a3db-960cbed2e905", + "supported_features": { + "permitted_synthesis_morphing": "ALL" + }, "order": null }, { @@ -193,6 +211,9 @@ metas = ''' ], "version": "0.0.1", "speaker_uuid": "5d3d9aa9-88e5-4a96-8ef7-f13a3cad1cb3", + "supported_features": { + "permitted_synthesis_morphing": "SELF_ONLY" + }, "order": null }, { @@ -213,6 +234,9 @@ metas = ''' ], "version": "0.0.1", "speaker_uuid": "32478dc2-4c8b-44f7-b041-c836e0df6d56", + "supported_features": { + "permitted_synthesis_morphing": "NOTHING" + }, "order": null } ]''' diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/hiroshiba/voicevoxcore/SpeakerMeta.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/hiroshiba/voicevoxcore/SpeakerMeta.java index c43d32a8e..a856dd4c5 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/hiroshiba/voicevoxcore/SpeakerMeta.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/hiroshiba/voicevoxcore/SpeakerMeta.java @@ -31,6 +31,12 @@ public class SpeakerMeta { @Nonnull public final String version; + /** 話者の対応機能。 */ + @SerializedName("supported_features") + @Expose + @Nonnull + public final SpeakerSupportedFeatures supportedFeatures; + /** * 話者の順番。 * @@ -48,6 +54,7 @@ private SpeakerMeta() { this.styles = new StyleMeta[0]; this.speakerUuid = ""; this.version = ""; + this.supportedFeatures = new SpeakerSupportedFeatures(); this.order = null; } } diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/hiroshiba/voicevoxcore/SpeakerSupportPermittedSynthesisMorphing.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/hiroshiba/voicevoxcore/SpeakerSupportPermittedSynthesisMorphing.java new file mode 100644 index 000000000..826b56a8d --- /dev/null +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/hiroshiba/voicevoxcore/SpeakerSupportPermittedSynthesisMorphing.java @@ -0,0 +1,18 @@ +package jp.hiroshiba.voicevoxcore; + +import com.google.gson.annotations.Expose; + +/** モーフィング機能への対応。 */ +public enum SpeakerSupportPermittedSynthesisMorphing { + /** 全て許可。 */ + @Expose + ALL, + + /** 同じ話者内でのみ許可。 */ + @Expose + SELF_ONLY, + + /** 全て禁止。 */ + @Expose + NOTHING, +} diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/hiroshiba/voicevoxcore/SpeakerSupportedFeatures.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/hiroshiba/voicevoxcore/SpeakerSupportedFeatures.java new file mode 100644 index 000000000..5a94171f3 --- /dev/null +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/hiroshiba/voicevoxcore/SpeakerSupportedFeatures.java @@ -0,0 +1,18 @@ +package jp.hiroshiba.voicevoxcore; + +import com.google.gson.annotations.Expose; +import com.google.gson.annotations.SerializedName; +import jakarta.annotation.Nonnull; + +/** 話者の対応機能。 */ +public class SpeakerSupportedFeatures { + /** モーフィング機能への対応。 */ + @SerializedName("permitted_synthesis_morphing") + @Expose + @Nonnull + SpeakerSupportPermittedSynthesisMorphing permittedSynthesisMorphing; + + SpeakerSupportedFeatures() { + this.permittedSynthesisMorphing = SpeakerSupportPermittedSynthesisMorphing.NOTHING; + } +} diff --git a/crates/voicevox_core_python_api/python/voicevox_core/_models.py b/crates/voicevox_core_python_api/python/voicevox_core/_models.py index 68359bf18..6df5045fe 100644 --- a/crates/voicevox_core_python_api/python/voicevox_core/_models.py +++ b/crates/voicevox_core_python_api/python/voicevox_core/_models.py @@ -72,6 +72,29 @@ class StyleMeta: """ +class SpeakerSupportPermittedSynthesisMorphing(str, Enum): + """モーフィング機能への対応。""" + + ALL = "ALL" + """全て許可。""" + + SELF_ONLY = "SELF_ONLY" + """同じ話者内でのみ許可。""" + + NOTHING = "NOTHING" + """全て禁止。""" + + +@pydantic.dataclasses.dataclass +class SpeakerSupportedFeatures: + """話者の対応機能。""" + + permitted_synthesis_morphing: SpeakerSupportPermittedSynthesisMorphing = ( + SpeakerSupportPermittedSynthesisMorphing.NOTHING + ) + """モーフィング機能への対応。""" + + @pydantic.dataclasses.dataclass class SpeakerMeta: """**話者** (*speaker*)のメタ情報。""" @@ -88,6 +111,11 @@ class SpeakerMeta: version: StyleVersion """話者のUUID。""" + supported_features: SpeakerSupportedFeatures = dataclasses.field( + default_factory=SpeakerSupportedFeatures, + ) + """話者の対応機能。""" + order: Optional[int] = None """ 話者の順番。 diff --git a/model/sample.vvm/metas.json b/model/sample.vvm/metas.json index e27a015dd..8909bc9c7 100644 --- a/model/sample.vvm/metas.json +++ b/model/sample.vvm/metas.json @@ -19,7 +19,10 @@ } ], "speaker_uuid": "dd9ccd75-75f6-40ce-a3db-960cbed2e905", - "version": "0.0.1" + "version": "0.0.1", + "supported_features": { + "permitted_synthesis_morphing": "ALL" + } }, { "name": "dummy3", @@ -34,7 +37,10 @@ } ], "speaker_uuid": "5d3d9aa9-88e5-4a96-8ef7-f13a3cad1cb3", - "version": "0.0.1" + "version": "0.0.1", + "supported_features": { + "permitted_synthesis_morphing": "SELF_ONLY" + } }, { "name": "dummy4",