From f0a2a4662514ae31ef3abbaf1d1fdb2e26455f24 Mon Sep 17 00:00:00 2001 From: sevenc-nanashi Date: Wed, 13 Sep 2023 18:55:12 +0900 Subject: [PATCH] =?UTF-8?q?Change:=20=E6=A7=8B=E6=88=90=E3=82=92=E5=A4=89?= =?UTF-8?q?=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../voicevox_core_java_api/lib/build.gradle | 6 +- .../java/jp/hiroshiba/voicevoxcore/Dll.java | 67 ++++++++++++------- .../voicevoxcore/SynthesizerTest.java | 22 +++--- .../jp/hiroshiba/voicevoxcore/TestUtils.java | 21 ++++++ 4 files changed, 79 insertions(+), 37 deletions(-) diff --git a/crates/voicevox_core_java_api/lib/build.gradle b/crates/voicevox_core_java_api/lib/build.gradle index 3e87cceff..93cf9cecc 100644 --- a/crates/voicevox_core_java_api/lib/build.gradle +++ b/crates/voicevox_core_java_api/lib/build.gradle @@ -13,6 +13,8 @@ plugins { version = '0.0.0' +def String buildTarget = hasProperty('buildTarget') ? buildTarget : "cpu" + repositories { // Use Maven Central for resolving dependencies. mavenCentral() @@ -36,7 +38,9 @@ dependencies { // https://mvnrepository.com/artifact/jakarta.validation/jakarta.validation-api implementation group: 'jakarta.validation', name: 'jakarta.validation-api', version: '3.0.2' - implementation group: 'com.microsoft.onnxruntime', name: 'onnxruntime', version: '1.14.0' + if (buildTarget == "android") { + implementation group: 'com.microsoft.onnxruntime', name: 'onnxruntime_android', version: '1.14.0' + } } // Apply a specific Java toolchain to ease working on different environments. diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/hiroshiba/voicevoxcore/Dll.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/hiroshiba/voicevoxcore/Dll.java index e4e674205..385833b46 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/hiroshiba/voicevoxcore/Dll.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/hiroshiba/voicevoxcore/Dll.java @@ -1,6 +1,5 @@ package jp.hiroshiba.voicevoxcore; -import ai.onnxruntime.OrtEnvironment; import java.io.InputStream; import java.nio.file.Files; import java.nio.file.Path; @@ -16,16 +15,25 @@ abstract class Dll { } else { String rawOsName = System.getProperty("os.name"); String rawOsArch = System.getProperty("os.arch"); - String osName, osArch, dllName; + String osName, osArch, vvDllName, ortDllName; + String[] ortOptionalDllNames; if (rawOsName.startsWith("Win")) { osName = "windows"; - dllName = "voicevox_core_java_api.dll"; + vvDllName = "voicevox_core_java_api.dll"; + ortDllName = "onnxruntime.dll"; + ortOptionalDllNames = + new String[] {"onnxruntime_providers_shared.dll", "onnxruntime_providers_cuda.dll"}; } else if (rawOsName.startsWith("Mac")) { osName = "macos"; - dllName = "libvoicevox_core_java_api.dylib"; + vvDllName = "libvoicevox_core_java_api.dylib"; + ortDllName = "libonnxruntime.1.14.0.dylib"; + ortOptionalDllNames = new String[] {}; } else if (rawOsName.startsWith("Linux")) { osName = "linux"; - dllName = "libvoicevox_core_java_api.so"; + vvDllName = "libvoicevox_core_java_api.so"; + ortDllName = "libonnxruntime.so.1.14.0"; + ortOptionalDllNames = + new String[] {"libonnxruntime_providers_shared.so", "libonnxruntime_providers_cuda.so"}; } else { throw new RuntimeException("Unsupported OS: " + rawOsName); } @@ -42,27 +50,40 @@ abstract class Dll { } String target = osName + "-" + osArch; - // ONNX Runtime の DLL を読み込む。 - OrtEnvironment.getEnvironment(); - try (InputStream in = Dll.class.getResourceAsStream("/dll/" + target + "/" + dllName)) { - if (in == null) { - try { - // フォールバック。開発用。 - System.loadLibrary("voicevox_core_java_api"); - } catch (UnsatisfiedLinkError e) { - throw new RuntimeException("Failed to load Voicevox Core DLL for " + target, e); - } - } else { - Path tempDir = Paths.get(System.getProperty("java.io.tmpdir")); - Path dllPath = tempDir.resolve(dllName); - dllPath.toFile().deleteOnExit(); - Files.copy(in, dllPath); + loadDll(target, ortDllName, "onnxruntime"); + for (String dllName : ortOptionalDllNames) { + loadDll(target, dllName); + } + loadDll(target, vvDllName, "voicevox_core_java_api"); + } + } + + private static void loadDll(String target, String dllName) { + loadDll(target, dllName, null); + } - System.load(dllPath.toAbsolutePath().toString()); + private static void loadDll(String target, String dllName, String fallbackDllName) { + String resourceRoot = "/dll/" + target + "/"; + try (InputStream in = Dll.class.getResourceAsStream(resourceRoot + dllName)) { + if (in == null) { + if (fallbackDllName == null) { + return; + } + try { + System.loadLibrary(fallbackDllName); + } catch (UnsatisfiedLinkError e) { + throw new RuntimeException("Failed to load " + dllName + " for " + target, e); } - } catch (Exception e) { - throw new RuntimeException("Failed to load Voicevox Core DLL for " + target, e); + } else { + Path tempDir = Paths.get(System.getProperty("java.io.tmpdir")); + Path dllPath = tempDir.resolve(dllName); + dllPath.toFile().deleteOnExit(); + Files.copy(in, dllPath); + + System.load(dllPath.toAbsolutePath().toString()); } + } catch (Exception e) { + throw new RuntimeException("Failed to load " + dllName + " for " + target, e); } } } diff --git a/crates/voicevox_core_java_api/lib/src/test/java/jp/hiroshiba/voicevoxcore/SynthesizerTest.java b/crates/voicevox_core_java_api/lib/src/test/java/jp/hiroshiba/voicevoxcore/SynthesizerTest.java index fe9b8220b..4172d310c 100644 --- a/crates/voicevox_core_java_api/lib/src/test/java/jp/hiroshiba/voicevoxcore/SynthesizerTest.java +++ b/crates/voicevox_core_java_api/lib/src/test/java/jp/hiroshiba/voicevoxcore/SynthesizerTest.java @@ -4,7 +4,6 @@ */ package jp.hiroshiba.voicevoxcore; -import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.List; @@ -37,19 +36,19 @@ boolean checkAllMoras( void checkModel() { VoiceModel model = loadModel(); OpenJtalk openJtalk = loadOpenJtalk(); - Synthesizer synthesizer = Synthesizer.builder(openJtalk).build(); + Synthesizer synthesizer = + Synthesizer.builder(openJtalk).accelerationMode(Synthesizer.AccelerationMode.CPU).build(); + synthesizer.loadVoiceModel(model); + assertTrue(synthesizer.isLoadedVoiceModel(model.id)); - synthesizer.unloadVoiceModel(model.id); - assertFalse(synthesizer.isLoadedVoiceModel(model.id)); } @Test void checkAudioQuery() { VoiceModel model = loadModel(); - OpenJtalk openJtalk = loadOpenJtalk(); - Synthesizer synthesizer = Synthesizer.builder(openJtalk).build(); - synthesizer.loadVoiceModel(model); + Synthesizer synthesizer = createSynthesizer(); + AudioQuery query = synthesizer.createAudioQuery("こんにちは", model.metas[0].styles[0].id).execute(); synthesizer.synthesis(query, model.metas[0].styles[0].id).execute(); @@ -58,9 +57,8 @@ void checkAudioQuery() { @Test void checkAccentPhrases() { VoiceModel model = loadModel(); - OpenJtalk openJtalk = loadOpenJtalk(); - Synthesizer synthesizer = Synthesizer.builder(openJtalk).build(); - synthesizer.loadVoiceModel(model); + Synthesizer synthesizer = createSynthesizer(); + List accentPhrases = synthesizer.createAccentPhrases("こんにちは", model.metas[0].styles[0].id).execute(); List accentPhrases2 = @@ -88,9 +86,7 @@ void checkAccentPhrases() { @Test void checkTts() { VoiceModel model = loadModel(); - OpenJtalk openJtalk = loadOpenJtalk(); - Synthesizer synthesizer = Synthesizer.builder(openJtalk).build(); - synthesizer.loadVoiceModel(model); + Synthesizer synthesizer = createSynthesizer(); synthesizer.tts("こんにちは", model.metas[0].styles[0].id).execute(); } } diff --git a/crates/voicevox_core_java_api/lib/src/test/java/jp/hiroshiba/voicevoxcore/TestUtils.java b/crates/voicevox_core_java_api/lib/src/test/java/jp/hiroshiba/voicevoxcore/TestUtils.java index 670eddbdb..c4d861804 100644 --- a/crates/voicevox_core_java_api/lib/src/test/java/jp/hiroshiba/voicevoxcore/TestUtils.java +++ b/crates/voicevox_core_java_api/lib/src/test/java/jp/hiroshiba/voicevoxcore/TestUtils.java @@ -3,7 +3,14 @@ import java.io.File; class TestUtils { + VoiceModel voiceModel = null; + OpenJtalk openJtalk = null; + Synthesizer synthesizer = null; + VoiceModel loadModel() { + if (voiceModel != null) { + return voiceModel; + } // cwdはvoicevox_core/crates/voicevox_core_java_api/lib String cwd = System.getProperty("user.dir"); File path = new File(cwd + "/../../../model/sample.vvm"); @@ -16,6 +23,9 @@ VoiceModel loadModel() { } OpenJtalk loadOpenJtalk() { + if (openJtalk != null) { + return openJtalk; + } String cwd = System.getProperty("user.dir"); File path = new File(cwd + "/../../test_util/data/open_jtalk_dic_utf_8-1.11"); @@ -25,4 +35,15 @@ OpenJtalk loadOpenJtalk() { throw new RuntimeException(e); } } + + Synthesizer createSynthesizer() { + if (synthesizer != null) { + return synthesizer; + } + OpenJtalk openJtalk = loadOpenJtalk(); + Synthesizer synthesizer = + Synthesizer.builder(openJtalk).accelerationMode(Synthesizer.AccelerationMode.CPU).build(); + synthesizer.loadVoiceModel(loadModel()); + return synthesizer; + } }