From 8ccac1bf949c877e2efcd835227ca9e9ea26d609 Mon Sep 17 00:00:00 2001 From: yamachu Date: Mon, 25 May 2026 13:36:33 +0900 Subject: [PATCH 1/5] Update submodule --- binding/voicevox_core | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/binding/voicevox_core b/binding/voicevox_core index cdb9ab6..72dde0a 160000 --- a/binding/voicevox_core +++ b/binding/voicevox_core @@ -1 +1 @@ -Subproject commit cdb9ab6e3c2fe6421d20af3fd2a476878ecf79c0 +Subproject commit 72dde0a885e91f94dff0de7377b1851a809eefa9 From 78bf8a7df86779f7892b3f9d05e6ad3ad61e9f8c Mon Sep 17 00:00:00 2001 From: yamachu Date: Mon, 25 May 2026 14:03:24 +0900 Subject: [PATCH 2/5] =?UTF-8?q?make=20generate=E3=81=AEhash=20replace?= =?UTF-8?q?=E3=81=8C=E4=B8=80=E9=83=A8=E7=8A=B6=E6=85=8B=E3=81=A7=E5=8B=95?= =?UTF-8?q?=E3=81=8B=E3=81=AA=E3=81=84=E7=8A=B6=E6=85=8B=E3=81=AA=E3=81=AE?= =?UTF-8?q?=E3=81=A7=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- binding/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/binding/Makefile b/binding/Makefile index 1af7646..dbdee69 100644 --- a/binding/Makefile +++ b/binding/Makefile @@ -5,8 +5,8 @@ generate: $(MAKE) replace-hash replace-hash: - $(eval VERSION := $(shell cat ../.git/modules/binding/voicevox_core/HEAD)) - $(shell sed -i.bak 's/.*<\/VoicevoxCoreCommitHash>/$(VERSION)<\/VoicevoxCoreCommitHash>/' ../src/VoicevoxCoreSharp.Core/VoicevoxCoreSharp.Core.Metas.props) + $(eval VERSION := $(shell git -C voicevox_core rev-parse HEAD)) + $(shell sed -i.bak 's|.*|$(VERSION)|' ../src/VoicevoxCoreSharp.Core/VoicevoxCoreSharp.Core.Metas.props) build/dev-library: cd voicevox_core; cargo build --release -p voicevox_core_c_api --features load-onnxruntime -F voicevox_core/buildtime-download-onnxruntime From 35339febf16361858f8663588b47625e7bef6a8d Mon Sep 17 00:00:00 2001 From: yamachu Date: Mon, 25 May 2026 14:03:36 +0900 Subject: [PATCH 3/5] make generate --- .../Runtime/Script/Native/CoreUnsafe.g.cs | 25 ++++++++++++++++++- .../Native/CoreUnsafe.g.cs | 25 ++++++++++++++++++- .../VoicevoxCoreSharp.Core.Metas.props | 2 +- 3 files changed, 49 insertions(+), 3 deletions(-) diff --git a/src/VoicevoxCoreSharp.Core.Unity/Runtime/Script/Native/CoreUnsafe.g.cs b/src/VoicevoxCoreSharp.Core.Unity/Runtime/Script/Native/CoreUnsafe.g.cs index c77b3f7..4701e37 100644 --- a/src/VoicevoxCoreSharp.Core.Unity/Runtime/Script/Native/CoreUnsafe.g.cs +++ b/src/VoicevoxCoreSharp.Core.Unity/Runtime/Script/Native/CoreUnsafe.g.cs @@ -535,18 +535,28 @@ internal static unsafe partial class CoreUnsafe [DllImport(__DllName, EntryPoint = "voicevox_synthesizer_delete", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] internal static extern void voicevox_synthesizer_delete(VoicevoxSynthesizer* synthesizer); + /// + /// デフォルトの `voicevox_synthesizer_load_voice_model` のオプションを生成する + /// @return デフォルト値が設定された `voicevox_synthesizer_load_voice_model` のオプション + /// + /// \no-orig-impl{voicevox_make_default_load_voice_model_options} + /// + [DllImport(__DllName, EntryPoint = "voicevox_make_default_load_voice_model_options", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + internal static extern VoicevoxLoadVoiceModelOptions voicevox_make_default_load_voice_model_options(); + /// /// 音声モデルを読み込む。 /// /// @param [in] synthesizer 音声シンセサイザ /// @param [in] model 音声モデル + /// @param [in] options オプション /// /// @returns 結果コード /// /// \orig-impl{voicevox_synthesizer_load_voice_model} /// [DllImport(__DllName, EntryPoint = "voicevox_synthesizer_load_voice_model", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] - internal static extern VoicevoxResultCode voicevox_synthesizer_load_voice_model(VoicevoxSynthesizer* synthesizer, VoicevoxVoiceModelFile* model); + internal static extern VoicevoxResultCode voicevox_synthesizer_load_voice_model(VoicevoxSynthesizer* synthesizer, VoicevoxVoiceModelFile* model, VoicevoxLoadVoiceModelOptions options); /// /// 音声モデルの読み込みを解除する。 @@ -1374,6 +1384,12 @@ internal unsafe partial struct VoicevoxSynthesizer { } + [StructLayout(LayoutKind.Sequential)] + internal unsafe partial struct VoicevoxLoadVoiceModelOptions + { + public VoicevoxOnExistingVoiceModelId on_existing; + } + [StructLayout(LayoutKind.Sequential)] internal unsafe partial struct VoicevoxSynthesisOptions { @@ -1437,6 +1453,13 @@ internal enum VoicevoxResultCode : int VOICEVOX_RESULT_INCOMPATIBLE_QUERIES_ERROR = 35, } + internal enum VoicevoxOnExistingVoiceModelId : int + { + VOICEVOX_ON_EXISTING_VOICE_MODEL_ID_ERROR = 0, + VOICEVOX_ON_EXISTING_VOICE_MODEL_ID_RELOAD = 1, + VOICEVOX_ON_EXISTING_VOICE_MODEL_ID_SKIP = 2, + } + internal enum VoicevoxAccelerationMode : int { VOICEVOX_ACCELERATION_MODE_AUTO = 0, diff --git a/src/VoicevoxCoreSharp.Core/Native/CoreUnsafe.g.cs b/src/VoicevoxCoreSharp.Core/Native/CoreUnsafe.g.cs index c77b3f7..4701e37 100644 --- a/src/VoicevoxCoreSharp.Core/Native/CoreUnsafe.g.cs +++ b/src/VoicevoxCoreSharp.Core/Native/CoreUnsafe.g.cs @@ -535,18 +535,28 @@ internal static unsafe partial class CoreUnsafe [DllImport(__DllName, EntryPoint = "voicevox_synthesizer_delete", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] internal static extern void voicevox_synthesizer_delete(VoicevoxSynthesizer* synthesizer); + /// + /// デフォルトの `voicevox_synthesizer_load_voice_model` のオプションを生成する + /// @return デフォルト値が設定された `voicevox_synthesizer_load_voice_model` のオプション + /// + /// \no-orig-impl{voicevox_make_default_load_voice_model_options} + /// + [DllImport(__DllName, EntryPoint = "voicevox_make_default_load_voice_model_options", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + internal static extern VoicevoxLoadVoiceModelOptions voicevox_make_default_load_voice_model_options(); + /// /// 音声モデルを読み込む。 /// /// @param [in] synthesizer 音声シンセサイザ /// @param [in] model 音声モデル + /// @param [in] options オプション /// /// @returns 結果コード /// /// \orig-impl{voicevox_synthesizer_load_voice_model} /// [DllImport(__DllName, EntryPoint = "voicevox_synthesizer_load_voice_model", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] - internal static extern VoicevoxResultCode voicevox_synthesizer_load_voice_model(VoicevoxSynthesizer* synthesizer, VoicevoxVoiceModelFile* model); + internal static extern VoicevoxResultCode voicevox_synthesizer_load_voice_model(VoicevoxSynthesizer* synthesizer, VoicevoxVoiceModelFile* model, VoicevoxLoadVoiceModelOptions options); /// /// 音声モデルの読み込みを解除する。 @@ -1374,6 +1384,12 @@ internal unsafe partial struct VoicevoxSynthesizer { } + [StructLayout(LayoutKind.Sequential)] + internal unsafe partial struct VoicevoxLoadVoiceModelOptions + { + public VoicevoxOnExistingVoiceModelId on_existing; + } + [StructLayout(LayoutKind.Sequential)] internal unsafe partial struct VoicevoxSynthesisOptions { @@ -1437,6 +1453,13 @@ internal enum VoicevoxResultCode : int VOICEVOX_RESULT_INCOMPATIBLE_QUERIES_ERROR = 35, } + internal enum VoicevoxOnExistingVoiceModelId : int + { + VOICEVOX_ON_EXISTING_VOICE_MODEL_ID_ERROR = 0, + VOICEVOX_ON_EXISTING_VOICE_MODEL_ID_RELOAD = 1, + VOICEVOX_ON_EXISTING_VOICE_MODEL_ID_SKIP = 2, + } + internal enum VoicevoxAccelerationMode : int { VOICEVOX_ACCELERATION_MODE_AUTO = 0, diff --git a/src/VoicevoxCoreSharp.Core/VoicevoxCoreSharp.Core.Metas.props b/src/VoicevoxCoreSharp.Core/VoicevoxCoreSharp.Core.Metas.props index e5c0e6f..be9f6e1 100644 --- a/src/VoicevoxCoreSharp.Core/VoicevoxCoreSharp.Core.Metas.props +++ b/src/VoicevoxCoreSharp.Core/VoicevoxCoreSharp.Core.Metas.props @@ -1,6 +1,6 @@ 1.17.3 - cdb9ab6e3c2fe6421d20af3fd2a476878ecf79c0 + 72dde0a885e91f94dff0de7377b1851a809eefa9 From 4a0b9be5572b66fe5ebbd61e23c7436d76b20dc1 Mon Sep 17 00:00:00 2001 From: yamachu Date: Tue, 9 Jun 2026 02:57:52 +0900 Subject: [PATCH 4/5] =?UTF-8?q?=E6=96=B0=E3=81=97=E3=81=84=E3=82=B7?= =?UTF-8?q?=E3=82=B0=E3=83=8D=E3=83=81=E3=83=A3=E3=81=AB=E5=90=88=E3=82=8F?= =?UTF-8?q?=E3=81=9B=E3=81=A6=E3=82=B3=E3=83=BC=E3=83=89=E3=81=A8=E3=82=B5?= =?UTF-8?q?=E3=83=B3=E3=83=97=E3=83=AB=E3=80=81=E3=83=86=E3=82=B9=E3=83=88?= =?UTF-8?q?=E3=81=AE=E6=9B=B8=E3=81=8D=E6=8F=9B=E3=81=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Assets/SampleVoicevoxCoreSharpScript.cs | 4 +- .../Script/Enum/OnExistingVoiceModelId.cs | 51 +++++++++++++++++++ .../Enum/OnExistingVoiceModelId.cs.meta | 11 ++++ .../Script/Struct/LoadVoiceModelOptions.cs | 46 +++++++++++++++++ .../Struct/LoadVoiceModelOptions.cs.meta | 11 ++++ .../Runtime/Script/Synthesizer.cs | 5 +- .../Enum/OnExistingVoiceModelId.cs | 51 +++++++++++++++++++ .../Struct/LoadVoiceModelOptions.cs | 46 +++++++++++++++++ src/VoicevoxCoreSharp.Core/Synthesizer.cs | 5 +- .../SynthesizerExtensions.cs | 2 +- .../SynthesizerTest.cs | 6 +-- tests/VoicevoxCoreSharp.Core.Tests/TtsTest.cs | 2 +- 12 files changed, 229 insertions(+), 11 deletions(-) create mode 100644 src/VoicevoxCoreSharp.Core.Unity/Runtime/Script/Enum/OnExistingVoiceModelId.cs create mode 100644 src/VoicevoxCoreSharp.Core.Unity/Runtime/Script/Enum/OnExistingVoiceModelId.cs.meta create mode 100644 src/VoicevoxCoreSharp.Core.Unity/Runtime/Script/Struct/LoadVoiceModelOptions.cs create mode 100644 src/VoicevoxCoreSharp.Core.Unity/Runtime/Script/Struct/LoadVoiceModelOptions.cs.meta create mode 100644 src/VoicevoxCoreSharp.Core/Enum/OnExistingVoiceModelId.cs create mode 100644 src/VoicevoxCoreSharp.Core/Struct/LoadVoiceModelOptions.cs diff --git a/examples/UnitySample/Assets/SampleVoicevoxCoreSharpScript.cs b/examples/UnitySample/Assets/SampleVoicevoxCoreSharpScript.cs index f452a67..d37b63a 100644 --- a/examples/UnitySample/Assets/SampleVoicevoxCoreSharpScript.cs +++ b/examples/UnitySample/Assets/SampleVoicevoxCoreSharpScript.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections; using System.Collections.Generic; using System.IO; @@ -50,7 +50,7 @@ void Start() return; } - result = synthesizer.LoadVoiceModel(voiceModel); + result = synthesizer.LoadVoiceModel(voiceModel, LoadVoiceModelOptions.Default()); if (result != ResultCode.RESULT_OK) { Debug.LogError(result.ToMessage()); diff --git a/src/VoicevoxCoreSharp.Core.Unity/Runtime/Script/Enum/OnExistingVoiceModelId.cs b/src/VoicevoxCoreSharp.Core.Unity/Runtime/Script/Enum/OnExistingVoiceModelId.cs new file mode 100644 index 0000000..f8a3540 --- /dev/null +++ b/src/VoicevoxCoreSharp.Core.Unity/Runtime/Script/Enum/OnExistingVoiceModelId.cs @@ -0,0 +1,51 @@ +using System; +using VoicevoxCoreSharp.Core.Native; + +namespace VoicevoxCoreSharp.Core.Enum +{ + /// + /// ::voicevox_synthesizer_load_voice_model の実行時に、同じIDの ::VoicevoxVoiceModelFile が既に読み込まれていたときのふるまい。 + /// + public enum OnExistingVoiceModelId : int + { + /// + /// エラーにする。デフォルトのふるまい + /// + VOICEVOX_ON_EXISTING_VOICE_MODEL_ID_ERROR = 0, + /// + /// 再読み込みする。VOICEVOX COREでは、長文のテキストを一度に音声合成するとCPU/GPUメモリが大量に占有されたままになる。再読み込みを行うとメモリの使用量が元に戻る + /// + VOICEVOX_ON_EXISTING_VOICE_MODEL_ID_RELOAD = 1, + /// + /// 何もしない + /// + VOICEVOX_ON_EXISTING_VOICE_MODEL_ID_SKIP = 2, + } + + internal static class OnExistingVoiceModelIdExt + { + public static OnExistingVoiceModelId FromNative(this VoicevoxOnExistingVoiceModelId mode) + { +#pragma warning disable CS8524 + return mode switch + { + VoicevoxOnExistingVoiceModelId.VOICEVOX_ON_EXISTING_VOICE_MODEL_ID_ERROR => OnExistingVoiceModelId.VOICEVOX_ON_EXISTING_VOICE_MODEL_ID_ERROR, + VoicevoxOnExistingVoiceModelId.VOICEVOX_ON_EXISTING_VOICE_MODEL_ID_RELOAD => OnExistingVoiceModelId.VOICEVOX_ON_EXISTING_VOICE_MODEL_ID_RELOAD, + VoicevoxOnExistingVoiceModelId.VOICEVOX_ON_EXISTING_VOICE_MODEL_ID_SKIP => OnExistingVoiceModelId.VOICEVOX_ON_EXISTING_VOICE_MODEL_ID_SKIP, + }; +#pragma warning restore CS8524 + } + + public static VoicevoxOnExistingVoiceModelId ToNative(this OnExistingVoiceModelId mode) + { +#pragma warning disable CS8524 + return mode switch + { + OnExistingVoiceModelId.VOICEVOX_ON_EXISTING_VOICE_MODEL_ID_ERROR => VoicevoxOnExistingVoiceModelId.VOICEVOX_ON_EXISTING_VOICE_MODEL_ID_ERROR, + OnExistingVoiceModelId.VOICEVOX_ON_EXISTING_VOICE_MODEL_ID_RELOAD => VoicevoxOnExistingVoiceModelId.VOICEVOX_ON_EXISTING_VOICE_MODEL_ID_RELOAD, + OnExistingVoiceModelId.VOICEVOX_ON_EXISTING_VOICE_MODEL_ID_SKIP => VoicevoxOnExistingVoiceModelId.VOICEVOX_ON_EXISTING_VOICE_MODEL_ID_SKIP, + }; +#pragma warning restore CS8524 + } + } +} diff --git a/src/VoicevoxCoreSharp.Core.Unity/Runtime/Script/Enum/OnExistingVoiceModelId.cs.meta b/src/VoicevoxCoreSharp.Core.Unity/Runtime/Script/Enum/OnExistingVoiceModelId.cs.meta new file mode 100644 index 0000000..de35f19 --- /dev/null +++ b/src/VoicevoxCoreSharp.Core.Unity/Runtime/Script/Enum/OnExistingVoiceModelId.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 93999e01ea9a84867bd270baa5886bc3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/VoicevoxCoreSharp.Core.Unity/Runtime/Script/Struct/LoadVoiceModelOptions.cs b/src/VoicevoxCoreSharp.Core.Unity/Runtime/Script/Struct/LoadVoiceModelOptions.cs new file mode 100644 index 0000000..9bf534c --- /dev/null +++ b/src/VoicevoxCoreSharp.Core.Unity/Runtime/Script/Struct/LoadVoiceModelOptions.cs @@ -0,0 +1,46 @@ +using System; +using VoicevoxCoreSharp.Core.Enum; +using VoicevoxCoreSharp.Core.Native; + +namespace VoicevoxCoreSharp.Core.Struct +{ + /// + /// ::voicevox_synthesizer_load_voice_model のオプション。 + /// + public struct LoadVoiceModelOptions + { + /// + /// 同じIDの ::VoicevoxVoiceModelFile が既に読み込まれていたときのふるまい + /// + public OnExistingVoiceModelId OnExisting { get; set; } + + public static LoadVoiceModelOptions Default() + { + return LoadVoiceModelOptionsDefault.Value; + } + } + + internal static class LoadVoiceModelOptionsDefault + { + public static readonly LoadVoiceModelOptions Value = CoreUnsafe.voicevox_make_default_load_voice_model_options().FromNative(); + } + + internal static class LoadVoiceModelOptionsExt + { + internal static VoicevoxLoadVoiceModelOptions ToNative(this LoadVoiceModelOptions loadVoiceModelOptions) + { + return new VoicevoxLoadVoiceModelOptions + { + on_existing = loadVoiceModelOptions.OnExisting.ToNative() + }; + } + + internal static LoadVoiceModelOptions FromNative(this VoicevoxLoadVoiceModelOptions loadVoiceModelOptions) + { + return new LoadVoiceModelOptions + { + OnExisting = loadVoiceModelOptions.on_existing.FromNative() + }; + } + } +} diff --git a/src/VoicevoxCoreSharp.Core.Unity/Runtime/Script/Struct/LoadVoiceModelOptions.cs.meta b/src/VoicevoxCoreSharp.Core.Unity/Runtime/Script/Struct/LoadVoiceModelOptions.cs.meta new file mode 100644 index 0000000..d4e1cad --- /dev/null +++ b/src/VoicevoxCoreSharp.Core.Unity/Runtime/Script/Struct/LoadVoiceModelOptions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5c4ed9e54fb1b4886b2741165ca0d74d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/VoicevoxCoreSharp.Core.Unity/Runtime/Script/Synthesizer.cs b/src/VoicevoxCoreSharp.Core.Unity/Runtime/Script/Synthesizer.cs index 1b5e09c..e31427e 100644 --- a/src/VoicevoxCoreSharp.Core.Unity/Runtime/Script/Synthesizer.cs +++ b/src/VoicevoxCoreSharp.Core.Unity/Runtime/Script/Synthesizer.cs @@ -60,11 +60,12 @@ public static ResultCode New(Onnxruntime onnxruntime, OpenJtalk openJtalk, Initi } } - public ResultCode LoadVoiceModel(VoiceModelFile voiceModel) + public ResultCode LoadVoiceModel(VoiceModelFile voiceModel, LoadVoiceModelOptions options) { unsafe { - return CoreUnsafe.voicevox_synthesizer_load_voice_model((VoicevoxSynthesizer*)Handle, (VoicevoxVoiceModelFile*)voiceModel.Handle).FromNative(); + var loadVoiceModelOptions = options.ToNative(); + return CoreUnsafe.voicevox_synthesizer_load_voice_model((VoicevoxSynthesizer*)Handle, (VoicevoxVoiceModelFile*)voiceModel.Handle, loadVoiceModelOptions).FromNative(); } } diff --git a/src/VoicevoxCoreSharp.Core/Enum/OnExistingVoiceModelId.cs b/src/VoicevoxCoreSharp.Core/Enum/OnExistingVoiceModelId.cs new file mode 100644 index 0000000..f8a3540 --- /dev/null +++ b/src/VoicevoxCoreSharp.Core/Enum/OnExistingVoiceModelId.cs @@ -0,0 +1,51 @@ +using System; +using VoicevoxCoreSharp.Core.Native; + +namespace VoicevoxCoreSharp.Core.Enum +{ + /// + /// ::voicevox_synthesizer_load_voice_model の実行時に、同じIDの ::VoicevoxVoiceModelFile が既に読み込まれていたときのふるまい。 + /// + public enum OnExistingVoiceModelId : int + { + /// + /// エラーにする。デフォルトのふるまい + /// + VOICEVOX_ON_EXISTING_VOICE_MODEL_ID_ERROR = 0, + /// + /// 再読み込みする。VOICEVOX COREでは、長文のテキストを一度に音声合成するとCPU/GPUメモリが大量に占有されたままになる。再読み込みを行うとメモリの使用量が元に戻る + /// + VOICEVOX_ON_EXISTING_VOICE_MODEL_ID_RELOAD = 1, + /// + /// 何もしない + /// + VOICEVOX_ON_EXISTING_VOICE_MODEL_ID_SKIP = 2, + } + + internal static class OnExistingVoiceModelIdExt + { + public static OnExistingVoiceModelId FromNative(this VoicevoxOnExistingVoiceModelId mode) + { +#pragma warning disable CS8524 + return mode switch + { + VoicevoxOnExistingVoiceModelId.VOICEVOX_ON_EXISTING_VOICE_MODEL_ID_ERROR => OnExistingVoiceModelId.VOICEVOX_ON_EXISTING_VOICE_MODEL_ID_ERROR, + VoicevoxOnExistingVoiceModelId.VOICEVOX_ON_EXISTING_VOICE_MODEL_ID_RELOAD => OnExistingVoiceModelId.VOICEVOX_ON_EXISTING_VOICE_MODEL_ID_RELOAD, + VoicevoxOnExistingVoiceModelId.VOICEVOX_ON_EXISTING_VOICE_MODEL_ID_SKIP => OnExistingVoiceModelId.VOICEVOX_ON_EXISTING_VOICE_MODEL_ID_SKIP, + }; +#pragma warning restore CS8524 + } + + public static VoicevoxOnExistingVoiceModelId ToNative(this OnExistingVoiceModelId mode) + { +#pragma warning disable CS8524 + return mode switch + { + OnExistingVoiceModelId.VOICEVOX_ON_EXISTING_VOICE_MODEL_ID_ERROR => VoicevoxOnExistingVoiceModelId.VOICEVOX_ON_EXISTING_VOICE_MODEL_ID_ERROR, + OnExistingVoiceModelId.VOICEVOX_ON_EXISTING_VOICE_MODEL_ID_RELOAD => VoicevoxOnExistingVoiceModelId.VOICEVOX_ON_EXISTING_VOICE_MODEL_ID_RELOAD, + OnExistingVoiceModelId.VOICEVOX_ON_EXISTING_VOICE_MODEL_ID_SKIP => VoicevoxOnExistingVoiceModelId.VOICEVOX_ON_EXISTING_VOICE_MODEL_ID_SKIP, + }; +#pragma warning restore CS8524 + } + } +} diff --git a/src/VoicevoxCoreSharp.Core/Struct/LoadVoiceModelOptions.cs b/src/VoicevoxCoreSharp.Core/Struct/LoadVoiceModelOptions.cs new file mode 100644 index 0000000..9bf534c --- /dev/null +++ b/src/VoicevoxCoreSharp.Core/Struct/LoadVoiceModelOptions.cs @@ -0,0 +1,46 @@ +using System; +using VoicevoxCoreSharp.Core.Enum; +using VoicevoxCoreSharp.Core.Native; + +namespace VoicevoxCoreSharp.Core.Struct +{ + /// + /// ::voicevox_synthesizer_load_voice_model のオプション。 + /// + public struct LoadVoiceModelOptions + { + /// + /// 同じIDの ::VoicevoxVoiceModelFile が既に読み込まれていたときのふるまい + /// + public OnExistingVoiceModelId OnExisting { get; set; } + + public static LoadVoiceModelOptions Default() + { + return LoadVoiceModelOptionsDefault.Value; + } + } + + internal static class LoadVoiceModelOptionsDefault + { + public static readonly LoadVoiceModelOptions Value = CoreUnsafe.voicevox_make_default_load_voice_model_options().FromNative(); + } + + internal static class LoadVoiceModelOptionsExt + { + internal static VoicevoxLoadVoiceModelOptions ToNative(this LoadVoiceModelOptions loadVoiceModelOptions) + { + return new VoicevoxLoadVoiceModelOptions + { + on_existing = loadVoiceModelOptions.OnExisting.ToNative() + }; + } + + internal static LoadVoiceModelOptions FromNative(this VoicevoxLoadVoiceModelOptions loadVoiceModelOptions) + { + return new LoadVoiceModelOptions + { + OnExisting = loadVoiceModelOptions.on_existing.FromNative() + }; + } + } +} diff --git a/src/VoicevoxCoreSharp.Core/Synthesizer.cs b/src/VoicevoxCoreSharp.Core/Synthesizer.cs index 1b5e09c..e31427e 100644 --- a/src/VoicevoxCoreSharp.Core/Synthesizer.cs +++ b/src/VoicevoxCoreSharp.Core/Synthesizer.cs @@ -60,11 +60,12 @@ public static ResultCode New(Onnxruntime onnxruntime, OpenJtalk openJtalk, Initi } } - public ResultCode LoadVoiceModel(VoiceModelFile voiceModel) + public ResultCode LoadVoiceModel(VoiceModelFile voiceModel, LoadVoiceModelOptions options) { unsafe { - return CoreUnsafe.voicevox_synthesizer_load_voice_model((VoicevoxSynthesizer*)Handle, (VoicevoxVoiceModelFile*)voiceModel.Handle).FromNative(); + var loadVoiceModelOptions = options.ToNative(); + return CoreUnsafe.voicevox_synthesizer_load_voice_model((VoicevoxSynthesizer*)Handle, (VoicevoxVoiceModelFile*)voiceModel.Handle, loadVoiceModelOptions).FromNative(); } } diff --git a/src/VoicevoxCoreSharp.Experimental/SynthesizerExtensions.cs b/src/VoicevoxCoreSharp.Experimental/SynthesizerExtensions.cs index b3c9009..eb361d2 100644 --- a/src/VoicevoxCoreSharp.Experimental/SynthesizerExtensions.cs +++ b/src/VoicevoxCoreSharp.Experimental/SynthesizerExtensions.cs @@ -9,7 +9,7 @@ namespace VoicevoxCoreSharp.Experimental public static partial class SynthesizerExtensions { [NonBlocking] - public static partial Task LoadVoiceModelAsync(this Synthesizer synthesizer, VoiceModelFile voiceModel); + public static partial Task LoadVoiceModelAsync(this Synthesizer synthesizer, VoiceModelFile voiceModel, LoadVoiceModelOptions options); [NonBlocking] public static partial Task<(nuint outputWavLength, byte[] outputWav)> SynthesisAsync(this Synthesizer synthesizer, string audioQueryJson, uint styleId, SynthesisOptions options); diff --git a/tests/VoicevoxCoreSharp.Core.Tests/SynthesizerTest.cs b/tests/VoicevoxCoreSharp.Core.Tests/SynthesizerTest.cs index 0301ae1..f9b9d1f 100644 --- a/tests/VoicevoxCoreSharp.Core.Tests/SynthesizerTest.cs +++ b/tests/VoicevoxCoreSharp.Core.Tests/SynthesizerTest.cs @@ -21,7 +21,7 @@ public void Tts() var synthesizerResult = Synthesizer.New(onnruntime, openJtalk, initializeOptions, out var synthesizer); VoiceModelFile.Open(Consts.SampleVoiceModel, out var voiceModel); - var loadResult = synthesizer.LoadVoiceModel(voiceModel); + var loadResult = synthesizer.LoadVoiceModel(voiceModel, LoadVoiceModelOptions.Default()); Assert.Equal(ResultCode.RESULT_OK, synthesizerResult); Assert.Equal(ResultCode.RESULT_OK, loadResult); @@ -47,7 +47,7 @@ public void VoiceModelLoaded() Synthesizer.New(onnruntime, openJtalk, initializeOptions, out var synthesizer); VoiceModelFile.Open(Consts.SampleVoiceModel, out var voiceModel); - synthesizer.LoadVoiceModel(voiceModel); + synthesizer.LoadVoiceModel(voiceModel, LoadVoiceModelOptions.Default()); Assert.True(synthesizer.IsLoadedVoiceModel(voiceModel.Id)); synthesizer.UnloadVoiceModel(voiceModel.Id); @@ -63,7 +63,7 @@ public void SingSynthesis() Onnxruntime.LoadOnce(onnxruntimeOptions, out var onnxruntime); Synthesizer.New(onnxruntime, openJtalk, initializeOptions, out var synthesizer); VoiceModelFile.Open(Consts.SampleVoiceModel, out var voiceModel); - synthesizer.LoadVoiceModel(voiceModel); + synthesizer.LoadVoiceModel(voiceModel, LoadVoiceModelOptions.Default()); var score = """ { diff --git a/tests/VoicevoxCoreSharp.Core.Tests/TtsTest.cs b/tests/VoicevoxCoreSharp.Core.Tests/TtsTest.cs index 3a0c1f6..1504077 100644 --- a/tests/VoicevoxCoreSharp.Core.Tests/TtsTest.cs +++ b/tests/VoicevoxCoreSharp.Core.Tests/TtsTest.cs @@ -21,7 +21,7 @@ public void TtsBySynthesis() var synthesizerResult = Synthesizer.New(onnruntime, openJtalk, initializeOptions, out var synthesizer); VoiceModelFile.Open(Consts.SampleVoiceModel, out var voiceModel); - var loadResult = synthesizer.LoadVoiceModel(voiceModel); + var loadResult = synthesizer.LoadVoiceModel(voiceModel, LoadVoiceModelOptions.Default()); Assert.Equal(ResultCode.RESULT_OK, synthesizerResult); Assert.Equal(ResultCode.RESULT_OK, loadResult); From 38db6a1016bfd9a4d1fe2b5c4a762c5cdab56636 Mon Sep 17 00:00:00 2001 From: yamachu Date: Tue, 9 Jun 2026 03:13:36 +0900 Subject: [PATCH 5/5] fix sample code --- examples/cli/Program.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/examples/cli/Program.cs b/examples/cli/Program.cs index 1499944..a3c31ed 100644 --- a/examples/cli/Program.cs +++ b/examples/cli/Program.cs @@ -1,10 +1,9 @@ using System.CommandLine; using System.CommandLine.Parsing; using Microsoft.Extensions.FileSystemGlobbing; - using VoicevoxCoreSharp.Core; -using VoicevoxCoreSharp.Core.Struct; using VoicevoxCoreSharp.Core.Enum; +using VoicevoxCoreSharp.Core.Struct; const string OutputWavName = "audio.wav"; const uint StyleId = 0; @@ -50,7 +49,7 @@ static int RunTts(string text, string? resourcePath = "voicevox_core") return 1; } - result = synthesizer.LoadVoiceModel(voiceModel); + result = synthesizer.LoadVoiceModel(voiceModel, LoadVoiceModelOptions.Default()); if (result != ResultCode.RESULT_OK) { Console.Error.WriteLine(result.ToMessage());