Skip to content

Commit

Permalink
Improve: Java APIを色々改善 (#673)
Browse files Browse the repository at this point in the history
  • Loading branch information
sevenc-nanashi authored Nov 7, 2023
1 parent 9ae1110 commit 4c4b767
Show file tree
Hide file tree
Showing 19 changed files with 791 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package jp.hiroshiba.voicevoxcore;

import com.google.gson.Gson;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
import jakarta.annotation.Nonnull;

/** VOICEVOX CORE自体の情報。 */
public class GlobalInfo extends Dll {
/**
* ライブラリのバージョン。
*
* @return ライブラリのバージョン。
*/
@Nonnull
public static String getVersion() {
return rsGetVersion();
}

/**
* このライブラリで利用可能なデバイスの情報を取得する。
*
* @return {@link SupportedDevices}。
*/
@Nonnull
public static SupportedDevices getSupportedDevices() {
Gson gson = new Gson();
String supportedDevicesJson = rsGetSupportedDevicesJson();
SupportedDevices supportedDevices = gson.fromJson(supportedDevicesJson, SupportedDevices.class);
if (supportedDevices == null) {
throw new NullPointerException("supported_devices");
}
return supportedDevices;
}

@Nonnull
private static native String rsGetVersion();

@Nonnull
private static native String rsGetSupportedDevicesJson();

/**
* このライブラリで利用可能なデバイスの情報。
*
* <p>あくまで本ライブラリが対応しているデバイスの情報であることに注意。GPUが使える環境ではなかったとしても {@link #cuda} や {@link #dml} は {@code
* true} を示しうる。
*/
public static class SupportedDevices {
/**
* CPUが利用可能。
*
* <p>常に <code>true</code> 。
*/
@SerializedName("cpu")
@Expose
@Nonnull
public final boolean cpu;

/**
* CUDAが利用可能。
*
* <p>ONNX Runtimeの <a href=
* "https://onnxruntime.ai/docs/execution-providers/CUDA-ExecutionProvider.html"
* target="_blank">CUDAExecutionProvider</a>に対応する。 必要な環境についてはそちらを参照。
*/
@SerializedName("cuda")
@Expose
@Nonnull
public final boolean cuda;

/**
* DirectMLが利用可能。
*
* <p>ONNX Runtimeの <a href=
* "https://onnxruntime.ai/docs/execution-providers/DirectML-ExecutionProvider.html"
* target="_blank">DmlExecutionProvider</a>に対応する。 必要な環境についてはそちらを参照。
*/
@SerializedName("dml")
@Expose
@Nonnull
public final boolean dml;

private SupportedDevices() {
this.cpu = false;
this.cuda = false;
this.dml = false;
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package jp.hiroshiba.voicevoxcore;

/** テキスト解析機としてのOpen JTalk。 */
public class OpenJtalk extends Dll {
private long handle;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,36 @@ protected void finalize() throws Throwable {
super.finalize();
}

/**
* ハードウェアアクセラレーションがGPUモードかどうかを返す。
*
* @return ハードウェアアクセラレーションがGPUモードかどうか。
*/
public boolean isGpuMode() {
return rsIsGpuMode();
}

/**
* メタ情報を取得する。
*
* @return メタ情報。
*/
@Nonnull
public VoiceModel.SpeakerMeta[] metas() {
Gson gson = new Gson();
String metasJson = rsGetMetasJson();
VoiceModel.SpeakerMeta[] rawMetas = gson.fromJson(metasJson, VoiceModel.SpeakerMeta[].class);
if (rawMetas == null) {
throw new NullPointerException("metas");
}
return rawMetas;
}

/**
* モデルを読み込む。
*
* @param voiceModel 読み込むモデル。
* @throws InvalidModelDataException 無効なモデルデータの場合。
*/
public void loadVoiceModel(VoiceModel voiceModel) throws InvalidModelDataException {
rsLoadVoiceModel(voiceModel);
Expand Down Expand Up @@ -59,6 +85,7 @@ public boolean isLoadedVoiceModel(String voiceModelId) {
* @param kana AquesTalk風記法。
* @param styleId スタイルID。
* @return {@link AudioQuery}。
* @throws InferenceFailedException 推論に失敗した場合。
*/
@Nonnull
public AudioQuery createAudioQueryFromKana(String kana, int styleId)
Expand All @@ -82,6 +109,7 @@ public AudioQuery createAudioQueryFromKana(String kana, int styleId)
* @param text 日本語のテキスト。
* @param styleId スタイルID。
* @return {@link AudioQuery}。
* @throws InferenceFailedException 推論に失敗した場合。
*/
@Nonnull
public AudioQuery createAudioQuery(String text, int styleId) throws InferenceFailedException {
Expand All @@ -104,6 +132,7 @@ public AudioQuery createAudioQuery(String text, int styleId) throws InferenceFai
* @param kana AquesTalk風記法。
* @param styleId スタイルID。
* @return {@link AccentPhrase} のリスト。
* @throws InferenceFailedException 推論に失敗した場合。
*/
@Nonnull
public List<AccentPhrase> createAccentPhrasesFromKana(String kana, int styleId)
Expand All @@ -123,6 +152,7 @@ public List<AccentPhrase> createAccentPhrasesFromKana(String kana, int styleId)
* @param text 日本語のテキスト。
* @param styleId スタイルID。
* @return {@link AccentPhrase} のリスト。
* @throws InferenceFailedException 推論に失敗した場合。
*/
@Nonnull
public List<AccentPhrase> createAccentPhrases(String text, int styleId)
Expand All @@ -142,6 +172,7 @@ public List<AccentPhrase> createAccentPhrases(String text, int styleId)
* @param accentPhrases 変更元のアクセント句の配列。
* @param styleId スタイルID。
* @return 変更後のアクセント句の配列。
* @throws InferenceFailedException 推論に失敗した場合。
*/
@Nonnull
public List<AccentPhrase> replaceMoraData(List<AccentPhrase> accentPhrases, int styleId)
Expand All @@ -161,6 +192,7 @@ public List<AccentPhrase> replaceMoraData(List<AccentPhrase> accentPhrases, int
* @param accentPhrases 変更元のアクセント句の配列。
* @param styleId スタイルID。
* @return 変更後のアクセント句の配列。
* @throws InferenceFailedException 推論に失敗した場合。
*/
@Nonnull
public List<AccentPhrase> replacePhonemeLength(List<AccentPhrase> accentPhrases, int styleId)
Expand All @@ -180,6 +212,7 @@ public List<AccentPhrase> replacePhonemeLength(List<AccentPhrase> accentPhrases,
* @param accentPhrases 変更元のアクセント句の配列。
* @param styleId スタイルID。
* @return 変更後のアクセント句の配列。
* @throws InferenceFailedException 推論に失敗した場合。
*/
@Nonnull
public List<AccentPhrase> replaceMoraPitch(List<AccentPhrase> accentPhrases, int styleId)
Expand Down Expand Up @@ -234,6 +267,11 @@ public TtsConfigurator tts(String text, int styleId) {

private native void rsNew(OpenJtalk openJtalk, Builder builder);

private native boolean rsIsGpuMode();

@Nonnull
private native String rsGetMetasJson();

private native void rsLoadVoiceModel(VoiceModel voiceModel) throws InvalidModelDataException;

private native void rsUnloadVoiceModel(String voiceModelId);
Expand Down Expand Up @@ -382,6 +420,7 @@ public SynthesisConfigurator interrogativeUpspeak(boolean interrogativeUpspeak)
* {@link AudioQuery} から音声合成する。
*
* @return 音声データ。
* @throws InferenceFailedException 推論に失敗した場合。
*/
@Nonnull
public byte[] execute() throws InferenceFailedException {
Expand Down Expand Up @@ -426,6 +465,7 @@ public TtsFromKanaConfigurator interrogativeUpspeak(boolean interrogativeUpspeak
* {@link AudioQuery} から音声合成する。
*
* @return 音声データ。
* @throws InferenceFailedException 推論に失敗した場合。
*/
@Nonnull
public byte[] execute() throws InferenceFailedException {
Expand Down Expand Up @@ -468,6 +508,7 @@ public TtsConfigurator interrogativeUpspeak(boolean interrogativeUpspeak) {
* {@link AudioQuery} から音声合成する。
*
* @return 音声データ。
* @throws InferenceFailedException 推論に失敗した場合。
*/
@Nonnull
public byte[] execute() throws InferenceFailedException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ public void importDict(UserDict dict) {
* ユーザー辞書を読み込む。
*
* @param path ユーザー辞書のパス。
* @throws LoadUserDictException ユーザー辞書を読み込めなかった場合。
*/
public void load(String path) throws LoadUserDictException {
rsLoad(path);
Expand All @@ -83,6 +84,7 @@ public void load(String path) throws LoadUserDictException {
* ユーザー辞書を保存する。
*
* @param path ユーザー辞書のパス。
* @throws SaveUserDictException ユーザー辞書を保存できなかった場合。
*/
public void save(String path) throws SaveUserDictException {
rsSave(path);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* GlobalInfoのテスト。
*/
package jp.hiroshiba.voicevoxcore;

import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;

import org.junit.jupiter.api.Test;

class InfoTest {
@Test
void checkVersion() {
assertNotNull(GlobalInfo.getVersion());
}

@Test
void checkSupportedDevices() {
GlobalInfo.SupportedDevices supportedDevices = GlobalInfo.getSupportedDevices();

assertNotNull(supportedDevices);
assertTrue(supportedDevices.cpu);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,14 @@ interface MoraCheckCallback {
boolean check(Mora mora, Mora otherMora);
}

@Test
void checkIsGpuMode() {
OpenJtalk openJtalk = loadOpenJtalk();
Synthesizer synthesizer =
Synthesizer.builder(openJtalk).accelerationMode(Synthesizer.AccelerationMode.CPU).build();
assertFalse(synthesizer.isGpuMode());
}

boolean checkAllMoras(
List<AccentPhrase> accentPhrases,
List<AccentPhrase> otherAccentPhrases,
Expand All @@ -40,9 +48,17 @@ void checkModel() throws InvalidModelDataException {
VoiceModel model = loadModel();
OpenJtalk openJtalk = loadOpenJtalk();
Synthesizer synthesizer = Synthesizer.builder(openJtalk).build();

assertTrue(synthesizer.metas().length == 0);

synthesizer.loadVoiceModel(model);

assertTrue(synthesizer.metas().length >= 1);
assertTrue(synthesizer.isLoadedVoiceModel(model.id));

synthesizer.unloadVoiceModel(model.id);

assertTrue(synthesizer.metas().length == 0);
assertFalse(synthesizer.isLoadedVoiceModel(model.id));
}

Expand Down
22 changes: 22 additions & 0 deletions crates/voicevox_core_java_api/src/info.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
use crate::common::throw_if_err;
use jni::{sys::jobject, JNIEnv};
#[no_mangle]
extern "system" fn Java_jp_hiroshiba_voicevoxcore_GlobalInfo_rsGetVersion(
env: JNIEnv<'_>,
) -> jobject {
throw_if_err(env, std::ptr::null_mut(), |env| {
let version = env.new_string(env!("CARGO_PKG_VERSION"))?;
Ok(version.into_raw())
})
}
#[no_mangle]
extern "system" fn Java_jp_hiroshiba_voicevoxcore_GlobalInfo_rsGetSupportedDevicesJson(
env: JNIEnv<'_>,
) -> jobject {
throw_if_err(env, std::ptr::null_mut(), |env| {
let supported_devices = voicevox_core::SupportedDevices::create()?;
let json = serde_json::to_string(&supported_devices).expect("Should not fail");
let json = env.new_string(json)?;
Ok(json.into_raw())
})
}
1 change: 1 addition & 0 deletions crates/voicevox_core_java_api/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
mod common;
mod info;
mod open_jtalk;
mod synthesizer;
mod user_dict;
Expand Down
31 changes: 31 additions & 0 deletions crates/voicevox_core_java_api/src/synthesizer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,37 @@ unsafe extern "system" fn Java_jp_hiroshiba_voicevoxcore_Synthesizer_rsNew<'loca
Ok(())
})
}
#[no_mangle]
unsafe extern "system" fn Java_jp_hiroshiba_voicevoxcore_Synthesizer_rsIsGpuMode<'local>(
env: JNIEnv<'local>,
this: JObject<'local>,
) -> jboolean {
throw_if_err(env, false, |env| {
let internal = env
.get_rust_field::<_, _, Arc<voicevox_core::Synthesizer>>(&this, "handle")?
.clone();

Ok(internal.is_gpu_mode())
})
.into()
}
#[no_mangle]
unsafe extern "system" fn Java_jp_hiroshiba_voicevoxcore_Synthesizer_rsGetMetasJson<'local>(
env: JNIEnv<'local>,
this: JObject<'local>,
) -> jobject {
throw_if_err(env, std::ptr::null_mut(), |env| {
let internal = env
.get_rust_field::<_, _, Arc<voicevox_core::Synthesizer>>(&this, "handle")?
.clone();

let metas_json = serde_json::to_string(&internal.metas()).expect("should not fail");

let j_metas_json = env.new_string(metas_json)?;

Ok(j_metas_json.into_raw())
})
}

#[no_mangle]
unsafe extern "system" fn Java_jp_hiroshiba_voicevoxcore_Synthesizer_rsLoadVoiceModel<'local>(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ class Synthesizer:
"""ハードウェアアクセラレーションがGPUモードかどうか。"""
...
@property
def metas(self) -> SpeakerMeta:
def metas(self) -> List[SpeakerMeta]:
"""メタ情報。"""
...
async def load_voice_model(self, model: VoiceModel) -> None:
Expand Down
12 changes: 12 additions & 0 deletions example/kotlin/.gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#
# https://help.github.com/articles/dealing-with-line-endings/
#
# Linux start script should use lf
./gradlew text eol=lf linguist-vendored linguist-generated

# These are Windows script files and should use crlf
*.bat text eol=crlf

./gradlew linguist-vendored linguist-generated
./gradlew.bat linguist-vendored linguist-generated
./gradle/wrapper/gradle-wrapper.jar linguist-vendored linguist-generated
Loading

0 comments on commit 4c4b767

Please sign in to comment.