From 71504d9de466597fb43859e02064aad208214345 Mon Sep 17 00:00:00 2001 From: Ryo Yamashita Date: Wed, 12 Feb 2025 11:40:47 +0900 Subject: [PATCH] fix!: various fix for `UserDictWord` (#1002) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. C APIとRust APIのみ`priority`のデフォルトが`5`ではなく`0`になっていた ため、`5`に合わせることでPython, Java, VOICEVOX ENGINEに合わせる。 2. VOICEVOX ENGINEにならった場合、`surface`, `pronounciation`と同様 `accent_type`もrequiredであるはずなので、そうしてしまう。 3. `impl Default for UserDictWord`を削除。 --- .../voicevox_core/src/__internal/interop.rs | 1 + crates/voicevox_core/src/user_dict/mod.rs | 2 +- crates/voicevox_core/src/user_dict/word.rs | 16 +++----------- .../include/voicevox_core.h | 4 +++- crates/voicevox_core_c_api/src/lib.rs | 12 +++++----- .../tests/e2e/testcases/user_dict_load.rs | 1 + .../e2e/testcases/user_dict_manipulate.rs | 8 +++---- .../hiroshiba/voicevoxcore/UserDictWord.java | 22 +++++-------------- .../voicevoxcore/blocking/UserDictTest.java | 11 +++++----- .../test/test_asyncio_user_dict_load.py | 1 + .../test/test_asyncio_user_dict_manipulate.py | 5 +++++ .../test/test_blocking_user_dict_load.py | 1 + .../test_blocking_user_dict_manipulate.py | 5 +++++ .../python/voicevox_core/_models/__init__.py | 2 +- 14 files changed, 45 insertions(+), 46 deletions(-) diff --git a/crates/voicevox_core/src/__internal/interop.rs b/crates/voicevox_core/src/__internal/interop.rs index 0085a3222..2e331ca11 100644 --- a/crates/voicevox_core/src/__internal/interop.rs +++ b/crates/voicevox_core/src/__internal/interop.rs @@ -7,4 +7,5 @@ pub use crate::{ blocking::PerformInference, DEFAULT_CPU_NUM_THREADS, DEFAULT_ENABLE_INTERROGATIVE_UPSPEAK, MARGIN, }, + user_dict::{DEFAULT_PRIORITY, DEFAULT_WORD_TYPE}, }; diff --git a/crates/voicevox_core/src/user_dict/mod.rs b/crates/voicevox_core/src/user_dict/mod.rs index 042ca0974..cedecf6be 100644 --- a/crates/voicevox_core/src/user_dict/mod.rs +++ b/crates/voicevox_core/src/user_dict/mod.rs @@ -3,4 +3,4 @@ mod part_of_speech_data; mod word; pub(crate) use self::word::{to_zenkaku, validate_pronunciation, InvalidWordError}; -pub use self::word::{UserDictWord, UserDictWordType}; +pub use self::word::{UserDictWord, UserDictWordType, DEFAULT_PRIORITY, DEFAULT_WORD_TYPE}; diff --git a/crates/voicevox_core/src/user_dict/word.rs b/crates/voicevox_core/src/user_dict/word.rs index 7b845bb50..a10a84403 100644 --- a/crates/voicevox_core/src/user_dict/word.rs +++ b/crates/voicevox_core/src/user_dict/word.rs @@ -79,6 +79,9 @@ impl InvalidWordError { type InvalidWordResult = std::result::Result; +pub const DEFAULT_WORD_TYPE: UserDictWordType = UserDictWordType::CommonNoun; +pub const DEFAULT_PRIORITY: u32 = 5; + static PRONUNCIATION_REGEX: LazyLock = LazyLock::new(|| Regex::new(r"^[ァ-ヴー]+$").unwrap()); static MORA_REGEX: LazyLock = LazyLock::new(|| { @@ -94,19 +97,6 @@ static MORA_REGEX: LazyLock = LazyLock::new(|| { }); static SPACE_REGEX: LazyLock = LazyLock::new(|| Regex::new(r"\p{Z}").unwrap()); -impl Default for UserDictWord { - fn default() -> Self { - Self { - surface: "".to_string(), - pronunciation: "".to_string(), - accent_type: 0, - word_type: UserDictWordType::CommonNoun, - priority: 0, - mora_count: 0, - } - } -} - impl UserDictWord { // TODO: これビルダースタイルにすべきでは? #[doc(alias = "voicevox_user_dict_word_make")] diff --git a/crates/voicevox_core_c_api/include/voicevox_core.h b/crates/voicevox_core_c_api/include/voicevox_core.h index 2f20e1098..98aa5e47b 100644 --- a/crates/voicevox_core_c_api/include/voicevox_core.h +++ b/crates/voicevox_core_c_api/include/voicevox_core.h @@ -1308,6 +1308,7 @@ const char *voicevox_error_result_to_message(VoicevoxResultCode result_code); * * @param [in] surface 表記 * @param [in] pronunciation 読み + * @param [in] accent_type アクセント型 * @returns ::VoicevoxUserDictWord * * \orig-impl{voicevox_user_dict_word_make} @@ -1316,7 +1317,8 @@ const char *voicevox_error_result_to_message(VoicevoxResultCode result_code); __declspec(dllimport) #endif struct VoicevoxUserDictWord voicevox_user_dict_word_make(const char *surface, - const char *pronunciation); + const char *pronunciation, + uintptr_t accent_type); /** * ユーザー辞書をb>構築(_construct_)する。 diff --git a/crates/voicevox_core_c_api/src/lib.rs b/crates/voicevox_core_c_api/src/lib.rs index 60ccc4fd3..93ab8ae4f 100644 --- a/crates/voicevox_core_c_api/src/lib.rs +++ b/crates/voicevox_core_c_api/src/lib.rs @@ -38,8 +38,8 @@ use std::sync::Once; use tracing_subscriber::fmt::format::Writer; use tracing_subscriber::EnvFilter; use uuid::Uuid; -use voicevox_core::__internal::interop::ToJsonValue as _; -use voicevox_core::{AccentPhrase, AudioQuery, StyleId, UserDictWord}; +use voicevox_core::__internal::interop::{ToJsonValue as _, DEFAULT_PRIORITY, DEFAULT_WORD_TYPE}; +use voicevox_core::{AccentPhrase, AudioQuery, StyleId}; fn init_logger_once() { static ONCE: Once = Once::new(); @@ -1431,6 +1431,7 @@ pub enum VoicevoxUserDictWordType { /// /// @param [in] surface 表記 /// @param [in] pronunciation 読み +/// @param [in] accent_type アクセント型 /// @returns ::VoicevoxUserDictWord /// /// \orig-impl{voicevox_user_dict_word_make} @@ -1438,14 +1439,15 @@ pub enum VoicevoxUserDictWordType { pub extern "C" fn voicevox_user_dict_word_make( surface: *const c_char, pronunciation: *const c_char, + accent_type: usize, ) -> VoicevoxUserDictWord { init_logger_once(); VoicevoxUserDictWord { surface, pronunciation, - accent_type: UserDictWord::default().accent_type(), - word_type: UserDictWord::default().word_type().into(), - priority: UserDictWord::default().priority(), + accent_type, + word_type: DEFAULT_WORD_TYPE.into(), + priority: DEFAULT_PRIORITY, } } diff --git a/crates/voicevox_core_c_api/tests/e2e/testcases/user_dict_load.rs b/crates/voicevox_core_c_api/tests/e2e/testcases/user_dict_load.rs index 3051369ed..7a812e46f 100644 --- a/crates/voicevox_core_c_api/tests/e2e/testcases/user_dict_load.rs +++ b/crates/voicevox_core_c_api/tests/e2e/testcases/user_dict_load.rs @@ -38,6 +38,7 @@ impl assert_cdylib::TestCase for TestCase { let mut word = lib.voicevox_user_dict_word_make( c"this_word_should_not_exist_in_default_dictionary".as_ptr(), c"アイウエオ".as_ptr(), + 0, ); word.word_type = c_api::VoicevoxUserDictWordType_VOICEVOX_USER_DICT_WORD_TYPE_PROPER_NOUN; diff --git a/crates/voicevox_core_c_api/tests/e2e/testcases/user_dict_manipulate.rs b/crates/voicevox_core_c_api/tests/e2e/testcases/user_dict_manipulate.rs index 85494ddd0..92d53b546 100644 --- a/crates/voicevox_core_c_api/tests/e2e/testcases/user_dict_manipulate.rs +++ b/crates/voicevox_core_c_api/tests/e2e/testcases/user_dict_manipulate.rs @@ -55,7 +55,7 @@ impl assert_cdylib::TestCase for TestCase { let dict = lib.voicevox_user_dict_new(); // 単語の追加のテスト - let word = lib.voicevox_user_dict_word_make(c"hoge".as_ptr(), c"ホゲ".as_ptr()); + let word = lib.voicevox_user_dict_word_make(c"hoge".as_ptr(), c"ホゲ".as_ptr(), 0); let word_uuid = add_word(dict, &word); @@ -66,7 +66,7 @@ impl assert_cdylib::TestCase for TestCase { assert_contains_uuid(&json, &word_uuid); // 単語の変更のテスト - let word = lib.voicevox_user_dict_word_make(c"fuga".as_ptr(), c"フガ".as_ptr()); + let word = lib.voicevox_user_dict_word_make(c"fuga".as_ptr(), c"フガ".as_ptr(), 0); assert_ok(lib.voicevox_user_dict_update_word(dict, &word_uuid.into_bytes(), &word)); @@ -81,7 +81,7 @@ impl assert_cdylib::TestCase for TestCase { // 辞書のインポートのテスト。 let other_dict = lib.voicevox_user_dict_new(); - let other_word = lib.voicevox_user_dict_word_make(c"piyo".as_ptr(), c"ピヨ".as_ptr()); + let other_word = lib.voicevox_user_dict_word_make(c"piyo".as_ptr(), c"ピヨ".as_ptr(), 0); let other_word_uuid = add_word(other_dict, &other_word); @@ -106,7 +106,7 @@ impl assert_cdylib::TestCase for TestCase { // 辞書のセーブ・ロードのテスト let temp_path = NamedTempFile::new().unwrap().into_temp_path(); let temp_path = CString::new(temp_path.to_str().unwrap()).unwrap(); - let word = lib.voicevox_user_dict_word_make(c"hoge".as_ptr(), c"ホゲ".as_ptr()); + let word = lib.voicevox_user_dict_word_make(c"hoge".as_ptr(), c"ホゲ".as_ptr(), 0); let word_uuid = add_word(dict, &word); assert_ok(lib.voicevox_user_dict_save(dict, temp_path.as_ptr())); diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/hiroshiba/voicevoxcore/UserDictWord.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/hiroshiba/voicevoxcore/UserDictWord.java index 3352337bf..07816c2b6 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/hiroshiba/voicevoxcore/UserDictWord.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/hiroshiba/voicevoxcore/UserDictWord.java @@ -59,21 +59,25 @@ public class UserDictWord { * * @param surface 言葉の表層形。 * @param pronunciation 言葉の発音。 + * @param accentType アクセント型。 * @throws IllegalArgumentException pronunciationが不正な場合。 */ - public UserDictWord(String surface, String pronunciation) { + public UserDictWord(String surface, String pronunciation, int accentType) { if (surface == null) { throw new NullPointerException("surface"); } if (pronunciation == null) { throw new NullPointerException("pronunciation"); } + if (accentType < 0) { + throw new IllegalArgumentException("accentType"); + } this.surface = rsToZenkaku(surface); rsValidatePronunciation(pronunciation); this.pronunciation = pronunciation; this.wordType = Type.COMMON_NOUN; - this.accentType = 0; + this.accentType = accentType; this.priority = 5; } @@ -91,20 +95,6 @@ public UserDictWord wordType(Type wordType) { return this; } - /** - * アクセント型を設定する。 - * - * @param accentType アクセント型。 - * @return このインスタンス。 - */ - public UserDictWord accentType(int accentType) { - if (accentType < 0) { - throw new IllegalArgumentException("accentType"); - } - this.accentType = accentType; - return this; - } - /** * 優先度を設定する。 * diff --git a/crates/voicevox_core_java_api/lib/src/test/java/jp/hiroshiba/voicevoxcore/blocking/UserDictTest.java b/crates/voicevox_core_java_api/lib/src/test/java/jp/hiroshiba/voicevoxcore/blocking/UserDictTest.java index 272bdfd86..b6a81b665 100644 --- a/crates/voicevox_core_java_api/lib/src/test/java/jp/hiroshiba/voicevoxcore/blocking/UserDictTest.java +++ b/crates/voicevox_core_java_api/lib/src/test/java/jp/hiroshiba/voicevoxcore/blocking/UserDictTest.java @@ -30,7 +30,8 @@ void checkLoad() throws RunModelException, InvalidModelDataException, LoadUserDi "this_word_should_not_exist_in_default_dictionary", synthesizer.metas()[0].styles[0].id); - userDict.addWord(new UserDictWord("this_word_should_not_exist_in_default_dictionary", "テスト")); + userDict.addWord( + new UserDictWord("this_word_should_not_exist_in_default_dictionary", "テスト", 1)); openJtalk.useUserDict(userDict); AudioQuery query2 = synthesizer.createAudioQuery( @@ -44,11 +45,11 @@ void checkLoad() throws RunModelException, InvalidModelDataException, LoadUserDi void checkManipulation() throws Exception { UserDict userDict = new UserDict(); // 単語追加 - String uuid = userDict.addWord(new UserDictWord("hoge", "ホゲ")); + String uuid = userDict.addWord(new UserDictWord("hoge", "ホゲ", 0)); assertTrue(userDict.toHashMap().get(uuid) != null); // 単語更新 - userDict.updateWord(uuid, new UserDictWord("hoge", "ホゲホゲ")); + userDict.updateWord(uuid, new UserDictWord("hoge", "ホゲホゲ", 0)); assertTrue(userDict.toHashMap().get(uuid).pronunciation.equals("ホゲホゲ")); // 単語削除 @@ -56,9 +57,9 @@ void checkManipulation() throws Exception { assertTrue(userDict.toHashMap().get(uuid) == null); // 辞書のインポート - userDict.addWord(new UserDictWord("hoge", "ホゲ")); + userDict.addWord(new UserDictWord("hoge", "ホゲ", 0)); UserDict userDict2 = new UserDict(); - userDict2.addWord(new UserDictWord("fuga", "フガ")); + userDict2.addWord(new UserDictWord("fuga", "フガ", 0)); userDict.importDict(userDict2); assertTrue(userDict.toHashMap().size() == 2); diff --git a/crates/voicevox_core_python_api/python/test/test_asyncio_user_dict_load.py b/crates/voicevox_core_python_api/python/test/test_asyncio_user_dict_load.py index 135822ca7..7a39d05e7 100644 --- a/crates/voicevox_core_python_api/python/test/test_asyncio_user_dict_load.py +++ b/crates/voicevox_core_python_api/python/test/test_asyncio_user_dict_load.py @@ -40,6 +40,7 @@ async def test_user_dict_load() -> None: voicevox_core.UserDictWord( surface="this_word_should_not_exist_in_default_dictionary", pronunciation="アイウエオ", + accent_type=0, ) ) assert isinstance(uuid, UUID) diff --git a/crates/voicevox_core_python_api/python/test/test_asyncio_user_dict_manipulate.py b/crates/voicevox_core_python_api/python/test/test_asyncio_user_dict_manipulate.py index 5fd30d9cc..2aca79d0d 100644 --- a/crates/voicevox_core_python_api/python/test/test_asyncio_user_dict_manipulate.py +++ b/crates/voicevox_core_python_api/python/test/test_asyncio_user_dict_manipulate.py @@ -24,6 +24,7 @@ async def test_user_dict_load() -> None: voicevox_core.UserDictWord( surface="hoge", pronunciation="ホゲ", + accent_type=0, ) ) assert isinstance(uuid_a, UUID) @@ -36,6 +37,7 @@ async def test_user_dict_load() -> None: voicevox_core.UserDictWord( surface="fuga", pronunciation="フガ", + accent_type=0, ), ) @@ -48,6 +50,7 @@ async def test_user_dict_load() -> None: voicevox_core.UserDictWord( surface="foo", pronunciation="フー", + accent_type=0, ) ) @@ -60,6 +63,7 @@ async def test_user_dict_load() -> None: voicevox_core.UserDictWord( surface="bar", pronunciation="バー", + accent_type=0, ) ) temp_path_fd, temp_path = tempfile.mkstemp() @@ -80,5 +84,6 @@ async def test_user_dict_load() -> None: voicevox_core.UserDictWord( surface="", pronunciation="カタカナ以外の文字", + accent_type=0, ) ) diff --git a/crates/voicevox_core_python_api/python/test/test_blocking_user_dict_load.py b/crates/voicevox_core_python_api/python/test/test_blocking_user_dict_load.py index 9a51834f8..2df4e706d 100644 --- a/crates/voicevox_core_python_api/python/test/test_blocking_user_dict_load.py +++ b/crates/voicevox_core_python_api/python/test/test_blocking_user_dict_load.py @@ -31,6 +31,7 @@ def test_user_dict_load() -> None: voicevox_core.UserDictWord( surface="this_word_should_not_exist_in_default_dictionary", pronunciation="アイウエオ", + accent_type=0, ) ) assert isinstance(uuid, UUID) diff --git a/crates/voicevox_core_python_api/python/test/test_blocking_user_dict_manipulate.py b/crates/voicevox_core_python_api/python/test/test_blocking_user_dict_manipulate.py index 968393f40..d2f5b5925 100644 --- a/crates/voicevox_core_python_api/python/test/test_blocking_user_dict_manipulate.py +++ b/crates/voicevox_core_python_api/python/test/test_blocking_user_dict_manipulate.py @@ -23,6 +23,7 @@ def test_user_dict_load() -> None: voicevox_core.UserDictWord( surface="hoge", pronunciation="ホゲ", + accent_type=0, ) ) assert isinstance(uuid_a, UUID) @@ -35,6 +36,7 @@ def test_user_dict_load() -> None: voicevox_core.UserDictWord( surface="fuga", pronunciation="フガ", + accent_type=0, ), ) @@ -47,6 +49,7 @@ def test_user_dict_load() -> None: voicevox_core.UserDictWord( surface="foo", pronunciation="フー", + accent_type=0, ) ) @@ -59,6 +62,7 @@ def test_user_dict_load() -> None: voicevox_core.UserDictWord( surface="bar", pronunciation="バー", + accent_type=0, ) ) temp_path_fd, temp_path = tempfile.mkstemp() @@ -79,5 +83,6 @@ def test_user_dict_load() -> None: voicevox_core.UserDictWord( surface="", pronunciation="カタカナ以外の文字", + accent_type=0, ) ) diff --git a/crates/voicevox_core_python_api/python/voicevox_core/_models/__init__.py b/crates/voicevox_core_python_api/python/voicevox_core/_models/__init__.py index 92d328407..cfdea2224 100644 --- a/crates/voicevox_core_python_api/python/voicevox_core/_models/__init__.py +++ b/crates/voicevox_core_python_api/python/voicevox_core/_models/__init__.py @@ -482,7 +482,7 @@ class UserDictWord: カタカナで表記する。 """ - accent_type: int = dataclasses.field(default=0) + accent_type: int """ アクセント型。