From 9431e00132bad0be0c047641014b43ccb8345a08 Mon Sep 17 00:00:00 2001 From: Ryo Yamashita Date: Sat, 25 Jan 2025 23:04:22 +0900 Subject: [PATCH] =?UTF-8?q?feat!:=20`VoiceModelFile::close`=E5=BE=8C?= =?UTF-8?q?=E3=82=82`id`=E3=81=A8`metas`=E3=81=B8=E3=81=AE=E3=82=A2?= =?UTF-8?q?=E3=82=AF=E3=82=BB=E3=82=B9=E3=82=92=E4=BF=9D=E8=A8=BC=20(#937)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. Rust APIでは、`VoiceModelFile::close`の返り値を`()`から `(VoiceModelId, Vec)`に 2. C APIでは、 `voicevox_voice_model_file_close`を `voicevox_voice_model_file_delete`に改名 3. Python APIとJava APIでは、`__(a)exit__`後も`id`と`metas`にアクセス可 能であることをドキュメント上で約束 BREAKING-CHANGE: 上記の1.と2.。 --- crates/voicevox_core/src/voice_model.rs | 12 ++++++++++-- crates/voicevox_core_c_api/include/voicevox_core.h | 6 +++--- crates/voicevox_core_c_api/src/lib.rs | 6 +++--- .../e2e/testcases/double_delete_voice_model_file.rs | 6 +++--- .../tests/e2e/testcases/simple_tts.rs | 2 +- .../tests/e2e/testcases/tts_via_audio_query.rs | 2 +- .../tests/e2e/testcases/user_dict_load.rs | 2 +- .../voicevoxcore/blocking/VoiceModelFile.java | 12 ++++++++++-- .../python/voicevox_core/_rust/asyncio.pyi | 8 +++++++- .../python/voicevox_core/_rust/blocking.pyi | 8 +++++++- docs/guide/dev/api-design.md | 1 + example/cpp/unix/simple_tts.cpp | 2 +- example/cpp/windows/simple_tts/simple_tts.cpp | 2 +- 13 files changed, 49 insertions(+), 20 deletions(-) diff --git a/crates/voicevox_core/src/voice_model.rs b/crates/voicevox_core/src/voice_model.rs index a52b266da..9a1a24169 100644 --- a/crates/voicevox_core/src/voice_model.rs +++ b/crates/voicevox_core/src/voice_model.rs @@ -600,6 +600,12 @@ pub(crate) mod blocking { Inner::open(path).block_on().map(Self) } + /// VVMファイルを閉じる。 + pub fn close(self) -> (VoiceModelId, VoiceModelMeta) { + let heads = self.0.into_heads(); + (*heads.header.manifest.id(), heads.header.metas.clone()) + } + pub(crate) fn inner(&self) -> &Inner { &self.0 } @@ -642,8 +648,10 @@ pub(crate) mod nonblocking { } /// VVMファイルを閉じる。 - pub async fn close(self) { - self.0.into_heads().zip.into_inner().close().await; + pub async fn close(self) -> (VoiceModelId, VoiceModelMeta) { + let heads = self.0.into_heads(); + heads.zip.into_inner().close().await; + (*heads.header.manifest.id(), heads.header.metas.clone()) } pub(crate) fn inner(&self) -> &Inner { diff --git a/crates/voicevox_core_c_api/include/voicevox_core.h b/crates/voicevox_core_c_api/include/voicevox_core.h index 979712565..0644d4dba 100644 --- a/crates/voicevox_core_c_api/include/voicevox_core.h +++ b/crates/voicevox_core_c_api/include/voicevox_core.h @@ -298,7 +298,7 @@ typedef struct VoicevoxUserDict VoicevoxUserDict; * 音声モデルファイル。 * * VVMファイルと対応する。 - * 構築(_construction_)は ::voicevox_voice_model_file_open で行い、破棄(_destruction_)は ::voicevox_voice_model_file_close で行う。 + * 構築(_construction_)は ::voicevox_voice_model_file_open で行い、破棄(_destruction_)は ::voicevox_voice_model_file_delete で行う。 */ typedef struct VoicevoxVoiceModelFile VoicevoxVoiceModelFile; @@ -636,7 +636,7 @@ __declspec(dllimport) char *voicevox_voice_model_file_create_metas_json(const struct VoicevoxVoiceModelFile *model); /** - * ::VoicevoxVoiceModelFile を、所有しているファイルディスクリプタを閉じた上で破棄(_destruct_)する。 + * ::VoicevoxVoiceModelFile を、所有しているファイルディスクリプタを閉じた上で破棄(_destruct_)する。ファイルの削除(_delete_)ではない。 * * 破棄対象への他スレッドでのアクセスが存在する場合、それらがすべて終わるのを待ってから破棄する。 * @@ -647,7 +647,7 @@ char *voicevox_voice_model_file_create_metas_json(const struct VoicevoxVoiceMode #ifdef _WIN32 __declspec(dllimport) #endif -void voicevox_voice_model_file_close(struct VoicevoxVoiceModelFile *model); +void voicevox_voice_model_file_delete(struct VoicevoxVoiceModelFile *model); /** * ::VoicevoxSynthesizer を構築(_construct_)する。 diff --git a/crates/voicevox_core_c_api/src/lib.rs b/crates/voicevox_core_c_api/src/lib.rs index ffdff9e8d..e684d9a27 100644 --- a/crates/voicevox_core_c_api/src/lib.rs +++ b/crates/voicevox_core_c_api/src/lib.rs @@ -416,7 +416,7 @@ pub extern "C" fn voicevox_get_version() -> *const c_char { /// 音声モデルファイル。 /// /// VVMファイルと対応する。 -/// 構築(_construction_)は ::voicevox_voice_model_file_open で行い、破棄(_destruction_)は ::voicevox_voice_model_file_close で行う。 +/// 構築(_construction_)は ::voicevox_voice_model_file_open で行い、破棄(_destruction_)は ::voicevox_voice_model_file_delete で行う。 #[derive(Debug, Educe)] #[educe(Default(expression = "Self { _padding: MaybeUninit::uninit() }"))] pub struct VoicevoxVoiceModelFile { @@ -497,7 +497,7 @@ pub extern "C" fn voicevox_voice_model_file_create_metas_json( // TODO: cbindgenが`#[unsafe(no_mangle)]`に対応したら`#[no_mangle]`を置き換える // SAFETY: voicevox_core_c_apiを構成するライブラリの中に、これと同名のシンボルは存在しない -/// ::VoicevoxVoiceModelFile を、所有しているファイルディスクリプタを閉じた上で破棄(_destruct_)する。 +/// ::VoicevoxVoiceModelFile を、所有しているファイルディスクリプタを閉じた上で破棄(_destruct_)する。ファイルの削除(_delete_)ではない。 /// /// 破棄対象への他スレッドでのアクセスが存在する場合、それらがすべて終わるのを待ってから破棄する。 /// @@ -505,7 +505,7 @@ pub extern "C" fn voicevox_voice_model_file_create_metas_json( /// /// @param [in] model 破棄対象 #[no_mangle] -pub extern "C" fn voicevox_voice_model_file_close(model: *mut VoicevoxVoiceModelFile) { +pub extern "C" fn voicevox_voice_model_file_delete(model: *mut VoicevoxVoiceModelFile) { init_logger_once(); model.drop_body(); } diff --git a/crates/voicevox_core_c_api/tests/e2e/testcases/double_delete_voice_model_file.rs b/crates/voicevox_core_c_api/tests/e2e/testcases/double_delete_voice_model_file.rs index 1ea6bdc19..fd7b40c7b 100644 --- a/crates/voicevox_core_c_api/tests/e2e/testcases/double_delete_voice_model_file.rs +++ b/crates/voicevox_core_c_api/tests/e2e/testcases/double_delete_voice_model_file.rs @@ -1,4 +1,4 @@ -//! `voicevox_voice_model_file_close`を二度呼ぶとクラッシュすることを確認する。 +//! `voicevox_voice_model_file_delete`を二度呼ぶとクラッシュすることを確認する。 use std::{mem::MaybeUninit, sync::LazyLock}; @@ -32,8 +32,8 @@ impl assert_cdylib::TestCase for TestCase { model.assume_init() }; - lib.voicevox_voice_model_file_close(model); - lib.voicevox_voice_model_file_close(model); + lib.voicevox_voice_model_file_delete(model); + lib.voicevox_voice_model_file_delete(model); unreachable!(); fn assert_ok(result_code: VoicevoxResultCode) { diff --git a/crates/voicevox_core_c_api/tests/e2e/testcases/simple_tts.rs b/crates/voicevox_core_c_api/tests/e2e/testcases/simple_tts.rs index 28e734ea4..750bf4d23 100644 --- a/crates/voicevox_core_c_api/tests/e2e/testcases/simple_tts.rs +++ b/crates/voicevox_core_c_api/tests/e2e/testcases/simple_tts.rs @@ -111,7 +111,7 @@ impl assert_cdylib::TestCase for TestCase { std::assert_eq!(SNAPSHOTS.output[&self.text].wav_length, wav_length); - lib.voicevox_voice_model_file_close(model); + lib.voicevox_voice_model_file_delete(model); lib.voicevox_open_jtalk_rc_delete(openjtalk); lib.voicevox_synthesizer_delete(synthesizer); lib.voicevox_wav_free(wav); diff --git a/crates/voicevox_core_c_api/tests/e2e/testcases/tts_via_audio_query.rs b/crates/voicevox_core_c_api/tests/e2e/testcases/tts_via_audio_query.rs index 32fabe3f4..f9b71308c 100644 --- a/crates/voicevox_core_c_api/tests/e2e/testcases/tts_via_audio_query.rs +++ b/crates/voicevox_core_c_api/tests/e2e/testcases/tts_via_audio_query.rs @@ -122,7 +122,7 @@ impl assert_cdylib::TestCase for TestCase { std::assert_eq!(SNAPSHOTS.output[&self.text].wav_length, wav_length); - lib.voicevox_voice_model_file_close(model); + lib.voicevox_voice_model_file_delete(model); lib.voicevox_open_jtalk_rc_delete(openjtalk); lib.voicevox_synthesizer_delete(synthesizer); lib.voicevox_json_free(audio_query); 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 a6e234eaa..3051369ed 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 @@ -136,7 +136,7 @@ impl assert_cdylib::TestCase for TestCase { audio_query_with_dict.get("kana") ); - lib.voicevox_voice_model_file_close(model); + lib.voicevox_voice_model_file_delete(model); lib.voicevox_open_jtalk_rc_delete(openjtalk); lib.voicevox_synthesizer_delete(synthesizer); lib.voicevox_user_dict_delete(dict); diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/hiroshiba/voicevoxcore/blocking/VoiceModelFile.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/hiroshiba/voicevoxcore/blocking/VoiceModelFile.java index 4c1c265b2..15410f7d6 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/hiroshiba/voicevoxcore/blocking/VoiceModelFile.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/hiroshiba/voicevoxcore/blocking/VoiceModelFile.java @@ -15,10 +15,18 @@ public class VoiceModelFile implements Closeable { private long handle; - /** ID。 */ + /** + * ID。 + * + *

{@link #close}の後でも利用可能。 + */ @Nonnull public final UUID id; - /** メタ情報。 */ + /** + * メタ情報。 + * + *

{@link #close}の後でも利用可能。 + */ @Nonnull public final SpeakerMeta[] metas; public VoiceModelFile(String modelPath) { diff --git a/crates/voicevox_core_python_api/python/voicevox_core/_rust/asyncio.pyi b/crates/voicevox_core_python_api/python/voicevox_core/_rust/asyncio.pyi index bdee4e1ee..7ae067119 100644 --- a/crates/voicevox_core_python_api/python/voicevox_core/_rust/asyncio.pyi +++ b/crates/voicevox_core_python_api/python/voicevox_core/_rust/asyncio.pyi @@ -39,7 +39,11 @@ class VoiceModelFile: ... @property def id(self) -> VoiceModelId: - """ID。""" + """ + ID。 + + :attr:`close` および :attr:`__aexit__` の後でも利用可能。 + """ ... @property def metas(self) -> list[SpeakerMeta]: @@ -47,6 +51,8 @@ class VoiceModelFile: メタ情報。 この中身を書き換えても、 ``VoiceModelFile`` としての動作には影響しない。 + + :attr:`close` および :attr:`__aexit__` の後でも利用可能。 """ ... async def __aenter__(self) -> "VoiceModelFile": ... diff --git a/crates/voicevox_core_python_api/python/voicevox_core/_rust/blocking.pyi b/crates/voicevox_core_python_api/python/voicevox_core/_rust/blocking.pyi index 58851e40a..d2719e7d1 100644 --- a/crates/voicevox_core_python_api/python/voicevox_core/_rust/blocking.pyi +++ b/crates/voicevox_core_python_api/python/voicevox_core/_rust/blocking.pyi @@ -39,7 +39,11 @@ class VoiceModelFile: ... @property def id(self) -> VoiceModelId: - """ID。""" + """ + ID。 + + :attr:`close` および :attr:`__exit__` の後でも利用可能。 + """ ... @property def metas(self) -> list[SpeakerMeta]: @@ -47,6 +51,8 @@ class VoiceModelFile: メタ情報。 この中身を書き換えても、 ``VoiceModelFile`` としての動作には影響しない。 + + :attr:`close` および :attr:`__exit__` の後でも利用可能。 """ ... def __enter__(self) -> "VoiceModelFile": ... diff --git a/docs/guide/dev/api-design.md b/docs/guide/dev/api-design.md index 6ea140a53..c3da8b588 100644 --- a/docs/guide/dev/api-design.md +++ b/docs/guide/dev/api-design.md @@ -11,6 +11,7 @@ VOICEVOX CORE の主要機能は Rust で実装されることを前提として * [`StyleId`](https://voicevox.github.io/voicevox_core/apis/rust_api/voicevox_core/struct.StyleId.html)といった[newtype](https://rust-unofficial.github.io/patterns/patterns/behavioural/newtype.html)は、そのままnewtypeとして表現するべきです。 * 例えばPythonなら[`typing.NewType`](https://docs.python.org/ja/3/library/typing.html#newtype)で表現します。 * オプショナルな引数は、キーワード引数がある言語であればキーワード引数で、ビルダースタイルが一般的な言語であればビルダースタイルで表現すべきです。 +* [`VoiceModelFile`](https://voicevox.github.io/voicevox_core/apis/rust_api/voicevox_core/nonblocking/struct.VoiceModelFile.html)の"close"後でも`id`と`metas`は利用可能であるべきです。ただしRustにおける"close"だけは、`VoiceModelFile`を`id`と`metas`に分解するような形にします。 * `Synthesizer::render`は`range: std::ops::Range`を引数に取っています。`Range`にあたる型が標準で存在し、かつそれが配列の範囲指定として用いられるようなものであれば、それを使うべきです。 * ただし例えばPythonでは、`slice`を引数に取るのは慣習にそぐわないため`start: int, stop: int`のようにすべきです。 * もし`Range`にあたる型が標準で無く、かつRustの"start"/"end"やPythonの"start"/"stop"にあたる明確な言葉が無いのであれば、誤解が生じないよう"end_exclusive"のように命名するべきです。 diff --git a/example/cpp/unix/simple_tts.cpp b/example/cpp/unix/simple_tts.cpp index 210df1549..35b3352c8 100644 --- a/example/cpp/unix/simple_tts.cpp +++ b/example/cpp/unix/simple_tts.cpp @@ -58,7 +58,7 @@ int main(int argc, char *argv[]) { std::cerr << voicevox_error_result_to_message(result) << std::endl; return 0; } - voicevox_voice_model_file_close(model); + voicevox_voice_model_file_delete(model); } std::cout << "音声生成中..." << std::endl; diff --git a/example/cpp/windows/simple_tts/simple_tts.cpp b/example/cpp/windows/simple_tts/simple_tts.cpp index 2bdc947c6..c47889dd4 100644 --- a/example/cpp/windows/simple_tts/simple_tts.cpp +++ b/example/cpp/windows/simple_tts/simple_tts.cpp @@ -70,7 +70,7 @@ int main() { OutErrorMessage(result); return 0; } - voicevox_voice_model_file_close(model); + voicevox_voice_model_file_delete(model); } std::wcout << L"音声生成中" << std::endl;