From 1c2e5db321a4d860a87c378a913d0b16718ed765 Mon Sep 17 00:00:00 2001 From: sevenc-nanashi Date: Sat, 29 Jul 2023 23:42:50 +0900 Subject: [PATCH 01/99] =?UTF-8?q?Add:=20Java+gradle=E3=81=AE=E3=82=BB?= =?UTF-8?q?=E3=83=83=E3=83=88=E3=82=A2=E3=83=83=E3=83=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cargo.lock | 147 +++++++++-- Cargo.toml | 1 + crates/voicevox_core_java_api/.gitattributes | 9 + crates/voicevox_core_java_api/.gitignore | 7 + crates/voicevox_core_java_api/Cargo.toml | 13 + .../gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 63375 bytes .../gradle/wrapper/gradle-wrapper.properties | 7 + crates/voicevox_core_java_api/gradlew | 248 ++++++++++++++++++ crates/voicevox_core_java_api/gradlew.bat | 92 +++++++ .../voicevox_core_java_api/lib/build.gradle | 41 +++ .../jp/Hiroshiba/VoicevoxCore/OpenJtalk.java | 9 + .../Hiroshiba/VoicevoxCore/OpenJtalkTest.java | 14 + crates/voicevox_core_java_api/settings.gradle | 14 + crates/voicevox_core_java_api/src/lib.rs | 13 + 14 files changed, 586 insertions(+), 29 deletions(-) create mode 100644 crates/voicevox_core_java_api/.gitattributes create mode 100644 crates/voicevox_core_java_api/.gitignore create mode 100644 crates/voicevox_core_java_api/Cargo.toml create mode 100644 crates/voicevox_core_java_api/gradle/wrapper/gradle-wrapper.jar create mode 100644 crates/voicevox_core_java_api/gradle/wrapper/gradle-wrapper.properties create mode 100755 crates/voicevox_core_java_api/gradlew create mode 100644 crates/voicevox_core_java_api/gradlew.bat create mode 100644 crates/voicevox_core_java_api/lib/build.gradle create mode 100644 crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/OpenJtalk.java create mode 100644 crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/OpenJtalkTest.java create mode 100644 crates/voicevox_core_java_api/settings.gradle create mode 100644 crates/voicevox_core_java_api/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index a783bb6d7..9590119de 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -509,6 +509,12 @@ dependencies = [ "jobserver", ] +[[package]] +name = "cesu8" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" + [[package]] name = "cexpr" version = "0.6.0" @@ -679,6 +685,16 @@ dependencies = [ "tracing-error", ] +[[package]] +name = "combine" +version = "4.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35ed6e9d84f0b51a7f52daf1c7d71dd136fd7a3f41a8462b8cdb8c78d920fad4" +dependencies = [ + "bytes 1.1.0", + "memchr", +] + [[package]] name = "concolor" version = "0.0.11" @@ -1811,6 +1827,28 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc" +[[package]] +name = "jni" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" +dependencies = [ + "cesu8", + "cfg-if", + "combine", + "jni-sys", + "log", + "thiserror", + "walkdir", + "windows-sys 0.45.0", +] + +[[package]] +name = "jni-sys" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" + [[package]] name = "jobserver" version = "0.1.25" @@ -3017,6 +3055,15 @@ version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + [[package]] name = "schannel" version = "0.1.20" @@ -4051,6 +4098,14 @@ dependencies = [ "voicevox_core", ] +[[package]] +name = "voicevox_core_java_api" +version = "0.0.0" +dependencies = [ + "jni", + "voicevox_core", +] + [[package]] name = "voicevox_core_python_api" version = "0.0.0" @@ -4085,6 +4140,16 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" +[[package]] +name = "walkdir" +version = "2.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698" +dependencies = [ + "same-file", + "winapi-util", +] + [[package]] name = "want" version = "0.3.0" @@ -4259,13 +4324,13 @@ version = "0.43.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04662ed0e3e5630dfa9b26e4cb823b817f1a9addda855d973a9458c236556244" dependencies = [ - "windows_aarch64_gnullvm 0.42.0", - "windows_aarch64_msvc 0.42.0", - "windows_i686_gnu 0.42.0", - "windows_i686_msvc 0.42.0", - "windows_x86_64_gnu 0.42.0", - "windows_x86_64_gnullvm 0.42.0", - "windows_x86_64_msvc 0.42.0", + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", ] [[package]] @@ -4287,13 +4352,22 @@ version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" dependencies = [ - "windows_aarch64_gnullvm 0.42.0", - "windows_aarch64_msvc 0.42.0", - "windows_i686_gnu 0.42.0", - "windows_i686_msvc 0.42.0", - "windows_x86_64_gnu 0.42.0", - "windows_x86_64_gnullvm 0.42.0", - "windows_x86_64_msvc 0.42.0", + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets 0.42.2", ] [[package]] @@ -4302,7 +4376,22 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets", + "windows-targets 0.48.0", +] + +[[package]] +name = "windows-targets" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", ] [[package]] @@ -4322,9 +4411,9 @@ dependencies = [ [[package]] name = "windows_aarch64_gnullvm" -version = "0.42.0" +version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" [[package]] name = "windows_aarch64_gnullvm" @@ -4340,9 +4429,9 @@ checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" [[package]] name = "windows_aarch64_msvc" -version = "0.42.0" +version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" [[package]] name = "windows_aarch64_msvc" @@ -4358,9 +4447,9 @@ checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" [[package]] name = "windows_i686_gnu" -version = "0.42.0" +version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" [[package]] name = "windows_i686_gnu" @@ -4376,9 +4465,9 @@ checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" [[package]] name = "windows_i686_msvc" -version = "0.42.0" +version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" [[package]] name = "windows_i686_msvc" @@ -4394,9 +4483,9 @@ checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" [[package]] name = "windows_x86_64_gnu" -version = "0.42.0" +version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" [[package]] name = "windows_x86_64_gnu" @@ -4406,9 +4495,9 @@ checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" [[package]] name = "windows_x86_64_gnullvm" -version = "0.42.0" +version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" [[package]] name = "windows_x86_64_gnullvm" @@ -4424,9 +4513,9 @@ checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" [[package]] name = "windows_x86_64_msvc" -version = "0.42.0" +version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" [[package]] name = "windows_x86_64_msvc" diff --git a/Cargo.toml b/Cargo.toml index fc5c52efc..509738aa8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,6 +5,7 @@ members = [ "crates/voicevox_core", "crates/voicevox_core_c_api", "crates/voicevox_core_python_api", + "crates/voicevox_core_java_api", "crates/xtask" ] diff --git a/crates/voicevox_core_java_api/.gitattributes b/crates/voicevox_core_java_api/.gitattributes new file mode 100644 index 000000000..097f9f98d --- /dev/null +++ b/crates/voicevox_core_java_api/.gitattributes @@ -0,0 +1,9 @@ +# +# https://help.github.com/articles/dealing-with-line-endings/ +# +# Linux start script should use lf +/gradlew text eol=lf + +# These are Windows script files and should use crlf +*.bat text eol=crlf + diff --git a/crates/voicevox_core_java_api/.gitignore b/crates/voicevox_core_java_api/.gitignore new file mode 100644 index 000000000..832d37e5b --- /dev/null +++ b/crates/voicevox_core_java_api/.gitignore @@ -0,0 +1,7 @@ +# Ignore Gradle project-specific cache directory +.gradle + +# Ignore Gradle build output directory +build + +!lib diff --git a/crates/voicevox_core_java_api/Cargo.toml b/crates/voicevox_core_java_api/Cargo.toml new file mode 100644 index 000000000..af09ef378 --- /dev/null +++ b/crates/voicevox_core_java_api/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "voicevox_core_java_api" +version.workspace = true +edition.workspace = true +publish.workspace = true + +[lib] +crate-type = ["cdylib"] + +[dependencies] +jni = "0.21.1" +voicevox_core.workspace = true + diff --git a/crates/voicevox_core_java_api/gradle/wrapper/gradle-wrapper.jar b/crates/voicevox_core_java_api/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..033e24c4cdf41af1ab109bc7f253b2b887023340 GIT binary patch literal 63375 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≫L+crb^Bz zc+Nw%zgpZ6>!A3%lau!Pw6`Y#WPVBtAfKSsqwYDWQK-~ zz(mx=nJ6-8t`YXB{6gaZ%G}Dmn&o500Y}2Rd?e&@=hBEmB1C=$OMBfxX__2c2O4K2#(0ksclP$SHp*8jq-1&(<6(#=6&H`Nlc2RVC4->r6U}sTY<1? zn@tv7XwUs-c>Lcmrm5AE0jHI5={WgHIow6cX=UK)>602(=arbuAPZ37;{HTJSIO%9EL`Et5%J7$u_NaC(55x zH^qX^H}*RPDx)^c46x>js=%&?y?=iFs^#_rUl@*MgLD92E5y4B7#EDe9yyn*f-|pQ zi>(!bIg6zY5fLSn@;$*sN|D2A{}we*7+2(4&EhUV%Qqo5=uuN^xt_hll7=`*mJq6s zCWUB|s$)AuS&=)T&_$w>QXHqCWB&ndQ$y4-9fezybZb0bYD^zeuZ>WZF{rc>c4s`` zgKdppTB|o>L1I1hAbnW%H%EkFt%yWC|0~+o7mIyFCTyb?@*Ho)eu(x`PuO8pLikN> z6YeI`V?AUWD(~3=8>}a6nZTu~#QCK(H0+4!ql3yS`>JX;j4+YkeG$ZTm33~PLa3L} zksw7@%e-mBM*cGfz$tS4LC^SYVdBLsR}nAprwg8h2~+Cv*W0%izK+WPVK}^SsL5R_ zpA}~G?VNhJhqx2he2;2$>7>DUB$wN9_-adL@TqVLe=*F8Vsw-yho@#mTD6*2WAr6B zjtLUh`E(;#p0-&$FVw(r$hn+5^Z~9J0}k;j$jL1;?2GN9s?}LASm?*Rvo@?E+(}F& z+=&M-n`5EIz%%F^e)nnWjkQUdG|W^~O|YeY4Fz}>qH2juEere}vN$oJN~9_Th^&b{ z%IBbET*E8%C@jLTxV~h#mxoRrJCF{!CJOghjuKOyl_!Jr?@4Upo7u>fTGtfm|CH2v z&9F+>;6aFbYXLj3{yZ~Yn1J2%!)A3~j2$`jOy{XavW@t)g}}KUVjCWG0OUc7aBc=2 zR3^u=dT47=5SmT{K1aGaVZkOx|24T-J0O$b9dfB25J|7yb6frwS6wZ1^y%EWOm}S< zc1SdYhfsdLG*FB-;!QLV3D!d~hnXTGVQVck9x%=B(Kk8c3y%f0nR95_TbY;l=obSl zEE@fp0|8Q$b3(+DXh?d0FEloGhO0#11CLQT5qtEckBLe-VN-I>9ys}PVK0r;0!jIG zH_q$;a`3Xv9P_V2ekV1SMzd#SKo<1~Dq2?M{(V;AwhH_2x@mN$=|=cG0<3o^j_0OF z7|WJ-f2G=7sA4NVGU2X5`o*D2T7(MbmZ2(oipooE{R?9!{WxX!%ofhsrPAxoIk!Kr z>I$a{Zq=%KaLrDCIL^gmA3z{2z%Wkr)b$QHcNUA^QwydWMJmxymO0QS22?mo%4(Md zgME(zE}ub--3*wGjV`3eBMCQG-@Gel1NKZDGuqobN|mAt0{@ZC9goI|BSmGBTUZ(`Xt z^e2LiMg?6E?G*yw(~K8lO(c4)RY7UWxrXzW^iCg-P41dUiE(i+gDmmAoB?XOB}+Ln z_}rApiR$sqNaT4frw69Wh4W?v(27IlK$Toy<1o)GeF+sGzYVeJ`F)3`&2WDi^_v67 zg;@ehwl3=t+}(DJtOYO!s`jHyo-}t@X|U*9^sIfaZfh;YLqEFmZ^E;$_XK}%eq;>0 zl?+}*kh)5jGA}3daJ*v1knbW0GusR1+_xD`MFPZc3qqYMXd>6*5?%O5pC7UVs!E-` zuMHc6igdeFQ`plm+3HhP)+3I&?5bt|V8;#1epCsKnz0%7m9AyBmz06r90n~9o;K30 z=fo|*`Qq%dG#23bVV9Jar*zRcV~6fat9_w;x-quAwv@BkX0{9e@y0NB(>l3#>82H6 z^US2<`=M@6zX=Pz>kb8Yt4wmeEo%TZ=?h+KP2e3U9?^Nm+OTx5+mVGDvgFee%}~~M zK+uHmj44TVs}!A}0W-A92LWE%2=wIma(>jYx;eVB*%a>^WqC7IVN9{o?iw{e4c=CG zC#i=cRJZ#v3 zF^9V+7u?W=xCY%2dvV_0dCP%5)SH*Xm|c#rXhwEl*^{Ar{NVoK*H6f5qCSy`+|85e zjGaKqB)p7zKNKI)iWe6A9qkl=rTjs@W1Crh(3G57qdT0w2ig^{*xerzm&U>YY{+fZbkQ#;^<$JniUifmAuEd^_M(&?sTrd(a*cD! zF*;`m80MrZ^> zaF{}rDhEFLeH#`~rM`o903FLO?qw#_Wyb5}13|0agjSTVkSI6Uls)xAFZifu@N~PM zQ%o?$k)jbY0u|45WTLAirUg3Zi1E&=G#LnSa89F3t3>R?RPcmkF}EL-R!OF_r1ZN` z?x-uHH+4FEy>KrOD-$KHg3$-Xl{Cf0;UD4*@eb~G{CK-DXe3xpEEls?SCj^p z$Uix(-j|9f^{z0iUKXcZQen}*`Vhqq$T?^)Ab2i|joV;V-qw5reCqbh(8N)c%!aB< zVs+l#_)*qH_iSZ_32E~}>=wUO$G_~k0h@ch`a6Wa zsk;<)^y=)cPpHt@%~bwLBy;>TNrTf50BAHUOtt#9JRq1ro{w80^sm-~fT>a$QC;<| zZIN%&Uq>8`Js_E((_1sewXz3VlX|-n8XCfScO`eL|H&2|BPZhDn}UAf_6s}|!XpmUr90v|nCutzMjb9|&}#Y7fj_)$alC zM~~D6!dYxhQof{R;-Vp>XCh1AL@d-+)KOI&5uKupy8PryjMhTpCZnSIQ9^Aq+7=Mb zCYCRvm4;H=Q8nZWkiWdGspC_Wvggg|7N`iED~Eap)Th$~wsxc(>(KI>{i#-~Dd8iQ zzonqc9DW1w4a*}k`;rxykUk+~N)|*I?@0901R`xy zN{20p@Ls<%`1G1Bx87Vm6Z#CA`QR(x@t8Wc?tpaunyV^A*-9K9@P>hAWW9Ev)E$gb z<(t?Te6GcJX2&0% z403pe>e)>m-^qlJU^kYIH)AutgOnq!J>FoMXhA-aEx-((7|(*snUyxa+5$wx8FNxS zKuVAVWArlK#kDzEM zqR?&aXIdyvxq~wF?iYPho*(h?k zD(SBpRDZ}z$A})*Qh!9&pZZRyNixD!8)B5{SK$PkVET(yd<8kImQ3ILe%jhx8Ga-1 zE}^k+Eo^?c4Y-t2_qXiVwW6i9o2qosBDj%DRPNT*UXI0=D9q{jB*22t4HHcd$T&Xi zT=Vte*Gz2E^qg%b7ev04Z&(;=I4IUtVJkg<`N6i7tjUn-lPE(Y4HPyJKcSjFnEzCH zPO(w%LmJ_=D~}PyfA91H4gCaf-qur3_KK}}>#9A}c5w@N;-#cHph=x}^mQ3`oo`Y$ope#)H9(kQK zGyt<7eNPuSAs$S%O>2ElZ{qtDIHJ!_THqTwcc-xfv<@1>IJ;YTv@!g-zDKBKAH<

Zet1e^8c}8fE97XH}+lF{qbF<`Y%dU|I!~Y`ZrVfKX82i z)(%!Tcf~eE^%2_`{WBPGPU@1NB5SCXe1sAI<4&n1IwO{&S$ThWn37heGOSW%nW7*L zxh0WK!E7zh%6yF-7%~l@I~b`2=*$;RYbi(I#zp$gL_d39U4A)KuB( zcS0bt48&%G_I~( zL(}w&2NA6#$=|g)J+-?ehHflD^lr77ngdz=dszFI;?~ZxeJv=gsm?4$$6#V==H{fa zqO!EkT>1-OQSJoX)cN}XsB;shvrHRwTH(I2^Ah4|rizn!V7T7fLh~Z<`Q+?zEMVxh z$=-x^RR*PlhkV_8mshTvs+zmZWY&Jk{9LX0Nx|+NAEq-^+Rh|ZlinVZ=e8=`WQt;e@= zPU}^1cG*O;G7l{Y#nl znp`y%CO_SC7gk0i0gY&phM04Y)~vU0!3$V$2T+h(1ZS+cCgc zaC?3M;B48^faGo>h~--#FNFauH?0BJJ6_nG5qOlr>k~%DCSJaOfl%KWHusw>tGrTxAhlEVDxc8R2C-)LCt&$Rt9IKor=ml7jirX@?WW+M z^I{b}MD5r$s>^^sN@&g`cXD~S_u09xo;{;noKZatIuzqd zW1e7oTl9>g8opPBT(p+&fo0F#!c{NFYYpIZ6u8hOB{F#{nP)@})X20$3iJtG$cO zJ$Oxl_qH{sL5d?=D$2M4C3Ajc;GN0(B-HVT;@pJ-LvIrN%|SY?t}g!J>ufQrR%hoY z!nr$tq~N%)9}^tEip93XW=MQ1@XovSvn`PTqXeT9@_7hGv4%LK1M**Q%UKi|(v@1_ zKGe*@+1%Y4v&`;5vUL`C&{tc+_7HFs7*OtjY8@Gg`C4O&#An{0xOvgNSehTHS~_1V z=daxCMzI5b_ydM5$z zZl`a{mM}i@x;=QyaqJY&{Q^R*^1Yzq!dHH~UwCCga+Us~2wk59ArIYtSw9}tEmjbo z5!JA=`=HP*Ae~Z4Pf7sC^A3@Wfa0Ax!8@H_&?WVe*)9B2y!8#nBrP!t1fqhI9jNMd zM_5I)M5z6Ss5t*f$Eh{aH&HBeh310Q~tRl3wCEcZ>WCEq%3tnoHE)eD=)XFQ7NVG5kM zaUtbnq2LQomJSWK)>Zz1GBCIHL#2E>T8INWuN4O$fFOKe$L|msB3yTUlXES68nXRX zP6n*zB+kXqqkpQ3OaMc9GqepmV?Ny!T)R@DLd`|p5ToEvBn(~aZ%+0q&vK1)w4v0* zgW44F2ixZj0!oB~^3k|vni)wBh$F|xQN>~jNf-wFstgiAgB!=lWzM&7&&OYS=C{ce zRJw|)PDQ@3koZfm`RQ$^_hEN$GuTIwoTQIDb?W&wEo@c75$dW(ER6q)qhF`{#7UTuPH&)w`F!w z0EKs}=33m}_(cIkA2rBWvApydi0HSOgc>6tu&+hmRSB%)s`v_NujJNhKLS3r6hv~- z)Hm@?PU{zd0Tga)cJWb2_!!9p3sP%Z zAFT|jy;k>4X)E>4fh^6=SxV5w6oo`mus&nWo*gJL zZH{SR!x)V)y=Qc7WEv-xLR zhD4OcBwjW5r+}pays`o)i$rcJb2MHLGPmeOmt5XJDg@(O3PCbxdDn{6qqb09X44T zh6I|s=lM6Nr#cGaA5-eq*T=LQ6SlRq*`~`b+dVi5^>el1p;#si6}kK}>w;1 z6B1dz{q_;PY{>DBQ+v@1pfXTd5a*^H9U*;qdj@XBF}MoSSQxVXeUpEM5Z0909&8$pRfR|B(t0ox&xl8{8mUNd#(zWONW{oycv$VjP1>q;jU@ z@+8E~fjz*I54OFFaQ{A5jn1w>r;l!NRlI(8q3*%&+tM?lov_G3wB`<}bQ>1=&xUht zmti5VZzV1Cx006Yzt|%Vwid>QPX8Nfa8|sue7^un@C+!3h!?-YK>lSfNIHh|0kL8v zbv_BklQ4HOqje|@Fyxn%IvL$N&?m(KN;%`I$N|muStjSsgG;gP4Smgz$2u(mG;DXP zf~uQ z212x^l6!MW>V@ORUGSFLAAjz3i5zO$=UmD_zhIk2OXUz^LkDLWjla*PW?l;`LLos> z7FBvCr)#)XBByDm(=n%{D>BcUq>0GOV9`i-(ZSI;RH1rdrAJ--f0uuAQ4odl z_^$^U_)0BBJwl@6R#&ZtJN+@a(4~@oYF)yG+G#3=)ll8O#Zv3SjV#zSXTW3h9kqn* z@AHL=vf~KMas}6{+u=}QFumr-!c=(BFP_dwvrdehzTyqco)m@xRc=6b#Dy+KD*-Bq zK=y*1VAPJ;d(b?$2cz{CUeG(0`k9_BIuUki@iRS5lp3=1#g)A5??1@|p=LOE|FNd; z-?5MLKd-5>yQ7n__5W^3C!_`hP(o%_E3BKEmo1h=H(7;{6$XRRW6{u+=oQX<((xAJ zNRY`Egtn#B1EBGHLy^eM5y}Jy0h!GAGhb7gZJoZI-9WuSRw)GVQAAcKd4Qm)pH`^3 zq6EIM}Q zxZGx%aLnNP1an=;o8p9+U^>_Bi`e23E^X|}MB&IkS+R``plrRzTE%ncmfvEW#AHJ~ znmJ`x&ez6eT21aLnoI`%pYYj zzQ?f^ob&Il;>6Fe>HPhAtTZa*B*!;;foxS%NGYmg!#X%)RBFe-acahHs3nkV61(E= zhekiPp1d@ACtA=cntbjuv+r-Zd`+lwKFdqZuYba_ey`&H<Psu;Tzwt;-LQxvv<_D5;ik7 zwETZe`+voUhk%$s2-7Rqfl`Ti_{(fydI(DAHKr<66;rYa6p8AD+NEc@Fd@%m`tiK% z=Mebzrtp=*Q%a}2UdK4J&5#tCN5PX>W=(9rUEXZ8yjRu+7)mFpKh{6;n%!bI(qA9kfyOtstGtOl zX!@*O0fly*L4k##fsm&V0j9Lj<_vu1)i?!#xTB7@2H&)$Kzt@r(GH=xRZlIimTDd_o(%9xO388LwC#;vQ?7OvRU_s< zDS@6@g}VnvQ+tn(C#sx0`J^T4WvFxYI17;uPs-Ub{R`J-NTdtBGl+Q>e81Z3#tDUr ztnVc*p{o|RNnMYts4pdw=P!uJkF@8~h)oV4dXu5F7-j0AW|=mt!QhP&ZV!!82*c7t zuOm>B*2gFtq;A8ynZ~Ms?!gEi5<{R_8tRN%aGM!saR4LJQ|?9w>Ff_61(+|ol_vL4 z-+N>fushRbkB4(e{{SQ}>6@m}s1L!-#20N&h%srA=L50?W9skMF9NGfQ5wU*+0<@> zLww8%f+E0Rc81H3e_5^DB@Dn~TWYk}3tqhO{7GDY;K7b*WIJ-tXnYM@z4rn(LGi?z z8%$wivs)fC#FiJh?(SbH-1bgdmHw&--rn7zBWe1xAhDdv#IRB@DGy}}zS%M0(F_3_ zLb-pWsdJ@xXE;=tpRAw?yj(Gz=i$;bsh&o2XN%24b6+?_gJDBeY zws3PE2u!#Cec>aFMk#ECxDlAs;|M7@LT8)Y4(`M}N6IQ{0YtcA*8e42!n^>`0$LFU zUCq2IR2(L`f++=85M;}~*E($nE&j;p{l%xchiTau*tB9bI= zn~Ygd@<+9DrXxoGPq}@vI1Q3iEfKRleuy*)_$+hg?+GOgf1r?d@Or42|s|D>XMa;ebr1uiTNUq@heusd6%WwJqyCCv!L*qou9l!B22H$bQ z)<)IA>Yo77S;|`fqBk!_PhLJEQb0wd1Z|`pCF;hol!34iQYtqu3K=$QxLW7(HFx~v>`vVRr zyqk^B4~!3F8t8Q_D|GLRrAbbQDf??D&Jd|mgw*t1YCd)CM2$76#Cqj1bD*vADwavp zS<`n@gLU4pwCqNPsIfHKl{5}gu9t-o+O< z??!fMqMrt$s}02pdBbOScUrc1T*{*-ideR6(1q4@oC6mxg8v8Y^h^^hfx6| z|Mld6Ax1CuSlmSJmHwdOix?$8emihK#&8&}u8m!#T1+c5u!H)>QW<7&R$eih)xkov zHvvEIJHbkt+2KQ<-bMR;2SYX?8SI=_<-J!GD5@P2FJ}K z5u82YFotCJF(dUeJFRX_3u8%iIYbRS??A?;iVO?84c}4Du9&jG<#urlZ_Unrcg8dR z!5I3%9F*`qwk#joKG_Q%5_xpU7|jm4h0+l$p;g%Tr>i74#3QnMXdz|1l2MQN$yw|5 zThMw15BxjWf2{KM)XtZ+e#N)ihlkxPe=5ymT9>@Ym%_LF}o z1XhCP`3E1A{iVoHA#|O|&5=w;=j*Qf`;{mBAK3={y-YS$`!0UmtrvzHBfR*s{z<0m zW>4C=%N98hZlUhwAl1X`rR)oL0&A`gv5X79??p_==g*n4$$8o5g9V<)F^u7v0Vv^n z1sp8{W@g6eWv2;A31Rhf5j?KJhITYfXWZsl^`7z`CFtnFrHUWiD?$pwU6|PQjs|7RA0o9ARk^9$f`u3&C|#Z3iYdh<0R`l2`)6+ z6tiDj@xO;Q5PDTYSxsx6n>bj+$JK8IPJ=U5#dIOS-zwyK?+t^V`zChdW|jpZuReE_ z)e~ywgFe!0q|jzsBn&(H*N`%AKpR@qM^|@qFai0};6mG_TvXjJ`;qZ{lGDZHScZk( z>pO+%icp)SaPJUwtIPo1BvGyP8E@~w2y}=^PnFJ$iHod^JH%j1>nXl<3f!nY9K$e` zq-?XYl)K`u*cVXM=`ym{N?z=dHQNR23M8uA-(vsA$6(xn+#B-yY!CB2@`Uz({}}w+ z0sni*39>rMC!Ay|1B@;al%T&xE(wCf+`3w>N)*LxZZZYi{5sqiVWgbNd>W*X?V}C- zjQ4F7e_uCUOHbtewQkq?m$*#@ZvWbu{4i$`aeKM8tc^ zL5!GL8gX}c+qNUtUIcps1S)%Gsx*MQLlQeoZz2y2OQb(A73Jc3`LmlQf0N{RTt;wa`6h|ljX1V7UugML=W5-STDbeWTiEMjPQ$({hn_s&NDXzs6?PLySp$?L`0ilH3vCUO{JS0Dp`z;Ry$6}R@1NdY7rxccbm$+;ApSe=2q!0 z()3$vYN0S$Cs)#-OBs{_2uFf}L4h$;7^2w20=l%5r9ui&pTEgg4U!FoCqyA6r2 zC5s72l}i*9y|KTjDE5gVlYe4I2gGZD)e`Py2gq7cK4at{bT~DSbQQ4Z4sl)kqXbbr zqvXtSqMrDdT2qt-%-HMoqeFEMsv~u)-NJ%Z*ipSJUm$)EJ+we|4*-Mi900K{K|e0; z1_j{X5)a%$+vM7;3j>skgrji92K1*Ip{SfM)=ob^E374JaF!C(cZ$R_E>Wv+?Iy9M z?@`#XDy#=z%3d9&)M=F8Xq5Zif%ldIT#wrlw(D_qOKo4wD(fyDHM5(wm1%7hy6euJ z%Edg!>Egs;ZC6%ktLFtyN0VvxN?*4C=*tOEw`{KQvS7;c514!FP98Nf#d#)+Y-wsl zP3N^-Pnk*{o(3~m=3DX$b76Clu=jMf9E?c^cbUk_h;zMF&EiVz*4I(rFoaHK7#5h0 zW7CQx+xhp}Ev+jw;SQ6P$QHINCxeF8_VX=F3&BWUd(|PVViKJl@-sYiUp@xLS2NuF z8W3JgUSQ&lUp@2E(7MG`sh4X!LQFa6;lInWqx}f#Q z4xhgK1%}b(Z*rZn=W{wBOe7YQ@1l|jQ|9ELiXx+}aZ(>{c7Ltv4d>PJf7f+qjRU8i%XZZFJkj&6D^s;!>`u%OwLa*V5Js9Y$b-mc!t@{C415$K38iVu zP7!{3Ff%i_e!^LzJWhBgQo=j5k<<($$b&%%Xm_f8RFC_(97&nk83KOy@I4k?(k<(6 zthO$3yl&0x!Pz#!79bv^?^85K5e7uS$ zJ33yka2VzOGUhQXeD{;?%?NTYmN3{b0|AMtr(@bCx+c=F)&_>PXgAG}4gwi>g82n> zL3DlhdL|*^WTmn;XPo62HhH-e*XIPSTF_h{#u=NY8$BUW=5@PD{P5n~g5XDg?Fzvb_u ziK&CJqod4srfY2T?+4x@)g9%3%*(Q2%YdCA3yM{s=+QD0&IM`8k8N&-6%iIL3kon> z0>p3BUe!lrz&_ZX2FiP%MeuQY-xVV%K?=bGPOM&XM0XRd7or< zy}jn_eEzuQ>t2fM9ict#ZNxD7HUycsq76IavfoNl$G1|t*qpUSX;YgpmJrr_8yOJ2 z(AwL;Ugi{gJ29@!G-mD82Z)46T`E+s86Qw|YSPO*OoooraA!8x_jQXYq5vUw!5f_x zubF$}lHjIWxFar8)tTg8z-FEz)a=xa`xL~^)jIdezZsg4%ePL$^`VN#c!c6`NHQ9QU zkC^<0f|Ksp45+YoX!Sv>+57q}Rwk*2)f{j8`d8Ctz^S~me>RSakEvxUa^Pd~qe#fb zN7rnAQc4u$*Y9p~li!Itp#iU=*D4>dvJ{Z~}kqAOBcL8ln3YjR{Sp!O`s=5yM zWRNP#;2K#+?I&?ZSLu)^z-|*$C}=0yi7&~vZE$s``IE^PY|dj^HcWI$9ZRm>3w(u` z-1%;;MJbzHFNd^!Ob!^PLO-xhhj@XrI81Y)x4@FdsI( za`o4Gy(`T$P?PB?s>o+eIOtuirMykbuAi65Y_UN1(?jTCy@J8Px`%;bcNmPm#Fr!= z5V!YViFJ!FBfEq>nJFk0^RAV1(7w+X`HRgP;nJHJdMa!}&vvduCMoslwHTes_I76|h>;(-9lbfGnt zoZomakOt759AuTX4b$)G8TzJ&m*BV8!vMs9#=e0tWa z%)84R=3?tfh72~=Rc;fXwj+x z+25xapYK@2@;}6)@8IL+F6iuJ_B{&A-0=U=U6WMbY>~ykVFp$XkH)f**b>TE5)shN z39E2L@JPCSl!?pkvFeh@6dCv9oE}|{GbbVM!XIgByN#md&tXy@>QscU0#z!I&X4;d z&B&ZA4lbrHJ!x4lCN4KC-)u#gT^cE{Xnhu`0RXVKn|j$vz8m}v^%*cQ{(h%FW8_8a zFM{$PirSI8@#*xg2T){A+EKX(eTC66Fb})w{vg%Vw)hvV-$tttI^V5wvU?a{(G}{G z@ob7Urk1@hDN&C$N!Nio9YrkiUC{5qA`KH*7CriaB;2~2Od>2l=WytBRl#~j`EYsj}jqK2xD*3 ztEUiPZzEJC??#Tj^?f)=sRXOJ_>5aO(|V#Yqro05p6)F$j5*wYr1zz|T4qz$0K(5! zr`6Pqd+)%a9Xq3aNKrY9843)O56F%=j_Yy_;|w8l&RU1+B4;pP*O_}X8!qD?IMiyT zLXBOOPg<*BZtT4LJ7DfyghK|_*mMP7a1>zS{8>?}#_XXaLoUBAz(Wi>$Q!L;oQ&cL z6O|T6%Dxq3E35$0g5areq9$2+R(911!Z9=wRPq-pju7DnN9LAfOu3%&onnfx^Px5( zT2^sU>Y)88F5#ATiVoS$jzC-M`vY8!{8#9O#3c&{7J1lo-rcNK7rlF0Zt*AKE(WN* z*o?Tv?Sdz<1v6gfCok8MG6Pzecx9?C zrQG5j^2{V556Hj=xTiU-seOCr2ni@b<&!j>GyHbv!&uBbHjH-U5Ai-UuXx0lcz$D7%=! z&zXD#Jqzro@R=hy8bv>D_CaOdqo6)vFjZldma5D+R;-)y1NGOFYqEr?h zd_mTwQ@K2veZTxh1aaV4F;YnaWA~|<8$p}-eFHashbWW6Dzj=3L=j-C5Ta`w-=QTw zA*k9!Ua~-?eC{Jc)xa;PzkUJ#$NfGJOfbiV^1au;`_Y8|{eJ(~W9pP9q?gLl5E6|e{xkT@s|Ac;yk01+twk_3nuk|lRu{7-zOjLAGe!)j?g+@-;wC_=NPIhk(W zfEpQrdRy z^Q$YBs%>$=So>PAMkrm%yc28YPi%&%=c!<}a=)sVCM51j+x#<2wz?2l&UGHhOv-iu z64x*^E1$55$wZou`E=qjP1MYz0xErcpMiNYM4+Qnb+V4MbM;*7vM_Yp^uXUuf`}-* z_2CnbQ);j5;Rz?7q)@cGmwE^P>4_u9;K|BFlOz_|c^1n~%>!uO#nA?5o4A>XLO{X2 z=8M%*n=IdnXQ}^+`DXRKM;3juVrXdgv79;E=ovQa^?d7wuw~nbu%%lsjUugE8HJ9zvZIM^nWvjLc-HKc2 zbj{paA}ub~4N4Vw5oY{wyop9SqPbWRq=i@Tbce`r?6e`?`iOoOF;~pRyJlKcIJf~G z)=BF$B>YF9>qV#dK^Ie#{0X(QPnOuu((_-u?(mxB7c9;LSS-DYJ8Wm4gz1&DPQ8;0 z=Wao(zb1RHXjwbu_Zv<=9njK28sS}WssjOL!3-E5>d17Lfnq0V$+IU84N z-4i$~!$V-%Ik;`Z3MOqYZdiZ^3nqqzIjLE+zpfQC+LlomQu-uNCStj%MsH(hsimN# z%l4vpJBs_2t7C)x@6*-k_2v0FOk<1nIRO3F{E?2DnS}w> z#%9Oa{`RB5FL5pKLkg59#x~)&I7GzfhiVC@LVFSmxZuiRUPVW*&2ToCGST0K`kRK) z02#c8W{o)w1|*YmjGSUO?`}ukX*rHIqGtFH#!5d1Jd}&%4Kc~Vz`S7_M;wtM|6PgI zNb-Dy-GI%dr3G3J?_yBX#NevuYzZgzZ!vN>$-aWOGXqX!3qzCIOzvA5PLC6GLIo|8 zQP^c)?NS29hPmk5WEP>cHV!6>u-2rR!tit#F6`_;%4{q^6){_CHGhvAs=1X8Fok+l zt&mk>{4ARXVvE-{^tCO?inl{)o}8(48az1o=+Y^r*AIe%0|{D_5_e>nUu`S%zR6|1 zu0$ov7c`pQEKr0sIIdm7hm{4K_s0V%M-_Mh;^A0*=$V9G1&lzvN9(98PEo=Zh$`Vj zXh?fZ;9$d!6sJRSjTkOhb7@jgSV^2MOgU^s2Z|w*e*@;4h?A8?;v8JaLPCoKP_1l- z=Jp0PYDf(d2Z`;O7mb6(_X_~z0O2yq?H`^c=h|8%gfywg#}wIyv&_uW{-e8e)YmGR zI0NNSDoJWa%0ztGzkwl>IYW*DesPRY?oH+ow^(>(47XUm^F`fAa0B~ja-ae$e>4-A z64lb_;|W0ppKI+ zxu2VLZzv4?Mr~mi?WlS-1L4a^5k+qb5#C)ktAYGUE1H?Vbg9qsRDHAvwJUN=w~AuT zUXYioFg2Dx-W)}w9VdFK#vpjoSc!WcvRZ_;TgHu;LSY*i7K_>Px{%C4-IL?6q?Qa_ zL7l=EEo|@X&$gX;fYP02qJF~LN9?E-OL2G(Fo4hW)G{`qnW zTIuc+-1VJvKgph0jAc(LzM);Pg$MPln?U|ek{_5nNJHfm-Y#ec+n#Yf_e>XfbLbN)eqHEDr0#?<;TskL5-0JGv|Ut{=$Xk8hlwbaMXdcI3GL zY-hykR{zX9liy$Z2F3!z346uu%9@-y6Gda`X2*ixlD_P@<}K?AoV?(%lM%* z(xNk=|A()443aGj)-~IDf3J+UA2p2lh6ei^pG*HL#SiThnIr5WZDXebI)F7X zGmP-3bH$i$+(IwqgbM7h%G5oJ@4{Z~qZ#Zs*k7eXJIqg;@0kAGV|b=F#hZs)2BYu1 zr8sj#Zd+Iu^G}|@-dR5S*U-;DqzkX3V0@q-k8&VHW?h0b0?tJ-Atqmg^J8iF7DP6k z)W{g?5~F*$5x?6W)3YKcrNu8%%(DglnzMx5rsU{#AD+WPpRBf``*<8F-x75D$$13U zcaNXYC0|;r&(F@!+E=%+;bFKwKAB$?6R%E_QG5Yn5xX#h+zeI-=mdXD5+D+lEuM`M ze+*G!zX^xbnA?~LnPI=D2`825Ax8rM()i*{G0gcV5MATV?<7mh+HDA7-f6nc@95st zzC_si${|&=$MUj@nLxl_HwEXb2PDH+V?vg zA^DJ%dn069O9TNK-jV}cQKh|$L4&Uh`?(z$}#d+{X zm&=KTJ$+KvLZv-1GaHJm{>v=zXW%NSDr8$0kSQx(DQ)6S?%sWSHUazXSEg_g3agt2@0nyD?A?B%9NYr(~CYX^&U#B4XwCg{%YMYo%e68HVJ7`9KR`mE*Wl7&5t71*R3F>*&hVIaZXaI;2a$?;{Ew{e3Hr1* zbf$&Fyhnrq7^hNC+0#%}n^U2{ma&eS)7cWH$bA@)m59rXlh96piJu@lcKl<>+!1#s zW#6L5Ov%lS(?d66-(n`A%UuiIqs|J|Ulq0RYq-m&RR0>wfA1?<34tI?MBI#a8lY{m z{F2m|A@=`DpZpwdIH#4)9$#H3zr4kn2OX!UE=r8FEUFAwq6VB?DJ8h59z$GXud$#+ zjneIq8uSi&rnG0IR8}UEn5OcZC?@-;$&Ry9hG{-1ta`8aAcOe1|82R7EH`$Qd3sf* zbrOk@G%H7R`j;hOosRVIP_2_-TuyB@rdj?(+k-qQwnhV3niH+CMl>ELX(;X3VzZVJ ztRais0C^L*lmaE(nmhvep+peCqr!#|F?iVagZcL>NKvMS_=*Yl%*OASDl3(mMOY9! z=_J$@nWpA-@><43m4olSQV8(PwhsO@+7#qs@0*1fDj70^UfQ(ORV0N?H{ceLX4<43 zEn)3CGoF&b{t2hbIz;Og+$+WiGf+x5mdWASEWIA*HQ9K9a?-Pf9f1gO6LanVTls)t z^f6_SD|>2Kx8mdQuiJwc_SmZOZP|wD7(_ti#0u=io|w~gq*Odv>@8JBblRCzMKK_4 zM-uO0Ud9>VD>J;zZzueo#+jbS7k#?W%`AF1@ZPI&q%}beZ|ThISf-ly)}HsCS~b^g zktgqOZ@~}1h&x50UQD~!xsW-$K~whDQNntLW=$oZDClUJeSr2$r3}94Wk1>co3beS zoY-7t{rGv|6T?5PNkY zj*XjF()ybvnVz5=BFnLO=+1*jG>E7F%&vm6up*QgyNcJJPD|pHoZ!H6?o3Eig0>-! zt^i-H@bJ;^!$6ZSH}@quF#RO)j>7A5kq4e+7gK=@g;POXcGV28Zv$jybL1J`g@wC# z_DW1ck}3+n@h2LFQhwVfaV@D+-kff4celZC0;0ef?pA#*PPd8Kk8sO1wza&BHQFblVU8P1=-qScHff^^fR zycH!hlHQs7iejITpc4UaBxzqTJ}Z#^lk{W(cr`qtW~Ap;HvuUf#MxgEG?tEU+B?G% znub0I(s@XvI(lva}$Z7<}Qg=rWd5n)}rX{nb+Aw;}?l9LZI-`N-*hts=c6XgjfJs ztp>-686v6ug{glEZ}K=jVG|N1WSWrU*&ue|4Q|O@;s0#L5P*U%Vx;)w7S0ZmLuvwA z@zs2Kut)n1K7qaywO#TbBR`Q~%mdr`V)D`|gN0!07C1!r3{+!PYf9*;h?;dE@#z(k z;o`g~<>P|Sy$ldHTUR3v=_X0Iw6F>3GllrFXVW?gU0q6|ocjd!glA)#f0G7i20ly>qxRljgfO2)RVpvmg#BSrN)GbGsrIb}9 z1t+r;Q>?MGLk#LI5*vR*C8?McB|=AoAjuDk&Pn`KQo z`!|mi{Cz@BGJ!TwMUUTkKXKNtS#OVNxfFI_Gfq3Kpw0`2AsJv9PZPq9x?~kNNR9BR zw#2jp%;FJNoOzW>tE#zskPICp>XSs?|B0E%DaJH)rtLA}$Y>?P+vEOvr#8=pylh zch;H3J`RE1{97O+1(1msdshZx$it^VfM$`-Gw>%NN`K|Tr$0}U`J?EBgR%bg=;et0 z_en)!x`~3so^V9-jffh3G*8Iy6sUq=uFq%=OkYvHaL~#3jHtr4sGM?&uY&U8N1G}QTMdqBM)#oLTLdKYOdOY%{5#Tgy$7QA! zWQmP!Wny$3YEm#Lt8TA^CUlTa{Cpp=x<{9W$A9fyKD0ApHfl__Dz4!HVVt(kseNzV z5Fb`|7Mo>YDTJ>g;7_MOpRi?kl>n(ydAf7~`Y6wBVEaxqK;l;}6x8(SD7}Tdhe2SR zncsdn&`eI}u}@^~_9(0^r!^wuKTKbs-MYjXy#-_#?F=@T*vUG@p4X+l^SgwF>TM}d zr2Ree{TP5x@ZtVcWd3++o|1`BCFK(ja-QP?zj6=ZOq)xf$CfSv{v;jCcNt4{r8f+m zz#dP|-~weHla%rsyYhB_&LHkwuj83RuCO0p;wyXsxW5o6{)zFAC~2%&NL? z=mA}szjHKsVSSnH#hM|C%;r0D$7)T`HQ1K5vZGOyUbgXjxD%4xbs$DAEz)-;iO?3& zXcyU*Z8zm?pP}w&9ot_5I;x#jIn^Joi5jBDOBP1)+p@G1U)pL6;SIO>Nhw?9St2UN zMedM(m(T6bNcPPD`%|9dvXAB&IS=W4?*7-tqldqALH=*UapL!4`2TM_{`W&pm*{?| z0DcsaTdGA%RN={Ikvaa&6p=Ux5ycM){F1OgOh(^Yk-T}a5zHH|=%Jk)S^vv9dY~`x zG+!=lsDjp!D}7o94RSQ-o_g#^CnBJlJ@?saH&+j0P+o=eKqrIApyR7ttQu*0 z1f;xPyH2--)F9uP2#Mw}OQhOFqXF#)W#BAxGP8?an<=JBiokg;21gKG_G8X!&Hv;7 zP9Vpzm#@;^-lf=6POs>UrGm-F>-! zm;3qp!Uw?VuXW~*Fw@LC)M%cvbe9!F(Oa^Y6~mb=8%$lg=?a0KcGtC$5y?`L5}*-j z7KcU8WT>2PpKx<58`m((l9^aYa3uP{PMb)nvu zgt;ia9=ZofxkrW7TfSrQf4(2juZRBgcE1m;WF{v1Fbm}zqsK^>sj=yN(x}v9#_{+C zR4r7abT2cS%Wz$RVt!wp;9U7FEW&>T>YAjpIm6ZSM4Q<{Gy+aN`Vb2_#Q5g@62uR_>II@eiHaay+JU$J=#>DY9jX*2A=&y8G%b zIY6gcJ@q)uWU^mSK$Q}?#Arq;HfChnkAOZ6^002J>fjPyPGz^D5p}o;h2VLNTI{HGg!obo3K!*I~a7)p-2Z3hCV_hnY?|6i`29b zoszLpkmch$mJeupLbt4_u-<3k;VivU+ww)a^ekoIRj4IW4S z{z%4_dfc&HAtm(o`d{CZ^AAIE5XCMvwQSlkzx3cLi?`4q8;iFTzuBAddTSWjfcZp* zn{@Am!pl&fv#k|kj86e$2%NK1G4kU=E~z9L^`@%2<%Dx%1TKk_hb-K>tq8A9bCDfW z@;Dc3KqLafkhN6414^46Hl8Tcv1+$q_sYjj%oHz)bsoGLEY1)ia5p=#eii(5AM|TW zA8=;pt?+U~>`|J(B85BKE0cB4n> zWrgZ)Rbu}^A=_oz65LfebZ(1xMjcj_g~eeoj74-Ex@v-q9`Q{J;M!mITVEfk6cn!u zn;Mj8C&3^8Kn%<`Di^~Y%Z$0pb`Q3TA}$TiOnRd`P1XM=>5)JN9tyf4O_z}-cN|i> zwpp9g`n%~CEa!;)nW@WUkF&<|wcWqfL35A}<`YRxV~$IpHnPQs2?+Fg3)wOHqqAA* zPv<6F6s)c^o%@YqS%P{tB%(Lxm`hsKv-Hb}MM3=U|HFgh8R-|-K(3m(eU$L@sg=uW zB$vAK`@>E`iM_rSo;Cr*?&wss@UXi19B9*0m3t3q^<)>L%4j(F85Ql$i^;{3UIP0c z*BFId*_mb>SC)d#(WM1%I}YiKoleKqQswkdhRt9%_dAnDaKM4IEJ|QK&BnQ@D;i-ame%MR5XbAfE0K1pcxt z{B5_&OhL2cx9@Sso@u2T56tE0KC`f4IXd_R3ymMZ%-!e^d}v`J?XC{nv1mAbaNJX| zXau+s`-`vAuf+&yi2bsd5%xdqyi&9o;h&fcO+W|XsKRFOD+pQw-p^pnwwYGu=hF7& z{cZj$O5I)4B1-dEuG*tU7wgYxNEhqAxH?p4Y1Naiu8Lt>FD%AxJ811`W5bveUp%*e z9H+S}!nLI;j$<*Dn~I*_H`zM^j;!rYf!Xf#X;UJW<0gic?y>NoFw}lBB6f#rl%t?k zm~}eCw{NR_%aosL*t$bmlf$u|U2hJ*_rTcTwgoi_N=wDhpimYnf5j!bj0lQ*Go`F& z6Wg+xRv55a(|?sCjOIshTEgM}2`dN-yV>)Wf$J58>lNVhjRagGZw?U9#2p!B5C3~Nc%S>p`H4PK z7vX@|Uo^*F4GXiFnMf4gwHB;Uk8X4TaLX4A>B&L?mw4&`XBnLCBrK2FYJLrA{*))0 z$*~X?2^Q0KS?Yp##T#ohH1B)y4P+rR7Ut^7(kCwS8QqgjP!aJ89dbv^XBbLhTO|=A z|3FNkH1{2Nh*j{p-58N=KA#6ZS}Ir&QWV0CU)a~{P%yhd-!ehF&~gkMh&Slo9gAT+ zM_&3ms;1Um8Uy0S|0r{{8xCB&Tg{@xotF!nU=YOpug~QlZRKR{DHGDuk(l{)d$1VD zj)3zgPeP%wb@6%$zYbD;Uhvy4(D|u{Q_R=fC+9z#sJ|I<$&j$|kkJiY?AY$ik9_|% z?Z;gOQG5I%{2{-*)Bk|Tia8n>TbrmjnK+8u*_cS%*;%>R|K|?urtIdgTM{&}Yn1;| zk`xq*Bn5HP5a`ANv`B$IKaqA4e-XC`sRn3Z{h!hN0=?x(kTP+fE1}-<3eL+QDFXN- z1JmcDt0|7lZN8sh^=$e;P*8;^33pN>?S7C0BqS)ow4{6ODm~%3018M6P^b~(Gos!k z2AYScAdQf36C)D`w&p}V89Lh1s88Dw@zd27Rv0iE7k#|U4jWDqoUP;-He5cd4V7Ql)4S+t>u9W;R-8#aee-Ct1{fPD+jv&zV(L&k z)!65@R->DB?K6Aml57?psj5r;%w9Vc3?zzGs&kTA>J9CmtMp^Wm#1a@cCG!L46h-j z8ZUL4#HSfW;2DHyGD|cXHNARk*{ql-J2W`9DMxzI0V*($9{tr|O3c;^)V4jwp^RvW z2wzIi`B8cYISb;V5lK}@xtm3NB;88)Kn}2fCH(WRH1l@3XaO7{R*Lc7{ZN1m+#&diI7_qzE z?BS+v<)xVMwt{IJ4yS2Q4(77II<>kqm$Jc3yWL42^gG6^Idg+y3)q$-(m2>E49-fV zyvsCzJ5EM4hyz1r#cOh5vgrzNGCBS}(Bupe`v6z{e z)cP*a8VCbRuhPp%BUwIRvj-$`3vrbp;V3wmAUt{?F z0OO?Mw`AS?y@>w%(pBO=0lohnxFWx`>Hs}V$j{XI2?}BtlvIl7!ZMZukDF7 z^6Rq2H*36KHxJ1xWm5uTy@%7;N0+|<>Up>MmxKhb;WbH1+=S94nOS-qN(IKDIw-yr zi`Ll^h%+%k`Yw?o3Z|ObJWtfO|AvPOc96m5AIw;4;USG|6jQKr#QP}+BLy*5%pnG2 zyN@VMHkD`(66oJ!GvsiA`UP;0kTmUST4|P>jTRfbf&Wii8~a`wMwVZoJ@waA{(t(V zwoc9l*4F>YUM8!aE1{?%{P4IM=;NUF|8YkmG0^Y_jTJtKClDV3D3~P7NSm7BO^r7& zWn!YrNc-ryEvhN$$!P%l$Y_P$s8E>cdAe3=@!Igo^0diL6`y}enr`+mQD;RC?w zb8}gXT!aC`%rdxx2_!`Qps&&w4i0F95>;6;NQ-ys;?j#Gt~HXzG^6j=Pv{3l1x{0( z4~&GNUEbH=9_^f@%o&BADqxb54EAq=8rKA~4~A!iDp9%eFHeA1L!Bb8Lz#kF(p#)X zn`CglEJ(+tr=h4bIIHlLkxP>exGw~{Oe3@L^zA)|Vx~2yNuPKtF^cV6X^5lw8hU*b zK-w6x4l&YWVB%0SmN{O|!`Sh6H45!7}oYPOc+a#a|n3f%G@eO)N>W!C|!FNXV3taFdpEK*A1TFGcRK zV$>xN%??ii7jx5D69O>W6O`$M)iQU7o!TPG*+>v6{TWI@p)Yg$;8+WyE9DVBMB=vnONSQ6k1v z;u&C4wZ_C`J-M0MV&MpOHuVWbq)2LZGR0&@A!4fZwTM^i;GaN?xA%0)q*g(F0PIB( zwGrCC#}vtILC_irDXI5{vuVO-(`&lf2Q4MvmXuU8G0+oVvzZp0Y)zf}Co0D+mUEZz zgwR+5y!d(V>s1} zji+mrd_6KG;$@Le2Ic&am6O+Rk1+QS?urB4$FQNyg2%9t%!*S5Ts{8j*&(H1+W;0~ z$frd%jJjlV;>bXD7!a-&!n52H^6Yp}2h3&v=}xyi>EXXZDtOIq@@&ljEJG{D`7Bjr zaibxip6B6Mf3t#-*Tn7p z96yx1Qv-&r3)4vg`)V~f8>>1_?E4&$bR~uR;$Nz=@U(-vyap|Jx zZ;6Ed+b#GXN+gN@ICTHx{=c@J|97TIPWs(_kjEIwZFHfc!rl8Ep-ZALBEZEr3^R-( z7ER1YXOgZ)&_=`WeHfWsWyzzF&a;AwTqzg~m1lOEJ0Su=C2<{pjK;{d#;E zr2~LgXN?ol2ua5Y*1)`(be0tpiFpKbRG+IK(`N?mIgdd9&e6vxzqxzaa`e7zKa3D_ zHi+c1`|720|dn(z4Qos^e7sn(PU%NYLv$&!|4kEse%DK;YAD06@XO3!EpKpz!^*?(?-Ip zC_Zlb(-_as+-D?0Ag9`|4?)bN)5o(J=&udAY|YgV(YuK9k=E>0z`$dSaL(wmxd!1f zME&3wwv@#{dgeMlZ4}GL!I`VZxtdQY$lmauCN_|mGXqEEj@i~du$|>5UvLjsbq!{; z@jEf;21iC1jFEmIPE^4gykHQzCMLj=2Ek4&FvlpqTlS(0YT%*W<>XgH$4ww`D`aihBGkPM(&EG};Cl&wzg8!jL z`rkqPzvH(0Kd{2n=?Bt8aAU&0IyiA+V-qnXVId^qG!SWZ7%_f&i!D{R#7Jo$%tICxY%j)ebORE>3H_c|to}c#HX;HAC?~B;2mmQrMp2;8T zmzde!k7BYg^Z1r|DUvSD3@{6S<1kndb%Qt%GA# z+sB2&F5L`R&fLRdAlpU_pVsJsYDEz{^ zKGaAz#%W+MPGT+D$+xowMY0=ipM)0p?zym&Aoi)qL(pO_weO(k?s|ELHl^W zviJiFUXRL&?`;3_;mvc02A@sbsW9}#{anvGafZ#ST;}za?XS3}ZG3B4m(SW{>w}Fh z)T5Yi*``Tstmi9SHXmuWSND@cj}qtY!`tuD29Dpu+-D3$h<5FY>jE>YJvqBmhw?oll`x7Ono(}R~P zle_eBwYy0Rr7kmf_SEt_gn4)AO-r`}^Z5Y%Rm8)K-?X>rvDL+QT?#)QwDsQ2c$tc* z&#hbgkL6}GnBDH;+lREM6MGIskRa@r>5Iq(ll2IepuhW86w@14=E{6$cz*cBDQ)CT>}v-DLM-v8)xaPBnmGBKM63RgDGqh!<*j90tSE4|G^+r@#-7g2 zs8KE8eZPZhQuN>wBU%8CmkE9LH1%O;-*ty0&K~01>F3XB>6sAm*m3535)9T&Fz}A4 zwGjZYVea@Fesd=Rv?ROE#q=}yfvQEP8*4zoEw4@^Qvw54utUfaR1T6gLmq?c9sON> z>Np6|0hdP_VURy81;`8{ZYS)EpU9-3;huFq)N3r{yP1ZBCHH7=b?Ig6OFK~%!GwtQ z3`RLKe8O&%^V`x=J4%^Oqg4ZN9rW`UQN^rslcr_Utzd-@u-Sm{rphS-y}{k41)Y4E zfzu}IC=J0JmRCV6a3E38nWl1G495grsDDc^H0Fn%^E0FZ=CSHB4iG<6jW1dY`2gUr zF>nB!y@2%rouAUe9m0VQIg$KtA~k^(f{C*Af_tOl=>vz>$>7qh+fPrSD0YVUnTt)? z;@1E0a*#AT{?oUs#bol@SPm0U5g<`AEF^=b-~&4Er)MsNnPsLb^;fL2kwp|$dwiE3 zNc5VDOQ%Q8j*d5vY##)PGXx51s8`0}2_X9u&r(k?s7|AgtW0LYbtlh!KJ;C9QZuz< zq>??uxAI1YP|JpN$+{X=97Cdu^mkwlB={`aUp+Uyu1P139=t%pSVKo7ZGi_v(0z>l zHLGxV%0w&#xvev)KCQ{7GC$nc3H?1VOsYGgjTK;Px(;o0`lerxB<+EJX9G9f8b+)VJdm(Ia)xjD&5ZL45Np?9 zB%oU;z05XN7zt{Q!#R~gcV^5~Y^gn+Lbad7C{UDX2Nznj8e{)TLH|zEc|{a#idm@z z6(zon+{a>FopmQsCXIs*4-dLGgTc)iOhO3r=l?imNUR-pWl!ktO0r_a0Nqo@bu8MzyjSq9zkqPe*`Sxz75rZ zr9X%(=PVqCRB=zfX+_u&*k4#s1k4OV11YgkCrlr6V;vz<{99HKC@qQ+H8xv5)sc63 z69;U4O&{fb5(fN``jJH#3=GHsV56@{d@7`VhA$K^;GU+R-V%%cnmjYs?>c5^6Ugv} zn<}L&i;2`zzW@(kxf$$gVH@7nh}2%G%ciQ_B?r{13?Q@=Q+6msQGtnyY%Gkjeor?g z7F*tMqLdhcq+LCCo^D;CtOACCBhXgK-M&w{*dcUdmtv@XFTofmmpcWKtCn^`#?oZC zUOm52 z7sK$hR|Vh6y&pfIUK&!`8HH*>12$nWA)Ynp+XwOj=jNLD z{QA4gezbe>wiP?`jJO;c&EId;=2u80s_r97;TX!6@*(<%WL+^bmxheMB3pKx0OpH^ zPs}knV+jpJ4TaD@r^V`mTsjf`7!z^H}eHQ#Rp z72(>Dm#QO!ZYR*O@yHic`3*T^t7jc=d`Jz6Lk@Y-bL%cOp_~=#xzIJl?`{Qu;$uC~NkePE+7wSW_FM`&V{gFN zl;lq@;FtAsl!h;tnOvj z#gYx!q$5MdZ0Jxjy=t*q)HFeeyI-vgaGdh1QNhqGRy8qS)|6S0QK7Gj9R?Co{Knh> za>xkQZ0}bBx!9@EUxRBYGm25^G}&j-`0VWX04E|J!kJ8^WoZ(jbhU_twFwWIH32fv zi=pg~(b#ajW=`)Vikwwe39lpML?|sY$?*6*kYBxku_<=#$gfTqQ_F!9F0=OkHnzBo zEwR!H_h|MNjuG$Tj6zaaouO}HYWCF8vN4C%EX-%Iu%ho;q$G#ErnafhXR*4J2Rp5* zhsi0;wlSwE*inVFO>{(8?N~82zijpt+9Y_-^>xnE%T*zk9gi|j7b@s<5{|qEquUD( zS;-%RySZOCOEh*>!kvbsQ265* z>X8*_Wy&~FB@aDHz%glyiAujXq-|2kDUjFTn9Rafsl+XNyFP%PG|l&ZGWBcEXxy=9 zeDn2PIoVuL$gX0RgVK1O$x3%pOzS7x^U5Pi;mtT)%cY;&e&M7GLM}zP+IPbqLt=^5 z7qLfri8myf;~2psc@^cA6mG&{C%e_(M$$!wC^5p^T1QzrS%I?(U{qcd+oJJkQxe10 zON{Q*?iz%F4MbEsoEc+x3E?&2wVR^v3|Q0lDaMvgS7mNjI{2w! z9|~=!83T%GW*iaChSS!`Xd^beFp9N4%K+k*j#jFumk}U?=WKL_kJAltxnxp~+lZzT zp@&&kSPTg3oSGos`rVBhK0|4NdHM_hnKuw1#0JV{gi_dKDJLB+ix~~HpU9%jD)@YY zOK)L7kgbLyN2%Dx#fuY}8swh4ACk7%BpP-n5(RhDq{gEHP*Fo4IviX{C49|B5h~SC zFr`=0)=h2^F5UpCAgt?R5u{6VvpUf#*nC zCQ`$!|C;L2lpjlG?(>T$(_$O3_YNNbPT~(?!j3aD8k=yu^ogw4bkjvgF|3BOq(hB& zG;^cPXmcUP$ox8zElCJ-zMbK9q^8{rri#8Cek5Ydr0YT-KTh@J z6^AcB9ejew8BY5kzZUZX(7Po==eW<(;uV~E7(BY5c0^xr`cuRwn)47bN?zOb!0?cw z#v}R$z66&m#+AHfo@(^V2#S~bhoUkkTArg+6w>JzZ52r96^({1W!?>4$h0l|-jDfj z>7(<+%67#(A|4hZ3>Y;hd&S?}F;`Vtqz|pK&B>NJ=Faci;gkf-+GmfQR8^zo_vul2 zB!)kfu4Dq_g)8TBBo52*sB6F`qa&JCR=_A$QWgX_K}fZm{Cb2#1q`^S3+WaS>sS#@ z-4k*G=#?z6d_e7JJ+Z8^(t0tNdL{K5F;2nfQbXgld}a(X)Gr;WojOy`^?es~AClT$ z5^lD{WJek0!p-QEH5E7n6DKQ0%_ZBZ=|jfV_MM{VmL8y-Wd|>OmeemP=C@xI@@M~1 zW2S*im@Rc=O>V886_UJ@oh1!2H$Ku&U*Hh_oxd{32)vf1$cRiepv28ricM;}#p!+k zaK{z1I=9Y%3m4|Pj*BD*Fn5Vh?O@oD^1UcjyeNh0fbhh~V6xb#4njlGW8OehUe!MnoR(wn#nsoyL1m!Rov)Nv4~&JEVl7L z#^qYdTpNI#u`N0UbVMiDmD>g2VQcG3>4D6gErgddZnSQTs){BExxRJRB?bIxTdZa z;!S8FHJPPiIDQ*FAUiWSYnjILFjDvxvSC zk z=j4Kx@Pg~&2Z?cmMDa;)#xVeorJrxDBqy{+`kG+ZPQqC@#ku-c3ucU+69$#q_*se` z-H#PFW^>-C0>++|6r=<$Z8)ZFaK=ZjwsNYXqRpl9G|yme@Eld5B-*I69Nx_TResHi z!5nm+>6zaJYQO#%D{~o-oOJ;q`fa5}l!8G*U-E$OM&7@dqciBCWtd}|SrDXz$TB($&m*=Epuolu2k`KUwO7maP3P0ok zmF57lSh0Ba@&sO1iZ5^+3s8{B8t|M;Pg&O+{tZJCiLWd6H@{b~9{CLF9s3Kn zt5)Rs9ejne?o{%f>B$Dl%X7fd~KY)I|(pxUeHj;gNsK6;ZR>`ciu;GxvhDUt!+31Knss2U(%ts8K z18)8;<2ax9RG?!|Lwdt^i5L^&O788roKmVAB)=EdK~HqR2Q=)H_VW}xY=95MP_Ov< zPEz3%DRK}+(aUBwsr83H8>`H^v~|A_t}0vPmRwKPt1{|qOY|PZu}j9+{ZhF&-H_TB zU9xWLpNTc`enI|)h9jQeqf5RfGLFk_vfX`40iMpd%KZF!lKbZTdBw$<^G6nuS+$fT zrbK)xo&;buPJcpOZ=x>n+bRXVFDs(23Xr=rDE&!)pVXZ;;A07NXGl_0m`{Z)DQIu$ zFDvY4xu-ifTe_$|n2B83eI;KUg6pVbw+N!nyLj~wnRi{4mNy{WDV)G1!6$y=+x6U{ z%4_9=Q^L!x_gAYp?J3+u5hA5cO8aHeI=6AC8^S{mzhqCBvBLYEutUC(X0>hKg|AvN zvkmJCQNA45_KjW{aEcyrBppcO6G0zTy%v1&@~+2!n?kA9?>0>AjFN|JdCnHQ8$hEU zw#mwGifHppLP?89LMb(Y3Li9iCPx7W%ek}2FgD2YSzjsR4Xj<=zN{Yo@7s7(k%mP4 znT2p&4EQ@q_chd-E z78uvD*C@oba`U3W2Iw`M#`5C8jOHv8^Li<|j^SI>>>`77Dp71Vtz=J?4Zck4SdRbd zfF}C_>Y(#)r@y!Q0`tMlG#b9>5`fAI$B&tWJfbGlYW$J4V+-s=HH!`+;1XeL@USdx zR0$G&&XBf9lQtkH5)p=U!8J!1{oc4E!N-~Abxl6E;;=3-hMYZ+44?u}zabmCE)yB?*_w91m$n1Yskp&@ z;kxeJX-#ioX^{elyLu~gzx|_KxLpX62MF%Axq3$!Z_P`pBWR?zP8OI`PV~6Aa0Oi0 zv_Ot1m&plf-ZF{e(z(Ms3*S5q$e|j;gOwGrmWsCHfLi(h8y?gc$(2H{884C1FvHQQ12tX=qFUsK~zM!W=K>;zaRsu4Xmcc@8nSs!vK+{ z?}bq}-m&p5jRSam67n>yG9ez=I^|J1O;Np8s=P~9MXYLxD+cFQK7PhG=bkjo{Naae zjp3NWWrlFWDb3Z5D07Q|WjZ=wOQ=aKA%en=O@hL$QCKpIXNZE=InFk|Fhq-&H!6&X z*MVy8=hL7Aw&pQjHrFf27C%3B<>FX{@fOLNhUoxL4*@nY}&M3G*T-p67a zo}~_&yGOB)#vbU|Q3FA8S^X)c-yBlmN(_%}`7Ha3uWFe?>9f=3hlO{^gv~$p`v?vk z_P*r43|(S{%ihs;)YH|jAMpP=-Ms7Ne75_YZZiL3CHVjSU`X1|?Ehh&gA=Xn7W7d@ zf8bM9Y>lG!`PWFDDA9G;x*{1Eh^55u66*9D+-4^dYZ{xXP@?sQLVrY%(azM;C^4FuN7CQ%$!3sr1JL=!Be& zuOZL^bLp$Qo2rL=WDzQIls%s!Go z{s}Q0b#+#8bKga|01t%^9Z=wEsevvXM_{$dCR97ed3@1kX)mtSS!JN^rtqKOj}p~> zfpCI@DX*DqcB6ZnBcl~}sGO~1s$AtfkX6fy3N8*ebvZc*KBW;dA=)?#BE&}-or74i zZUt5;{FBPnkZD8YUXDsx&2LvSziAlec3oc>&Lf1Doc3g?H9{OO_$M4B0qTat0UsWP zTlxUeQ3B;oJ%en4n?zQB6*Fb#wH7`$SQN5GI|=DnJKiYm{?-?#-H;#sIjz7kQ4&VW zN9d1(1$_W~S=<%qDD!mwRytas=eqX^iW}YSx3;wJ#)Xp_`Qk1DFiXac$-3;jQbCif zLA-T_s~5yP@Q@W>pXKl^gipQ>gp@HlBB>WDVpW199;V%?N1`U$ovLE;NI2?|_q2~5 zlg>xT9NADWkv5-*FjS~nP^7$k!N2z?dr!)&l0+4xDK7=-6Rkd$+_^`{bVx!5LgC#N z-dv-k@OlYCEvBfcr1*RsNwcV?QT0bm(q-IyJJ$hm2~mq{6zIn!D20k5)fe(+iM6DJ ze-w_*F|c%@)HREgpRrl@W5;_J5vB4c?UW8~%o0)(A4`%-yNk1(H z5CGuzH(uHQ`&j+IRmTOKoJ?#Ct$+1grR|IitpDGt!~ZdqSJ?cOtw-R=EQ+q4UvclH zdX=xlK-fhQKoKCPBoFAZ*(~11O6-tXo>i0w!T$u{lg!#itEUX3V{$S*naW!C@%rll zS{L(1t%xz(*B`{1NL!*aMc<~fE=g;gXi&Gb$HpD!P)8?JzfN;4F&wv(5HH<=c>>)n z({271)xREH89=C(5YKL{mmJJ_d>qHz;;gTvTlgM*vz9@YTTYZ#%_2A zS0G-t9oMQEpvfv(UjfQ8T$vAHi)zOj3>D*{xSRiu3acc=7cvLyD?_ZObdu$5@b*!y zaZ#u?7uF}SrHVQa=sTOhGW{6WUlq#RhPPm^GsRH#qlX8{Kq-i~98l;eq>KdCnWyKl zUu&UWBqu#Tt9jQ97U4}3)&(p2-eCLznXMEm!>i^EMpeVzPg%p;?@O;dJBQQY(vV;d z3v+-3oTPC!2LTUAx^S2t{v;S_h(EZ^0_dS5g^F*m{TEIy^Qal~%mu3h7*o`jWOH}i ztv8M)3X3a*+ry_KkYXYE4dB0?M|t}#Tp+(}6CQ zBbq;xhoHj}b@j-@koDB#XcCY~>_x&Y;i%MH|3tF^X2h{36UCVfQ-;oEA+4ZkJ`^Qi zQf^8}6eFO$Z+Dj-F1wkG##tTx>FjR2oOXFmbKFj6K3+=kePQ<4d7%z5R5cOB;zO6| zm9^m#U4lcA;7t&*=q|a-!`!)}SgYXT#i8hnxtx@kaoBF$QAS-hT7N5kH^l zB^i+})V>L;9_0Qqf-dyF%ky8Mp-dp#%!Nls3vCt}q3QLM3M-(Zs1k}1bqQ9PVU)U` ztE=?;^6=x}_VD%N@${>qhpkU*)AuUBu_cqYiY&@;O$HV*z@~#Tzh?#=CK`=KwBv+o zh%zu%0xPKYtyC)DaQ zpDW}*86g%>BH3IcWMq`g$j()0kWE(qkIL8A&A0mf&+BzxpKF}=`#jG% z&*wa!&pGFLs5_b#QTZE4Bp+})qzyPQ7B4Z7Y*&?0PSX&|FIR;WBP1|coF9ZeP*$9w z!6aJ_3%Sh=HY3FAt8V144|yfu}IAyYHr1OYKIZ51F>_uY^%N#!k~eU53at-_E-Gh?ahmM5y* z+BTIbeH;%v1}Cjo{8d%UeSMWg(nphxEU`sL< zQR~LrTq>Da(FqSP2%&^1ZL#DTo5Sbl9;&57tQ-@U&I#lj)aNSkcfEJwQD!33?anVU z?pw2q7WtMvfji493`rSFnyp7{w87cW`ak=UEYlk5PCB1K6UDVKXyozOChH4yHh~Q< zv>yvKw6WLfi!PZUx60JZcTNM7jo{ww9b8Q+S7C3WA5&llSwdwh$=Q(*(f3ofqcz=nwOmOy z(J!K=*wNoRU*${{Mbwapi9pTB(&VVKefqd-qrUb9*Eyr2E@oZ9Cgf}Mc;QP<0D)R4 zz=!*^VIG4T*7Xl=sJxrWv9hW^eJ%qYp5(d0?E6LZzJ}=7E+1{?GQA;z+!^VBD81}O z0kJ^dKy&WMw+1+aGVYY-v@i28@Gm+sX5=@U%F=Z?W)oar}2~Rc&F|+3A)n-U2GF10+QdxDb^iA@7eL$c7yhBtL z>lABrh^qy9XZ${E1}Ss5!N4;ig0-pUh6@|RPCHOWvgG{|l}2enRgJftsN%D|ck0YO zuAQd2aMPSyGuJ~jm)aY=+p~mGudw4erwE%P^)5f<*$$2C-4^I=e8-}7##ZQ!8!Tep z+Z_!}CAI~sry$|XK$ktXaxP*x<_ijCPp`2=6sNLZU<@9Sz-rz7^BCE9yh0jV4(I!Z zxmA4d;>B-!vD}Xp*&*N%`b^e&R;D97WS}{~{O-EtXeZNfdf51tw!WR6Noo4hjHPv5 z?heYYRSBPjMc}tFEU^|U8a1CxxK%)WTcn9P%`wR^I$QSeMn6=w>Z9OoVvcrl`zYlZ z2y`mAu0bV(Scc>G_EmIo_4 zm*~h`mxYZC&+U>C5G1FZH5L^U>Cq-9UDRQa35jz&NBj*0{uJKfZs5=Fn@&)Xh6aX(H3w9m9BGLePqVotxTeSPh5-mc7$# z-80t6yB0$Nx<54ohdO*QL7m_(&+#*=eoNiYDB4rE4Cag@qfyZS};Fx;Vf1;oync2k z9v#-w?d6R& zOI`CCS_d=tf3|?g3Z}b6-_Rdg3y~enQhmgkni0Cvf9m6%Ft8r;NC5|b%t&?lkl*4{ z8Ui^;Ds^gq6ti(1xB7y_$zA!i-M~#!!tl$ErTR>P~>T=Yky)8(uvPbvLmB=UfoD zrfl}8<1OQrm?8#j1!?s*T>AoectQl&m!o&*^JcIW`_&bk3tN}k^0rjl=HL$z*uIYt z?7l?^Dqr?q1210Sp$xoAy!&{2^{^Anl460 zI&7urrc&|Y{rjv04VOl{y7c82N6xzg5ueYmQ(q(zC3w_C#x*~%yf5j7MI{W`tsoxzA*PrmK)cTskU| zf2C}Bq$>S$-1JgIh0aW@LxI|-8(OGuD#^M01ghh}&#ObO>tZgSw_LW`zdf&IN$YO# z)|X_9m#JwLW5pErZB3ScggKcNzxA9(hyKkK9I#pR&79&*+SV_eu={00{HF=Bb+AEe znaSof+r1jZ!EL5XgqXWkckaFSSyEk}o!%p8XsD}O>borZ6x%X2b&q!s&1-O(>`kZ$ zB2l^5Cx9xQx9)PXN1xPM)@+LxACH_iZ8zGc(>wnFS_O|@hKsxpMjXOzLEa7OvSlM&&G9ioQw9~RsD4F zK7Q+_&|Q6{eZ^8Rx@pKL`le6kH+(fLc{=V&{b%I5=n}VHV4)X_2Y!pYxgC8wU)yP! zPF3t$?(jsC>Ge=&{kmPGUEETpaw(QTAl)m#{qR3_aq9!wK%6XHfV4C>Y^>Z|%ns7j z{Ja?^IA{+@;kR#IjHxkar%3$eJT4?xNBKUVmoO z`A8Zo-{~_;vcikZ(p}EZzU4kO6WPqkMyE{VvS?;44Z@lj zz^fKX9UL!8Wc(9VgI?P4*zpis8dzl};I>yr1>dtXU=FTAlx}Eht4-*7RACL^AflGh zyZb1hTf(~CkMo%#Q%NMgM9tE2D+)joqbtHYA89Ql1nqVTt+MxZ^*FRd&n5YlIi!8m z>$Ysd!l{+C)y;Wa(ZV-=<+NZKV;v4mt}v2m>`v$-$3b;GsLxf= zd~f(rmfpl``{0aVwN7y!>eGyJFP`L+TxHjHTOS{K^$L2`@6(Rli`{EFwpH@R%eZ6g zwf7rc43Yk!=k;{ z-Rn%~B3amGr}}SxfE$vS8FIPL=Qt57$|R#sSoFgdNUT?fYOYjPl%ZBFpi=jq=DWby7Zxm@y;B<89!9= zbgEH*Uy)~iq5kJLX$+ps$kV`#6jW#|9BGz^`ivNeid(wVbk4jl)VBpW&~;eXNi{#` zwx?{DXR~*sqQcFhY0XCfQ4-*2aN1BGX>$_swtKEqnd>j6vcZ!#0)pXRi?<{!P?tGw z2x_`RD$W)qD{?z}VDPt?+)8*rqLWFIPQ(9-VbBdf{7ff?w9CZ{sIi_gnuC$I0(+P8 zms9XB%}VQ>>pve##}jog6+cD?v~n4Pa9Vmc zg#K$|+`adO=B7`uj35Y}6EZ z{dY`x@w8;R-7zrsr1O_~Jvl*|o-x%jF=Rr1C}GXP^|IYN`1sqmG-oI@R#%X66c#5W z$$tQB)sqwiVm;Y^`Dw3mo|firP{*HsOQJre5%Dm^H@we0FN88VWJ0dja?_U38z73f zrCV!b3qNP0kM#%9T!W5`ynGcg%BL28FW1J-J1_S`BJGCaReQ!am(2%qZ3lLgzq|ns z!!fF@`0=*z)J2BwZ*hO|Yu^cI_nF$9l-Pb3jE7=P8gZ#!xiuZ7-cSa`gb`6mxGTgg z-DLdID?M!Z%+hHB#{?&0$GFRpf+_}q<_wbzX6K?w;%6szz1RbySDSr2r^h_qi$khs zXdZ9A0!_Bf)TR2-^-K~q`FQ!#1x(U4VbV%AA@Ei{%cA(EwC{XfjRi?`&9rav5;Q5% zO1`Rn@OA_ZB@N*mC#)?d3P!}Eh;=NgpIKsy{(yr`hv=aouwt@r&P&}Z3DNWo9ro30 zX52~(aTV$*HHlgB66-4GQru!_AZ|)V*I5X=WG)`N@U&D>e@@C#V@JwEL*L`7#$yes z62C^5%Qniaow2$3HrAc7U{qzpb&FA*xLI1JSWR@`RF=JCcvTI)%dH7;sWInt9JLu# z|Ao|Q?K)cDg_JKsym=joo5gR80wtv01N`um1nQ@Ms0Y*bVzxL34} zo?gizp?`=Y{*W>^Hy2%Jl)y?A+&7s1UVHFixuIy~sawXjcDCL`129cK7|ZQS0u;A} zTJC#WNmqkIrnHpAhHVcM(U^vJA~dl@jf_bs*3?i+=&vuC?Aiy_pcB~=1syDni4 zw+FLuz>F773u#$;NUQ9WDtUPY@+rA3WBhQdKFKOyzkA(URa7;4tW>3jQIfi8v0h3g zJC_HVDXS#>DWb|&se7FHnr=q&l#xg9o02}}u=b-R>@sw={Z zHF*?t2FmhqZ=|qa>x=A!*$S+0T zhO*D*M?NTf-eX`eO)9TIQu{7Dm77Acnj4b1jI9@c*ZL8wL%8kLEhd$KM8=Y!fbN@9 zC7B5#y>JM1n5M)!&im==EgHs2j+xCZG~+~QWCi?s!QyFo2kqx{%jE2n3^N*Ayz6Lp zhg5g^3# z+5FoJ@$u@9WJgPKpUWEd4}4AK9TJKU8W%ms!d0p%OIOX+bY+55zl!vIaz$XFI9Ep+ z;bL_}7PDI2Y`Ng*XY(65 zh0%`@Lve%fc;)N4_g12bNrt6gH=N#OHtxO`$lpWlw=Z6MF+E@;>GkZ#lAZTn`aHwf z&I1|aV#b_VHMIgBN*RzU9i@Z@m}0i>o?({&%fpEfaOpFeaJ7V37;m0?kzd}}Lk@9$ zL}8TEo7WZAcRi%zFZxkr6<0k#X-;lTD`Oc~cDb@olwgWCewvk{GJ}hCXbF!AdiLpd z|Cck$ZTKI?Ack{34Lva7+k=H8K2HTZiurox6F+>dy+@R9T^awxj590D$|kXUg+Ygc z(f)jlRwN(4z$#%PnOVc;#Fv{nAi{#UcXPNcmP#5O{zh_*`=q^JCeia{sN4zHjk2*y zqUVh{Ya{j>SPmP^i#Qfcq_MTqo8g52Fi^F zKBc$$HVI!xFx*4Y9l+nt)$AoZORD}%5I10oI3kx`-N30QueiwIw#0VV2E*Fb-nKW% z=+r^hos`Y-7~{cA1FVbK$_=~*z53+Q8KGjg;>ztg((H12%QTf4OYU8y)C}h5yo#$% z&Q$`vMM*g?ZcatAn2j!hFv8KuN(dw)T*}sF#THDHxo8xC^?vJ zc`U6bVo~hOr6I!8*GTZ<^D~;unKjK=!IR|GB4E>Mcvt*2GK);93jIDd<(nNjHO z4Hi@2^%Uyx=^Z~5eZ!5rO5%4H|eFoNjD#+Kcu%_57zZb4Z@Ak#X6txD^{U3wBl^r+W- zLorkK;uc;NgTj7dGxHQS+@T*T>Q*j4^Ll$ejQqWrwcHyG9y%Mk%m8nBVG5hvSaYm5 zJN^#-Q46kZG)@T8n2^QCjxIwxUVi%s>EY`E?#@_(A~njFrTiDq;8v|W-1jT|ROlNI zU$h|YoD4PVTE^&NC6_m{EAFBVqsM`P*`-AcDGWQygURzM32Xeq2xng~XQsYeTZ5v$ zQLaa2M_Iplw}4eL6fLPu`6`PYcVMysO>`{8CB~glD=TX7?JZcHfHNmykBM?QD)#D) zGp>R*<^D?WhFQKRc^}22l6F=D2RPrxaX2ZF!b1X0XF*d4%=!sbNcS1q2WOUE(7e4$ z^L8f;F)__d3>&KQFE8%$I4h^y5FYBfB&fWzn71_OSrPe-DHV{O#Q;GP z+Tw!J?eVjX19RKH?*hKQWQt8r7B#lYX8xoSHFGCW-*DSQ4EM4M3Mw%gkSYNK18@(e zfzMF}WWaCyS@1y%-~Xg0ry~tkQkUmKuI5lGAua{{vn22V!2T()AU5FpKh@Nv)s^Js zv~@VuUG;=CnLmQR{PeUBQf2;lAV!vG>^Z0N zL88rrjL-*J!43;7C=w9xhcw`yjRKq7o4L9=0SmR9PA-nX12@#h(iIu-0N_xm2OV)( zU_raT0y>$wm^oMi2|U3N;OhF9uy}`<-xVka#DV*l{O0yHzi9vUxa1Qtpi$buR*8cU zd4~lS1pT$L^!0=6qUKOpM+XPsy{f7W#1bjrEwaeN!Ik9(zySIT^pEHvHgJUneFN4) zk=k|$55(g8slmS|@+*4fr2urd3LwjIIZA**g+%l(SZNn4HwQ}y6o`vw>2&mR1X+&q zDa1Af0B;4rAMZMOlHbAqK|R_xuwJ7ANARtFE({-P2o{tJJR<>2KVp)ZK-M;)ejx zd*E~Mka<{OL7%CAhk4n|1qg?97-I!l0rOinjVi#arbgg4bi5;nY5oFL`UWtPk5&L#grSxv zE3!}=1px!ZTLT90aYc^s`~{VojjJml&<`@e41dFP+XU6D0AOkbn2rlI3>^LcqauG& zc$m3Z{!u8LvUrm^fT{qX5yD9{?r(CCiUdck%!T`KIZd2oQJz1joB&M(Teg_>;yS<2-5>BWfSPpG`Rt{!j6>kqMAvl^zk0JUEfy$HVJMkxP-GkwZuxL62me2#pj_5*ZIU zP~#C^OZLfl$HO)v;~~c&JHivn|1I9H5y_CDkt0JLLGKm(4*KLVhJ2jh2#vJuM6`b& zE==-lvME^Oj022xF&IV*? '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/crates/voicevox_core_java_api/gradlew.bat b/crates/voicevox_core_java_api/gradlew.bat new file mode 100644 index 000000000..93e3f59f1 --- /dev/null +++ b/crates/voicevox_core_java_api/gradlew.bat @@ -0,0 +1,92 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/crates/voicevox_core_java_api/lib/build.gradle b/crates/voicevox_core_java_api/lib/build.gradle new file mode 100644 index 000000000..8e6bde364 --- /dev/null +++ b/crates/voicevox_core_java_api/lib/build.gradle @@ -0,0 +1,41 @@ +/* + * This file was generated by the Gradle 'init' task. + * + * This generated file contains a sample Java library project to get you started. + * For more details on building Java & JVM projects, please refer to https://docs.gradle.org/8.2.1/userguide/building_java_projects.html in the Gradle documentation. + */ + +plugins { + // Apply the java-library plugin for API and implementation separation. + id 'java-library' +} + +repositories { + // Use Maven Central for resolving dependencies. + mavenCentral() +} + +dependencies { + // Use JUnit Jupiter for testing. + testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2' + + testRuntimeOnly 'org.junit.platform:junit-platform-launcher' + + // This dependency is exported to consumers, that is to say found on their compile classpath. + api 'org.apache.commons:commons-math3:3.6.1' + + // This dependency is used internally, and not exposed to consumers on their own compile classpath. + implementation 'com.google.guava:guava:31.1-jre' +} + +// Apply a specific Java toolchain to ease working on different environments. +java { + toolchain { + languageVersion = JavaLanguageVersion.of(8) + } +} + +tasks.named('test') { + // Use JUnit Platform for unit tests. + useJUnitPlatform() +} diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/OpenJtalk.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/OpenJtalk.java new file mode 100644 index 000000000..3b91ca5e6 --- /dev/null +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/OpenJtalk.java @@ -0,0 +1,9 @@ +package jp.Hiroshiba.VoicevoxCore; + +public class OpenJtalk { + native static boolean test(); + + static { + System.loadLibrary("voicevox_core_java_api"); + } +} diff --git a/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/OpenJtalkTest.java b/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/OpenJtalkTest.java new file mode 100644 index 000000000..972cd19d0 --- /dev/null +++ b/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/OpenJtalkTest.java @@ -0,0 +1,14 @@ +/* + * This Java source file was generated by the Gradle 'init' task. + */ +package jp.Hiroshiba.VoicevoxCore; + +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.*; + +class OpenJtalkTest { + @Test + void someLibraryMethodReturnsTrue() { + assertTrue(OpenJtalk.test(), "someLibraryMethod should return 'true'"); + } +} diff --git a/crates/voicevox_core_java_api/settings.gradle b/crates/voicevox_core_java_api/settings.gradle new file mode 100644 index 000000000..b8e6bb336 --- /dev/null +++ b/crates/voicevox_core_java_api/settings.gradle @@ -0,0 +1,14 @@ +/* + * This file was generated by the Gradle 'init' task. + * + * The settings file is used to specify which projects to include in your build. + * For more detailed information on multi-project builds, please refer to https://docs.gradle.org/8.2.1/userguide/building_swift_projects.html in the Gradle documentation. + */ + +plugins { + // Apply the foojay-resolver plugin to allow automatic download of JDKs + id 'org.gradle.toolchains.foojay-resolver-convention' version '0.4.0' +} + +rootProject.name = 'jp.Hiroshiba.VoicevoxCore' +include('lib') diff --git a/crates/voicevox_core_java_api/src/lib.rs b/crates/voicevox_core_java_api/src/lib.rs new file mode 100644 index 000000000..1e44ddf20 --- /dev/null +++ b/crates/voicevox_core_java_api/src/lib.rs @@ -0,0 +1,13 @@ +use jni::{ + objects::{JClass, JString}, + sys::{jboolean, jstring}, + JNIEnv, +}; + +#[no_mangle] +pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_OpenJtalk_test<'local>( + mut env: JNIEnv<'local>, + class: JClass<'local>, +) -> jboolean { + true.into() +} From fca848c5d2800fa28dbeed0c8afbae11fdb3d30b Mon Sep 17 00:00:00 2001 From: sevenc-nanashi Date: Sun, 30 Jul 2023 00:24:14 +0900 Subject: [PATCH 02/99] =?UTF-8?q?Add:=20OpenJtalk=E3=82=AF=E3=83=A9?= =?UTF-8?q?=E3=82=B9=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cargo.lock | 1 + crates/voicevox_core_java_api/Cargo.toml | 1 + .../jp/Hiroshiba/VoicevoxCore/OpenJtalk.java | 14 +++++++- .../VoicevoxCore/VoicevoxException.java | 7 ++++ ...{OpenJtalkTest.java => SynthesisTest.java} | 0 crates/voicevox_core_java_api/src/lib.rs | 34 ++++++++++++++++--- crates/voicevox_core_java_api/src/utils.rs | 13 +++++++ 7 files changed, 64 insertions(+), 6 deletions(-) create mode 100644 crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/VoicevoxException.java rename crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/{OpenJtalkTest.java => SynthesisTest.java} (100%) create mode 100644 crates/voicevox_core_java_api/src/utils.rs diff --git a/Cargo.lock b/Cargo.lock index 9590119de..ef3984435 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4102,6 +4102,7 @@ dependencies = [ name = "voicevox_core_java_api" version = "0.0.0" dependencies = [ + "easy-ext", "jni", "voicevox_core", ] diff --git a/crates/voicevox_core_java_api/Cargo.toml b/crates/voicevox_core_java_api/Cargo.toml index af09ef378..01ad02e19 100644 --- a/crates/voicevox_core_java_api/Cargo.toml +++ b/crates/voicevox_core_java_api/Cargo.toml @@ -8,6 +8,7 @@ publish.workspace = true crate-type = ["cdylib"] [dependencies] +easy-ext.workspace = true jni = "0.21.1" voicevox_core.workspace = true diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/OpenJtalk.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/OpenJtalk.java index 3b91ca5e6..87d02f352 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/OpenJtalk.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/OpenJtalk.java @@ -1,7 +1,19 @@ package jp.Hiroshiba.VoicevoxCore; public class OpenJtalk { - native static boolean test(); + private long internalPtr; + + public OpenJtalk() { + internalPtr = rsNewWithoutDic(); + } + + public OpenJtalk(String open_jtalk_dict_dir) { + internalPtr = rsNewWithInitilize(open_jtalk_dict_dir); + } + + private native long rsNewWithoutDic(); + + private native long rsNewWithInitilize(String open_jtalk_dict_dir); static { System.loadLibrary("voicevox_core_java_api"); diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/VoicevoxException.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/VoicevoxException.java new file mode 100644 index 000000000..0fa6fa42f --- /dev/null +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/VoicevoxException.java @@ -0,0 +1,7 @@ +package jp.Hiroshiba.VoicevoxCore; + +class VoicevoxException extends RuntimeException { + public VoicevoxException(String message) { + super(message); + } +} diff --git a/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/OpenJtalkTest.java b/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/SynthesisTest.java similarity index 100% rename from crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/OpenJtalkTest.java rename to crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/SynthesisTest.java diff --git a/crates/voicevox_core_java_api/src/lib.rs b/crates/voicevox_core_java_api/src/lib.rs index 1e44ddf20..a1fc54c40 100644 --- a/crates/voicevox_core_java_api/src/lib.rs +++ b/crates/voicevox_core_java_api/src/lib.rs @@ -1,13 +1,37 @@ +mod utils; use jni::{ objects::{JClass, JString}, - sys::{jboolean, jstring}, + sys::jlong, JNIEnv, }; #[no_mangle] -pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_OpenJtalk_test<'local>( +pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_OpenJtalk_rsNewWithoutDic<'local>( + mut _env: JNIEnv<'local>, + _class: JClass<'local>, +) -> jlong { + let internal = voicevox_core::OpenJtalk::new_without_dic(); + let internal_ptr = Box::into_raw(Box::new(internal)); + + internal_ptr as jlong +} + +#[no_mangle] +pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_OpenJtalk_rsNewWithInitialize<'local>( mut env: JNIEnv<'local>, - class: JClass<'local>, -) -> jboolean { - true.into() + _class: JClass<'local>, + open_jtalk_dict_dir: JString<'local>, +) -> jlong { + let open_jtalk_dict_dir = env + .get_string(&open_jtalk_dict_dir) + .expect("invalid java string"); + let open_jtalk_dict_dir = open_jtalk_dict_dir.to_str().unwrap(); + + let internal = unwrap_with_throw!( + env, + voicevox_core::OpenJtalk::new_with_initialize(open_jtalk_dict_dir) + ); + let internal_ptr = Box::into_raw(Box::new(internal)); + + internal_ptr as jlong } diff --git a/crates/voicevox_core_java_api/src/utils.rs b/crates/voicevox_core_java_api/src/utils.rs new file mode 100644 index 000000000..28c958a84 --- /dev/null +++ b/crates/voicevox_core_java_api/src/utils.rs @@ -0,0 +1,13 @@ +#[macro_export] +macro_rules! unwrap_with_throw { + ($env:expr, $expr:expr) => { + match $expr { + Ok(value) => value, + Err(error) => { + $env.throw_new("jp/Hiroshiba/VoicevoxCore/VoicevoxError", error.to_string()) + .unwrap(); + return 0; + } + } + }; +} From 5f096509e114db1293bf6a43b621c5419c772ba1 Mon Sep 17 00:00:00 2001 From: sevenc-nanashi Date: Sun, 30 Jul 2023 01:15:30 +0900 Subject: [PATCH 03/99] =?UTF-8?q?WIP:=20VoiceModel=E3=82=92=E8=BF=BD?= =?UTF-8?q?=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cargo.lock | 72 +++++++++- crates/voicevox_core_java_api/Cargo.toml | 6 + .../jp/Hiroshiba/VoicevoxCore/OpenJtalk.java | 10 +- .../Hiroshiba/VoicevoxCore/SpeakerMeta.java | 8 ++ .../jp/Hiroshiba/VoicevoxCore/StyleMeta.java | 6 + .../jp/Hiroshiba/VoicevoxCore/VoiceModel.java | 18 +++ crates/voicevox_core_java_api/src/lib.rs | 129 ++++++++++++++++-- 7 files changed, 229 insertions(+), 20 deletions(-) create mode 100644 crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/SpeakerMeta.java create mode 100644 crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/StyleMeta.java create mode 100644 crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/VoiceModel.java diff --git a/Cargo.lock b/Cargo.lock index ef3984435..1463f248d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -92,6 +92,30 @@ dependencies = [ "memchr", ] +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_log-sys" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27f0fc03f560e1aebde41c2398b691cb98b5ea5996a6184a7a67bbbb77448969" + +[[package]] +name = "android_logger" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fa490e751f3878eb9accb9f18988eca52c2337ce000a8bf31ef50d4c723ca9e" +dependencies = [ + "android_log-sys", + "env_logger 0.10.0", + "log", + "once_cell", +] + [[package]] name = "android_system_properties" version = "0.1.5" @@ -356,7 +380,7 @@ dependencies = [ "cexpr", "clang-sys", "clap 3.2.22", - "env_logger", + "env_logger 0.9.1", "lazy_static", "lazycell", "log", @@ -532,14 +556,17 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.23" +version = "0.4.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16b0a3d9ed01224b22057780a37bb8c5dbfe1be8ba48678e7bf57ec4b385411f" +checksum = "ec837a71355b28f6556dbd569b37b3f363091c0bd4b2e735674521b4c5fd9bc5" dependencies = [ + "android-tzdata", "iana-time-zone", - "num-integer", + "js-sys", "num-traits", "serde", + "time 0.1.45", + "wasm-bindgen", "winapi", ] @@ -1126,6 +1153,16 @@ dependencies = [ "termcolor", ] +[[package]] +name = "env_logger" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0" +dependencies = [ + "log", + "regex", +] + [[package]] name = "equivalent" version = "1.0.1" @@ -3604,6 +3641,17 @@ dependencies = [ "num_cpus", ] +[[package]] +name = "time" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" +dependencies = [ + "libc", + "wasi 0.10.0+wasi-snapshot-preview1", + "winapi", +] + [[package]] name = "time" version = "0.2.27" @@ -3844,9 +3892,9 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.16" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6176eae26dd70d0c919749377897b54a9276bd7061339665dd68777926b5a70" +checksum = "30a651bc37f915e81f087d86e62a18eec5f79550c7faff886f7090b4ea757c77" dependencies = [ "matchers", "nu-ansi-term", @@ -4102,8 +4150,14 @@ dependencies = [ name = "voicevox_core_java_api" version = "0.0.0" dependencies = [ + "android_logger", + "chrono", "easy-ext", "jni", + "once_cell", + "tokio", + "tracing", + "tracing-subscriber", "voicevox_core", ] @@ -4167,6 +4221,12 @@ version = "0.9.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" +[[package]] +name = "wasi" +version = "0.10.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" + [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" diff --git a/crates/voicevox_core_java_api/Cargo.toml b/crates/voicevox_core_java_api/Cargo.toml index 01ad02e19..1a3e6e008 100644 --- a/crates/voicevox_core_java_api/Cargo.toml +++ b/crates/voicevox_core_java_api/Cargo.toml @@ -8,7 +8,13 @@ publish.workspace = true crate-type = ["cdylib"] [dependencies] +android_logger = "0.13.1" +chrono = "0.4.26" easy-ext.workspace = true jni = "0.21.1" +once_cell.workspace = true +tokio.workspace = true +tracing = { workspace = true, features = ["log"] } +tracing-subscriber = "0.3.17" voicevox_core.workspace = true diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/OpenJtalk.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/OpenJtalk.java index 87d02f352..eae13e61a 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/OpenJtalk.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/OpenJtalk.java @@ -1,19 +1,19 @@ package jp.Hiroshiba.VoicevoxCore; public class OpenJtalk { - private long internalPtr; + protected long internalPtr; public OpenJtalk() { - internalPtr = rsNewWithoutDic(); + rsNewWithoutDic(); } - public OpenJtalk(String open_jtalk_dict_dir) { - internalPtr = rsNewWithInitilize(open_jtalk_dict_dir); + public OpenJtalk(String openJtalkDictDir) { + rsNewWithInitilize(openJtalkDictDir); } private native long rsNewWithoutDic(); - private native long rsNewWithInitilize(String open_jtalk_dict_dir); + private native long rsNewWithInitilize(String openJtalkDictDir); static { System.loadLibrary("voicevox_core_java_api"); diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/SpeakerMeta.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/SpeakerMeta.java new file mode 100644 index 000000000..f6e5348c8 --- /dev/null +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/SpeakerMeta.java @@ -0,0 +1,8 @@ +package jp.Hiroshiba.VoicevoxCore; + +public class SpeakerMeta { + String name; + StyleMeta[] styles; + String speakerUuid; + String version; +} diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/StyleMeta.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/StyleMeta.java new file mode 100644 index 000000000..eba116dfe --- /dev/null +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/StyleMeta.java @@ -0,0 +1,6 @@ +package jp.Hiroshiba.VoicevoxCore; + +public class StyleMeta { + String name; + Integer id; +} diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/VoiceModel.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/VoiceModel.java new file mode 100644 index 000000000..384cc6db3 --- /dev/null +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/VoiceModel.java @@ -0,0 +1,18 @@ +package jp.Hiroshiba.VoicevoxCore; + +public class VoiceModel { + protected long internalPtr; + + public String id; + public SpeakerMeta[] metas; + + public VoiceModel(String modelPath) { + internalPtr = rsFromPath(modelPath); + } + + native static long rsFromPath(String modelPath); + + static { + System.loadLibrary("voicevox_core_java_api"); + } +} diff --git a/crates/voicevox_core_java_api/src/lib.rs b/crates/voicevox_core_java_api/src/lib.rs index a1fc54c40..6a3902d4b 100644 --- a/crates/voicevox_core_java_api/src/lib.rs +++ b/crates/voicevox_core_java_api/src/lib.rs @@ -1,27 +1,95 @@ mod utils; use jni::{ - objects::{JClass, JString}, - sys::jlong, + objects::{JClass, JObject, JString, JValueGen}, + sys::{jboolean, jlong}, JNIEnv, }; +use once_cell::sync::Lazy; +use tokio::runtime::Runtime; +static RUNTIME: Lazy = Lazy::new(|| { + if cfg!(target_os = "android") { + android_logger::init_once( + android_logger::Config::default() + .with_tag("VoicevoxCore") + .with_filter( + android_logger::FilterBuilder::new() + .parse( + "error,voicevox_core=info,voicevox_core_java_api=info,onnxruntime=info", + ) + .build(), + ), + ); + } else { + // TODO: Android以外でのログ出力を良い感じにする。(System.Loggerを使う?) + use chrono::SecondsFormat; + use std::{ + env, fmt, + io::{self, IsTerminal, Write}, + }; + use tracing_subscriber::{fmt::format::Writer, EnvFilter}; + + let _ = tracing_subscriber::fmt() + .with_env_filter(if env::var_os(EnvFilter::DEFAULT_ENV).is_some() { + EnvFilter::from_default_env() + } else { + "error,voicevox_core=info,voicevox_core_c_api=info,onnxruntime=info".into() + }) + .with_timer(local_time as fn(&mut Writer<'_>) -> _) + .with_ansi(out().is_terminal() && env_allows_ansi()) + .with_writer(out) + .try_init(); + + fn local_time(wtr: &mut Writer<'_>) -> fmt::Result { + // ローカル時刻で表示はするが、そのフォーマットはtracing-subscriber本来のものに近いようにする。 + // https://github.com/tokio-rs/tracing/blob/tracing-subscriber-0.3.16/tracing-subscriber/src/fmt/time/datetime.rs#L235-L241 + wtr.write_str(&chrono::Local::now().to_rfc3339_opts(SecondsFormat::Micros, false)) + } + + fn out() -> impl IsTerminal + Write { + io::stderr() + } + + fn env_allows_ansi() -> bool { + // https://docs.rs/termcolor/1.2.0/src/termcolor/lib.rs.html#245-291 + // ただしWindowsではPowerShellっぽかったらそのまま許可する。 + // ちゃんとやるなら`ENABLE_VIRTUAL_TERMINAL_PROCESSING`をチェックするなり、そもそも + // fwdansiとかでWin32の色に変換するべきだが、面倒。 + env::var_os("TERM").map_or( + cfg!(windows) && env::var_os("PSModulePath").is_some(), + |term| term != "dumb", + ) && env::var_os("NO_COLOR").is_none() + } + } + Runtime::new().unwrap() +}); #[no_mangle] pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_OpenJtalk_rsNewWithoutDic<'local>( - mut _env: JNIEnv<'local>, - _class: JClass<'local>, -) -> jlong { + mut env: JNIEnv<'local>, + this: JObject<'local>, +) -> jboolean { let internal = voicevox_core::OpenJtalk::new_without_dic(); let internal_ptr = Box::into_raw(Box::new(internal)); - internal_ptr as jlong + unwrap_with_throw!( + env, + env.set_field( + this, + "internalPtr", + "J", + JValueGen::Long(internal_ptr as jlong), + ) + ); + + true as jboolean } #[no_mangle] pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_OpenJtalk_rsNewWithInitialize<'local>( mut env: JNIEnv<'local>, - _class: JClass<'local>, + this: JObject<'local>, open_jtalk_dict_dir: JString<'local>, -) -> jlong { +) -> jboolean { let open_jtalk_dict_dir = env .get_string(&open_jtalk_dict_dir) .expect("invalid java string"); @@ -33,5 +101,48 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_OpenJtalk_rsNewWithInitial ); let internal_ptr = Box::into_raw(Box::new(internal)); - internal_ptr as jlong + unwrap_with_throw!( + env, + env.set_field( + this, + "internalPtr", + "J", + JValueGen::Long(internal_ptr as jlong), + ) + ); + + true as jboolean +} + +#[no_mangle] +pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_VoiceModel_rsFromPath<'local>( + mut env: JNIEnv<'local>, + this: JClass<'local>, + model_path: JString<'local>, +) -> jboolean { + let model_path = env.get_string(&model_path).expect("invalid java string"); + let model_path = model_path.to_str().unwrap(); + + let internal = unwrap_with_throw!( + env, + RUNTIME.block_on(voicevox_core::VoiceModel::from_path(model_path)) + ); + let id = unwrap_with_throw!(env, env.new_string(internal.id().raw_voice_model_id())); + let internal_ptr = Box::into_raw(Box::new(internal)); + + unwrap_with_throw!( + env, + env.set_field( + &this, + "internalPtr", + "J", + JValueGen::Long(internal_ptr as jlong), + ) + ); + + unwrap_with_throw!( + env, + env.set_field(&this, "id", "Ljava/lang/String;", JValueGen::Object(&id)) + ); + true as jboolean } From 957f11abbcb6a0ef3338133664706c475b91fd1d Mon Sep 17 00:00:00 2001 From: sevenc-nanashi Date: Sun, 30 Jul 2023 17:48:58 +0900 Subject: [PATCH 04/99] =?UTF-8?q?Refactor:=20unwrap=5For=5Fthrow\!?= =?UTF-8?q?=E3=81=8B=E3=82=89throw=5Fif=5Ferr=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cargo.lock | 1 + crates/voicevox_core_java_api/Cargo.toml | 1 + crates/voicevox_core_java_api/src/lib.rs | 81 ++++++++++------------ crates/voicevox_core_java_api/src/utils.rs | 31 ++++++--- 4 files changed, 61 insertions(+), 53 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1463f248d..da6dfb914 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4151,6 +4151,7 @@ name = "voicevox_core_java_api" version = "0.0.0" dependencies = [ "android_logger", + "anyhow", "chrono", "easy-ext", "jni", diff --git a/crates/voicevox_core_java_api/Cargo.toml b/crates/voicevox_core_java_api/Cargo.toml index 1a3e6e008..b1fec34d6 100644 --- a/crates/voicevox_core_java_api/Cargo.toml +++ b/crates/voicevox_core_java_api/Cargo.toml @@ -9,6 +9,7 @@ crate-type = ["cdylib"] [dependencies] android_logger = "0.13.1" +anyhow.workspace = true chrono = "0.4.26" easy-ext.workspace = true jni = "0.21.1" diff --git a/crates/voicevox_core_java_api/src/lib.rs b/crates/voicevox_core_java_api/src/lib.rs index 6a3902d4b..8db6c1bf7 100644 --- a/crates/voicevox_core_java_api/src/lib.rs +++ b/crates/voicevox_core_java_api/src/lib.rs @@ -1,4 +1,5 @@ mod utils; +use crate::utils::throw_if_err; use jni::{ objects::{JClass, JObject, JString, JValueGen}, sys::{jboolean, jlong}, @@ -6,6 +7,7 @@ use jni::{ }; use once_cell::sync::Lazy; use tokio::runtime::Runtime; + static RUNTIME: Lazy = Lazy::new(|| { if cfg!(target_os = "android") { android_logger::init_once( @@ -65,84 +67,77 @@ static RUNTIME: Lazy = Lazy::new(|| { #[no_mangle] pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_OpenJtalk_rsNewWithoutDic<'local>( - mut env: JNIEnv<'local>, + env: JNIEnv<'local>, this: JObject<'local>, ) -> jboolean { - let internal = voicevox_core::OpenJtalk::new_without_dic(); - let internal_ptr = Box::into_raw(Box::new(internal)); + throw_if_err(env, false, |env| { + let internal = voicevox_core::OpenJtalk::new_without_dic(); + let internal_ptr = Box::into_raw(Box::new(internal)); - unwrap_with_throw!( - env, env.set_field( this, "internalPtr", "J", JValueGen::Long(internal_ptr as jlong), - ) - ); - - true as jboolean + )?; + Ok(true) + }) as jboolean } #[no_mangle] pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_OpenJtalk_rsNewWithInitialize<'local>( - mut env: JNIEnv<'local>, + env: JNIEnv<'local>, this: JObject<'local>, open_jtalk_dict_dir: JString<'local>, ) -> jboolean { - let open_jtalk_dict_dir = env - .get_string(&open_jtalk_dict_dir) - .expect("invalid java string"); - let open_jtalk_dict_dir = open_jtalk_dict_dir.to_str().unwrap(); + throw_if_err(env, false, |env| { + let open_jtalk_dict_dir = env.get_string(&open_jtalk_dict_dir)?; + let open_jtalk_dict_dir = open_jtalk_dict_dir.to_str()?; - let internal = unwrap_with_throw!( - env, - voicevox_core::OpenJtalk::new_with_initialize(open_jtalk_dict_dir) - ); - let internal_ptr = Box::into_raw(Box::new(internal)); + let internal = voicevox_core::OpenJtalk::new_with_initialize(open_jtalk_dict_dir)?; + let internal_ptr = Box::into_raw(Box::new(internal)); - unwrap_with_throw!( - env, env.set_field( this, "internalPtr", "J", JValueGen::Long(internal_ptr as jlong), - ) - ); - - true as jboolean + )?; + Ok(true) + }) as jboolean } #[no_mangle] pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_VoiceModel_rsFromPath<'local>( - mut env: JNIEnv<'local>, + env: JNIEnv<'local>, this: JClass<'local>, model_path: JString<'local>, ) -> jboolean { - let model_path = env.get_string(&model_path).expect("invalid java string"); - let model_path = model_path.to_str().unwrap(); + throw_if_err(env, false, |env| { + let model_path = env.get_string(&model_path)?; + let model_path = model_path.to_str()?; - let internal = unwrap_with_throw!( - env, - RUNTIME.block_on(voicevox_core::VoiceModel::from_path(model_path)) - ); - let id = unwrap_with_throw!(env, env.new_string(internal.id().raw_voice_model_id())); - let internal_ptr = Box::into_raw(Box::new(internal)); + let internal = RUNTIME.block_on(voicevox_core::VoiceModel::from_path(model_path))?; + let id = env.new_string(internal.id().raw_voice_model_id())?; + let internal_ptr = Box::into_raw(Box::new(&internal)); - unwrap_with_throw!( - env, env.set_field( &this, "internalPtr", "J", JValueGen::Long(internal_ptr as jlong), - ) - ); + )?; - unwrap_with_throw!( - env, - env.set_field(&this, "id", "Ljava/lang/String;", JValueGen::Object(&id)) - ); - true as jboolean + env.set_field(&this, "id", "Ljava/lang/String;", JValueGen::Object(&id))?; + let speakers = env.new_object_array( + internal.metas().len() as i32, + object!("SpeakerMeta"), + JObject::null(), + )?; + for (i, meta) in internal.metas().iter().enumerate() { + let j_meta = env.new_object("SpeakerMeta", "()V", &[])?; + env.set_object_array_element(&speakers, i as i32, j_meta)?; + } + Ok(true) + }) as jboolean } diff --git a/crates/voicevox_core_java_api/src/utils.rs b/crates/voicevox_core_java_api/src/utils.rs index 28c958a84..d25224b2c 100644 --- a/crates/voicevox_core_java_api/src/utils.rs +++ b/crates/voicevox_core_java_api/src/utils.rs @@ -1,13 +1,24 @@ +use anyhow::Result; +use jni::JNIEnv; +pub static PACKAGE_NAME: &str = "jp/Hiroshiba/VoicevoxCore"; + #[macro_export] -macro_rules! unwrap_with_throw { - ($env:expr, $expr:expr) => { - match $expr { - Ok(value) => value, - Err(error) => { - $env.throw_new("jp/Hiroshiba/VoicevoxCore/VoicevoxError", error.to_string()) - .unwrap(); - return 0; - } - } +macro_rules! object { + ($name: literal) => { + concat!("Ljp/Hiroshiba/VoicevoxCore/", $name, ";") }; } + +pub fn throw_if_err(mut env: JNIEnv, fallback: T, inner: F) -> T +where + F: FnOnce(&mut JNIEnv) -> Result, +{ + match inner(&mut env) { + Ok(value) => value as _, + Err(error) => { + env.throw_new("jp/Hiroshiba/VoicevoxCore/VoicevoxError", error.to_string()) + .unwrap(); + fallback + } + } +} From 87a0ac45c82724c717808aa59a0447c07100784b Mon Sep 17 00:00:00 2001 From: sevenc-nanashi Date: Sun, 30 Jul 2023 20:04:27 +0900 Subject: [PATCH 05/99] =?UTF-8?q?Add:=20VoiceModel=E3=82=92=E8=BF=BD?= =?UTF-8?q?=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crates/voicevox_core_java_api/Cargo.toml | 2 +- .../jp/Hiroshiba/VoicevoxCore/OpenJtalk.java | 4 +- .../jp/Hiroshiba/VoicevoxCore/StyleMeta.java | 2 +- .../jp/Hiroshiba/VoicevoxCore/VoiceModel.java | 4 +- .../VoicevoxCore/VoicevoxException.java | 2 +- .../jp/Hiroshiba/VoicevoxCore/MetaTest.java | 22 +++++++ .../Hiroshiba/VoicevoxCore/SynthesisTest.java | 14 ----- crates/voicevox_core_java_api/src/lib.rs | 60 +++++++++++++++++-- crates/voicevox_core_java_api/src/utils.rs | 13 +++- 9 files changed, 94 insertions(+), 29 deletions(-) create mode 100644 crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/MetaTest.java delete mode 100644 crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/SynthesisTest.java diff --git a/crates/voicevox_core_java_api/Cargo.toml b/crates/voicevox_core_java_api/Cargo.toml index b1fec34d6..ceba708bc 100644 --- a/crates/voicevox_core_java_api/Cargo.toml +++ b/crates/voicevox_core_java_api/Cargo.toml @@ -16,6 +16,6 @@ jni = "0.21.1" once_cell.workspace = true tokio.workspace = true tracing = { workspace = true, features = ["log"] } -tracing-subscriber = "0.3.17" +tracing-subscriber.workspace = true voicevox_core.workspace = true diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/OpenJtalk.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/OpenJtalk.java index eae13e61a..ff9dba30c 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/OpenJtalk.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/OpenJtalk.java @@ -11,9 +11,9 @@ public OpenJtalk(String openJtalkDictDir) { rsNewWithInitilize(openJtalkDictDir); } - private native long rsNewWithoutDic(); + private native boolean rsNewWithoutDic(); - private native long rsNewWithInitilize(String openJtalkDictDir); + private native boolean rsNewWithInitilize(String openJtalkDictDir); static { System.loadLibrary("voicevox_core_java_api"); diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/StyleMeta.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/StyleMeta.java index eba116dfe..e4d56af52 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/StyleMeta.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/StyleMeta.java @@ -2,5 +2,5 @@ public class StyleMeta { String name; - Integer id; + int id; } diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/VoiceModel.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/VoiceModel.java index 384cc6db3..dc7f597c9 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/VoiceModel.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/VoiceModel.java @@ -7,10 +7,10 @@ public class VoiceModel { public SpeakerMeta[] metas; public VoiceModel(String modelPath) { - internalPtr = rsFromPath(modelPath); + rsFromPath(modelPath); } - native static long rsFromPath(String modelPath); + private native boolean rsFromPath(String modelPath); static { System.loadLibrary("voicevox_core_java_api"); diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/VoicevoxException.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/VoicevoxException.java index 0fa6fa42f..8dfe8e8a7 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/VoicevoxException.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/VoicevoxException.java @@ -1,6 +1,6 @@ package jp.Hiroshiba.VoicevoxCore; -class VoicevoxException extends RuntimeException { +public class VoicevoxException extends RuntimeException { public VoicevoxException(String message) { super(message); } diff --git a/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/MetaTest.java b/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/MetaTest.java new file mode 100644 index 000000000..065063cb7 --- /dev/null +++ b/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/MetaTest.java @@ -0,0 +1,22 @@ +/* + * This Java source file was generated by the Gradle 'init' task. + */ +package jp.Hiroshiba.VoicevoxCore; + +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.*; + +import java.io.File; + +class MetaTest { + @Test + void checkMeta() { + // cwdはvoicevox_core/crates/voicevox_core_java_api/lib + String cwd = System.getProperty("user.dir"); + File path = new File( + cwd + "/../../../model/sample.vvm"); + VoiceModel model = new VoiceModel(path.getAbsolutePath()); + + System.out.println(model); + } +} diff --git a/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/SynthesisTest.java b/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/SynthesisTest.java deleted file mode 100644 index 972cd19d0..000000000 --- a/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/SynthesisTest.java +++ /dev/null @@ -1,14 +0,0 @@ -/* - * This Java source file was generated by the Gradle 'init' task. - */ -package jp.Hiroshiba.VoicevoxCore; - -import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.*; - -class OpenJtalkTest { - @Test - void someLibraryMethodReturnsTrue() { - assertTrue(OpenJtalk.test(), "someLibraryMethod should return 'true'"); - } -} diff --git a/crates/voicevox_core_java_api/src/lib.rs b/crates/voicevox_core_java_api/src/lib.rs index 8db6c1bf7..17eea8015 100644 --- a/crates/voicevox_core_java_api/src/lib.rs +++ b/crates/voicevox_core_java_api/src/lib.rs @@ -1,7 +1,7 @@ mod utils; use crate::utils::throw_if_err; use jni::{ - objects::{JClass, JObject, JString, JValueGen}, + objects::{JObject, JString, JValueGen}, sys::{jboolean, jlong}, JNIEnv, }; @@ -110,7 +110,7 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_OpenJtalk_rsNewWithInitial #[no_mangle] pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_VoiceModel_rsFromPath<'local>( env: JNIEnv<'local>, - this: JClass<'local>, + this: JObject<'local>, model_path: JString<'local>, ) -> jboolean { throw_if_err(env, false, |env| { @@ -118,7 +118,6 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_VoiceModel_rsFromPath<'loc let model_path = model_path.to_str()?; let internal = RUNTIME.block_on(voicevox_core::VoiceModel::from_path(model_path))?; - let id = env.new_string(internal.id().raw_voice_model_id())?; let internal_ptr = Box::into_raw(Box::new(&internal)); env.set_field( @@ -128,14 +127,65 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_VoiceModel_rsFromPath<'loc JValueGen::Long(internal_ptr as jlong), )?; - env.set_field(&this, "id", "Ljava/lang/String;", JValueGen::Object(&id))?; + env.set_field( + &this, + "id", + "Ljava/lang/String;", + JValueGen::Object(&env.new_string(internal.id().raw_voice_model_id())?.into()), + )?; let speakers = env.new_object_array( internal.metas().len() as i32, object!("SpeakerMeta"), JObject::null(), )?; for (i, meta) in internal.metas().iter().enumerate() { - let j_meta = env.new_object("SpeakerMeta", "()V", &[])?; + let j_meta = env.new_object(object!("SpeakerMeta"), "()V", &[])?; + env.set_field( + &j_meta, + "name", + "Ljava/lang/String;", + JValueGen::Object(&env.new_string(meta.name())?.into()), + )?; + let j_styles = env.new_object_array( + meta.styles().len() as i32, + object!("StyleMeta"), + JObject::null(), + )?; + for (j, style) in meta.styles().iter().enumerate() { + let j_style = env.new_object(object!("StyleMeta"), "()V", &[])?; + env.set_field( + &j_style, + "name", + "Ljava/lang/String;", + JValueGen::Object(&env.new_string(style.name())?.into()), + )?; + env.set_field( + &j_style, + "id", + "I", + JValueGen::Int(style.id().raw_id() as i32), + )?; + env.set_object_array_element(&j_styles, j as i32, j_style)?; + } + env.set_field( + &j_meta, + "styles", + concat!("[", object!("StyleMeta")), + JValueGen::Object(&j_styles), + )?; + env.set_field( + &j_meta, + "speakerUuid", + "Ljava/lang/String;", + JValueGen::Object(&env.new_string(meta.speaker_uuid())?.into()), + )?; + env.set_field( + &j_meta, + "version", + "Ljava/lang/String;", + JValueGen::Object(&env.new_string(meta.version().raw_version())?.into()), + )?; + env.set_object_array_element(&speakers, i as i32, j_meta)?; } Ok(true) diff --git a/crates/voicevox_core_java_api/src/utils.rs b/crates/voicevox_core_java_api/src/utils.rs index d25224b2c..1cb88a185 100644 --- a/crates/voicevox_core_java_api/src/utils.rs +++ b/crates/voicevox_core_java_api/src/utils.rs @@ -1,6 +1,5 @@ use anyhow::Result; use jni::JNIEnv; -pub static PACKAGE_NAME: &str = "jp/Hiroshiba/VoicevoxCore"; #[macro_export] macro_rules! object { @@ -16,8 +15,16 @@ where match inner(&mut env) { Ok(value) => value as _, Err(error) => { - env.throw_new("jp/Hiroshiba/VoicevoxCore/VoicevoxError", error.to_string()) - .unwrap(); + // Java側の例外は無視する。 + // env.exception_clear()してもいいが、errorのメッセージは"Java exception was thrown" + // となり、デバッグが困難になるため、そのままにしておく。 + if !env.exception_check().unwrap_or(false) { + env.throw_new( + "jp/Hiroshiba/VoicevoxCore/VoicevoxException", + error.to_string(), + ) + .unwrap_or_else(|_| panic!("Failed to throw exception, original error: {}", error)); + } fallback } } From 4228435a50994ca305969b1689055d6910111c26 Mon Sep 17 00:00:00 2001 From: sevenc-nanashi Date: Mon, 31 Jul 2023 21:29:57 +0900 Subject: [PATCH 06/99] =?UTF-8?q?Refactor:=20=E3=83=95=E3=82=A1=E3=82=A4?= =?UTF-8?q?=E3=83=AB=E5=88=86=E5=89=B2=E3=80=81internal=E5=91=A8=E3=82=8A?= =?UTF-8?q?=E3=82=92jni-rs=E3=81=AE=E3=82=82=E3=81=AE=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../jp/Hiroshiba/VoicevoxCore/OpenJtalk.java | 14 +- .../jp/Hiroshiba/VoicevoxCore/VoiceModel.java | 13 +- crates/voicevox_core_java_api/src/common.rs | 90 ++++++++ crates/voicevox_core_java_api/src/lib.rs | 197 +----------------- .../voicevox_core_java_api/src/open_jtalk.rs | 48 +++++ crates/voicevox_core_java_api/src/utils.rs | 31 --- .../voicevox_core_java_api/src/voice_model.rs | 101 +++++++++ 7 files changed, 264 insertions(+), 230 deletions(-) create mode 100644 crates/voicevox_core_java_api/src/common.rs create mode 100644 crates/voicevox_core_java_api/src/open_jtalk.rs delete mode 100644 crates/voicevox_core_java_api/src/utils.rs create mode 100644 crates/voicevox_core_java_api/src/voice_model.rs diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/OpenJtalk.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/OpenJtalk.java index ff9dba30c..a0b114914 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/OpenJtalk.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/OpenJtalk.java @@ -1,7 +1,7 @@ package jp.Hiroshiba.VoicevoxCore; -public class OpenJtalk { - protected long internalPtr; +public class OpenJtalk implements AutoCloseable { + protected long internal; public OpenJtalk() { rsNewWithoutDic(); @@ -11,9 +11,15 @@ public OpenJtalk(String openJtalkDictDir) { rsNewWithInitilize(openJtalkDictDir); } - private native boolean rsNewWithoutDic(); + public void close() { + rsDrop(); + } + + private native void rsNewWithoutDic(); + + private native void rsNewWithInitilize(String openJtalkDictDir); - private native boolean rsNewWithInitilize(String openJtalkDictDir); + private native void rsDrop(); static { System.loadLibrary("voicevox_core_java_api"); diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/VoiceModel.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/VoiceModel.java index dc7f597c9..cad55d7e8 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/VoiceModel.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/VoiceModel.java @@ -1,7 +1,8 @@ package jp.Hiroshiba.VoicevoxCore; -public class VoiceModel { - protected long internalPtr; +public class VoiceModel + implements AutoCloseable { + protected long internal; public String id; public SpeakerMeta[] metas; @@ -10,7 +11,13 @@ public VoiceModel(String modelPath) { rsFromPath(modelPath); } - private native boolean rsFromPath(String modelPath); + public void close() { + rsDrop(); + } + + private native void rsFromPath(String modelPath); + + private native void rsDrop(); static { System.loadLibrary("voicevox_core_java_api"); diff --git a/crates/voicevox_core_java_api/src/common.rs b/crates/voicevox_core_java_api/src/common.rs new file mode 100644 index 000000000..c33484e92 --- /dev/null +++ b/crates/voicevox_core_java_api/src/common.rs @@ -0,0 +1,90 @@ +use anyhow::Result; +use jni::JNIEnv; +use once_cell::sync::Lazy; +use tokio::runtime::Runtime; + +pub static RUNTIME: Lazy = Lazy::new(|| { + if cfg!(target_os = "android") { + android_logger::init_once( + android_logger::Config::default() + .with_tag("VoicevoxCore") + .with_filter( + android_logger::FilterBuilder::new() + .parse( + "error,voicevox_core=info,voicevox_core_java_api=info,onnxruntime=info", + ) + .build(), + ), + ); + } else { + // TODO: Android以外でのログ出力を良い感じにする。(System.Loggerを使う?) + use chrono::SecondsFormat; + use std::{ + env, fmt, + io::{self, IsTerminal, Write}, + }; + use tracing_subscriber::{fmt::format::Writer, EnvFilter}; + + let _ = tracing_subscriber::fmt() + .with_env_filter(if env::var_os(EnvFilter::DEFAULT_ENV).is_some() { + EnvFilter::from_default_env() + } else { + "error,voicevox_core=info,voicevox_core_c_api=info,onnxruntime=info".into() + }) + .with_timer(local_time as fn(&mut Writer<'_>) -> _) + .with_ansi(out().is_terminal() && env_allows_ansi()) + .with_writer(out) + .try_init(); + + fn local_time(wtr: &mut Writer<'_>) -> fmt::Result { + // ローカル時刻で表示はするが、そのフォーマットはtracing-subscriber本来のものに近いようにする。 + // https://github.com/tokio-rs/tracing/blob/tracing-subscriber-0.3.16/tracing-subscriber/src/fmt/time/datetime.rs#L235-L241 + wtr.write_str(&chrono::Local::now().to_rfc3339_opts(SecondsFormat::Micros, false)) + } + + fn out() -> impl IsTerminal + Write { + io::stderr() + } + + fn env_allows_ansi() -> bool { + // https://docs.rs/termcolor/1.2.0/src/termcolor/lib.rs.html#245-291 + // ただしWindowsではPowerShellっぽかったらそのまま許可する。 + // ちゃんとやるなら`ENABLE_VIRTUAL_TERMINAL_PROCESSING`をチェックするなり、そもそも + // fwdansiとかでWin32の色に変換するべきだが、面倒。 + env::var_os("TERM").map_or( + cfg!(windows) && env::var_os("PSModulePath").is_some(), + |term| term != "dumb", + ) && env::var_os("NO_COLOR").is_none() + } + } + Runtime::new().unwrap() +}); + +#[macro_export] +macro_rules! object { + ($name: literal) => { + concat!("Ljp/Hiroshiba/VoicevoxCore/", $name, ";") + }; +} + +pub fn throw_if_err(mut env: JNIEnv, fallback: T, inner: F) -> T +where + F: FnOnce(&mut JNIEnv) -> Result, +{ + match inner(&mut env) { + Ok(value) => value as _, + Err(error) => { + // Java側の例外は無視する。 + // env.exception_clear()してもいいが、errorのメッセージは"Java exception was thrown" + // となり、デバッグが困難になるため、そのままにしておく。 + if !env.exception_check().unwrap_or(false) { + env.throw_new( + "jp/Hiroshiba/VoicevoxCore/VoicevoxException", + error.to_string(), + ) + .unwrap_or_else(|_| panic!("Failed to throw exception, original error: {}", error)); + } + fallback + } + } +} diff --git a/crates/voicevox_core_java_api/src/lib.rs b/crates/voicevox_core_java_api/src/lib.rs index 17eea8015..79f36841b 100644 --- a/crates/voicevox_core_java_api/src/lib.rs +++ b/crates/voicevox_core_java_api/src/lib.rs @@ -1,193 +1,6 @@ -mod utils; -use crate::utils::throw_if_err; -use jni::{ - objects::{JObject, JString, JValueGen}, - sys::{jboolean, jlong}, - JNIEnv, -}; -use once_cell::sync::Lazy; -use tokio::runtime::Runtime; +mod common; +mod open_jtalk; +mod voice_model; -static RUNTIME: Lazy = Lazy::new(|| { - if cfg!(target_os = "android") { - android_logger::init_once( - android_logger::Config::default() - .with_tag("VoicevoxCore") - .with_filter( - android_logger::FilterBuilder::new() - .parse( - "error,voicevox_core=info,voicevox_core_java_api=info,onnxruntime=info", - ) - .build(), - ), - ); - } else { - // TODO: Android以外でのログ出力を良い感じにする。(System.Loggerを使う?) - use chrono::SecondsFormat; - use std::{ - env, fmt, - io::{self, IsTerminal, Write}, - }; - use tracing_subscriber::{fmt::format::Writer, EnvFilter}; - - let _ = tracing_subscriber::fmt() - .with_env_filter(if env::var_os(EnvFilter::DEFAULT_ENV).is_some() { - EnvFilter::from_default_env() - } else { - "error,voicevox_core=info,voicevox_core_c_api=info,onnxruntime=info".into() - }) - .with_timer(local_time as fn(&mut Writer<'_>) -> _) - .with_ansi(out().is_terminal() && env_allows_ansi()) - .with_writer(out) - .try_init(); - - fn local_time(wtr: &mut Writer<'_>) -> fmt::Result { - // ローカル時刻で表示はするが、そのフォーマットはtracing-subscriber本来のものに近いようにする。 - // https://github.com/tokio-rs/tracing/blob/tracing-subscriber-0.3.16/tracing-subscriber/src/fmt/time/datetime.rs#L235-L241 - wtr.write_str(&chrono::Local::now().to_rfc3339_opts(SecondsFormat::Micros, false)) - } - - fn out() -> impl IsTerminal + Write { - io::stderr() - } - - fn env_allows_ansi() -> bool { - // https://docs.rs/termcolor/1.2.0/src/termcolor/lib.rs.html#245-291 - // ただしWindowsではPowerShellっぽかったらそのまま許可する。 - // ちゃんとやるなら`ENABLE_VIRTUAL_TERMINAL_PROCESSING`をチェックするなり、そもそも - // fwdansiとかでWin32の色に変換するべきだが、面倒。 - env::var_os("TERM").map_or( - cfg!(windows) && env::var_os("PSModulePath").is_some(), - |term| term != "dumb", - ) && env::var_os("NO_COLOR").is_none() - } - } - Runtime::new().unwrap() -}); - -#[no_mangle] -pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_OpenJtalk_rsNewWithoutDic<'local>( - env: JNIEnv<'local>, - this: JObject<'local>, -) -> jboolean { - throw_if_err(env, false, |env| { - let internal = voicevox_core::OpenJtalk::new_without_dic(); - let internal_ptr = Box::into_raw(Box::new(internal)); - - env.set_field( - this, - "internalPtr", - "J", - JValueGen::Long(internal_ptr as jlong), - )?; - Ok(true) - }) as jboolean -} - -#[no_mangle] -pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_OpenJtalk_rsNewWithInitialize<'local>( - env: JNIEnv<'local>, - this: JObject<'local>, - open_jtalk_dict_dir: JString<'local>, -) -> jboolean { - throw_if_err(env, false, |env| { - let open_jtalk_dict_dir = env.get_string(&open_jtalk_dict_dir)?; - let open_jtalk_dict_dir = open_jtalk_dict_dir.to_str()?; - - let internal = voicevox_core::OpenJtalk::new_with_initialize(open_jtalk_dict_dir)?; - let internal_ptr = Box::into_raw(Box::new(internal)); - - env.set_field( - this, - "internalPtr", - "J", - JValueGen::Long(internal_ptr as jlong), - )?; - Ok(true) - }) as jboolean -} - -#[no_mangle] -pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_VoiceModel_rsFromPath<'local>( - env: JNIEnv<'local>, - this: JObject<'local>, - model_path: JString<'local>, -) -> jboolean { - throw_if_err(env, false, |env| { - let model_path = env.get_string(&model_path)?; - let model_path = model_path.to_str()?; - - let internal = RUNTIME.block_on(voicevox_core::VoiceModel::from_path(model_path))?; - let internal_ptr = Box::into_raw(Box::new(&internal)); - - env.set_field( - &this, - "internalPtr", - "J", - JValueGen::Long(internal_ptr as jlong), - )?; - - env.set_field( - &this, - "id", - "Ljava/lang/String;", - JValueGen::Object(&env.new_string(internal.id().raw_voice_model_id())?.into()), - )?; - let speakers = env.new_object_array( - internal.metas().len() as i32, - object!("SpeakerMeta"), - JObject::null(), - )?; - for (i, meta) in internal.metas().iter().enumerate() { - let j_meta = env.new_object(object!("SpeakerMeta"), "()V", &[])?; - env.set_field( - &j_meta, - "name", - "Ljava/lang/String;", - JValueGen::Object(&env.new_string(meta.name())?.into()), - )?; - let j_styles = env.new_object_array( - meta.styles().len() as i32, - object!("StyleMeta"), - JObject::null(), - )?; - for (j, style) in meta.styles().iter().enumerate() { - let j_style = env.new_object(object!("StyleMeta"), "()V", &[])?; - env.set_field( - &j_style, - "name", - "Ljava/lang/String;", - JValueGen::Object(&env.new_string(style.name())?.into()), - )?; - env.set_field( - &j_style, - "id", - "I", - JValueGen::Int(style.id().raw_id() as i32), - )?; - env.set_object_array_element(&j_styles, j as i32, j_style)?; - } - env.set_field( - &j_meta, - "styles", - concat!("[", object!("StyleMeta")), - JValueGen::Object(&j_styles), - )?; - env.set_field( - &j_meta, - "speakerUuid", - "Ljava/lang/String;", - JValueGen::Object(&env.new_string(meta.speaker_uuid())?.into()), - )?; - env.set_field( - &j_meta, - "version", - "Ljava/lang/String;", - JValueGen::Object(&env.new_string(meta.version().raw_version())?.into()), - )?; - - env.set_object_array_element(&speakers, i as i32, j_meta)?; - } - Ok(true) - }) as jboolean -} +pub use crate::open_jtalk::*; +pub use crate::voice_model::*; diff --git a/crates/voicevox_core_java_api/src/open_jtalk.rs b/crates/voicevox_core_java_api/src/open_jtalk.rs new file mode 100644 index 000000000..5b3012cb4 --- /dev/null +++ b/crates/voicevox_core_java_api/src/open_jtalk.rs @@ -0,0 +1,48 @@ +use crate::common::throw_if_err; +use jni::{ + objects::{JObject, JString}, + JNIEnv, +}; +#[no_mangle] +pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_OpenJtalk_rsNewWithoutDic<'local>( + env: JNIEnv<'local>, + this: JObject<'local>, +) { + throw_if_err(env, (), |env| { + let internal = voicevox_core::OpenJtalk::new_without_dic(); + + unsafe { env.set_rust_field(&this, "internal", internal) }?; + Ok(()) + }) +} + +#[no_mangle] +pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_OpenJtalk_rsNewWithInitialize<'local>( + env: JNIEnv<'local>, + this: JObject<'local>, + open_jtalk_dict_dir: JString<'local>, +) { + throw_if_err(env, (), |env| { + let open_jtalk_dict_dir = env.get_string(&open_jtalk_dict_dir)?; + let open_jtalk_dict_dir = open_jtalk_dict_dir.to_str()?; + + let internal = voicevox_core::OpenJtalk::new_with_initialize(open_jtalk_dict_dir)?; + unsafe { env.set_rust_field(&this, "internal", internal) }?; + + Ok(()) + }) +} + +#[no_mangle] +pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_OpenJtalk_rsDrop<'local>( + env: JNIEnv<'local>, + this: JObject<'local>, +) { + throw_if_err(env, (), |env| { + let internal = + unsafe { env.get_rust_field::<_, _, voicevox_core::OpenJtalk>(&this, "internal") }?; + drop(internal); + unsafe { env.take_rust_field(&this, "internal") }?; + Ok(()) + }) +} diff --git a/crates/voicevox_core_java_api/src/utils.rs b/crates/voicevox_core_java_api/src/utils.rs deleted file mode 100644 index 1cb88a185..000000000 --- a/crates/voicevox_core_java_api/src/utils.rs +++ /dev/null @@ -1,31 +0,0 @@ -use anyhow::Result; -use jni::JNIEnv; - -#[macro_export] -macro_rules! object { - ($name: literal) => { - concat!("Ljp/Hiroshiba/VoicevoxCore/", $name, ";") - }; -} - -pub fn throw_if_err(mut env: JNIEnv, fallback: T, inner: F) -> T -where - F: FnOnce(&mut JNIEnv) -> Result, -{ - match inner(&mut env) { - Ok(value) => value as _, - Err(error) => { - // Java側の例外は無視する。 - // env.exception_clear()してもいいが、errorのメッセージは"Java exception was thrown" - // となり、デバッグが困難になるため、そのままにしておく。 - if !env.exception_check().unwrap_or(false) { - env.throw_new( - "jp/Hiroshiba/VoicevoxCore/VoicevoxException", - error.to_string(), - ) - .unwrap_or_else(|_| panic!("Failed to throw exception, original error: {}", error)); - } - fallback - } - } -} diff --git a/crates/voicevox_core_java_api/src/voice_model.rs b/crates/voicevox_core_java_api/src/voice_model.rs new file mode 100644 index 000000000..48ed8e3f7 --- /dev/null +++ b/crates/voicevox_core_java_api/src/voice_model.rs @@ -0,0 +1,101 @@ +use crate::{ + common::{throw_if_err, RUNTIME}, + object, +}; +use jni::{ + objects::{JObject, JString, JValueGen}, + JNIEnv, +}; + +#[no_mangle] +pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_VoiceModel_rsFromPath<'local>( + env: JNIEnv<'local>, + this: JObject<'local>, + model_path: JString<'local>, +) { + throw_if_err(env, (), |env| { + let model_path = env.get_string(&model_path)?; + let model_path = model_path.to_str()?; + + let internal = RUNTIME.block_on(voicevox_core::VoiceModel::from_path(model_path))?; + + env.set_field( + &this, + "id", + "Ljava/lang/String;", + JValueGen::Object(&env.new_string(internal.id().raw_voice_model_id())?.into()), + )?; + let speakers = env.new_object_array( + internal.metas().len() as i32, + object!("SpeakerMeta"), + JObject::null(), + )?; + for (i, meta) in internal.metas().iter().enumerate() { + let j_meta = env.new_object(object!("SpeakerMeta"), "()V", &[])?; + env.set_field( + &j_meta, + "name", + "Ljava/lang/String;", + JValueGen::Object(&env.new_string(meta.name())?.into()), + )?; + let j_styles = env.new_object_array( + meta.styles().len() as i32, + object!("StyleMeta"), + JObject::null(), + )?; + for (j, style) in meta.styles().iter().enumerate() { + let j_style = env.new_object(object!("StyleMeta"), "()V", &[])?; + env.set_field( + &j_style, + "name", + "Ljava/lang/String;", + JValueGen::Object(&env.new_string(style.name())?.into()), + )?; + env.set_field( + &j_style, + "id", + "I", + JValueGen::Int(style.id().raw_id() as i32), + )?; + env.set_object_array_element(&j_styles, j as i32, j_style)?; + } + env.set_field( + &j_meta, + "styles", + concat!("[", object!("StyleMeta")), + JValueGen::Object(&j_styles), + )?; + env.set_field( + &j_meta, + "speakerUuid", + "Ljava/lang/String;", + JValueGen::Object(&env.new_string(meta.speaker_uuid())?.into()), + )?; + env.set_field( + &j_meta, + "version", + "Ljava/lang/String;", + JValueGen::Object(&env.new_string(meta.version().raw_version())?.into()), + )?; + + env.set_object_array_element(&speakers, i as i32, j_meta)?; + } + unsafe { env.set_rust_field(&this, "internal", internal) }?; + + Ok(()) + }) +} + +#[no_mangle] +pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_VoiceModel_rsDrop<'local>( + env: JNIEnv<'local>, + this: JObject<'local>, +) { + throw_if_err(env, (), |env| { + let internal = + unsafe { env.get_rust_field::<_, _, voicevox_core::VoiceModel>(&this, "internal") }?; + drop(internal); + unsafe { env.take_rust_field(&this, "internal") }?; + Ok(()) + }) +} From 50dc06d3b92d12e7d1a0a680318226a3e21e091c Mon Sep 17 00:00:00 2001 From: sevenc-nanashi Date: Tue, 1 Aug 2023 20:30:50 +0900 Subject: [PATCH 07/99] =?UTF-8?q?Refactor:=20=E3=83=95=E3=82=A1=E3=82=A4?= =?UTF-8?q?=E3=83=AB=E7=B5=B1=E5=90=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../jp/Hiroshiba/VoicevoxCore/OpenJtalk.java | 4 +- .../Hiroshiba/VoicevoxCore/SpeakerMeta.java | 8 -- .../jp/Hiroshiba/VoicevoxCore/StyleMeta.java | 6 -- .../Hiroshiba/VoicevoxCore/Synthesizer.java | 72 ++++++++++++++ .../jp/Hiroshiba/VoicevoxCore/VoiceModel.java | 12 +++ .../jp/Hiroshiba/VoicevoxCore/MetaTest.java | 6 +- .../jp/Hiroshiba/VoicevoxCore/TtsTest.java | 37 +++++++ crates/voicevox_core_java_api/src/common.rs | 19 ++++ crates/voicevox_core_java_api/src/lib.rs | 2 + .../voicevox_core_java_api/src/open_jtalk.rs | 8 +- .../voicevox_core_java_api/src/synthesizer.rs | 98 +++++++++++++++++++ .../voicevox_core_java_api/src/voice_model.rs | 16 +-- 12 files changed, 259 insertions(+), 29 deletions(-) delete mode 100644 crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/SpeakerMeta.java delete mode 100644 crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/StyleMeta.java create mode 100644 crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Synthesizer.java create mode 100644 crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/TtsTest.java create mode 100644 crates/voicevox_core_java_api/src/synthesizer.rs diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/OpenJtalk.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/OpenJtalk.java index a0b114914..dd53be804 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/OpenJtalk.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/OpenJtalk.java @@ -8,7 +8,7 @@ public OpenJtalk() { } public OpenJtalk(String openJtalkDictDir) { - rsNewWithInitilize(openJtalkDictDir); + rsNewWithInitialize(openJtalkDictDir); } public void close() { @@ -17,7 +17,7 @@ public void close() { private native void rsNewWithoutDic(); - private native void rsNewWithInitilize(String openJtalkDictDir); + private native void rsNewWithInitialize(String openJtalkDictDir); private native void rsDrop(); diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/SpeakerMeta.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/SpeakerMeta.java deleted file mode 100644 index f6e5348c8..000000000 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/SpeakerMeta.java +++ /dev/null @@ -1,8 +0,0 @@ -package jp.Hiroshiba.VoicevoxCore; - -public class SpeakerMeta { - String name; - StyleMeta[] styles; - String speakerUuid; - String version; -} diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/StyleMeta.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/StyleMeta.java deleted file mode 100644 index e4d56af52..000000000 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/StyleMeta.java +++ /dev/null @@ -1,6 +0,0 @@ -package jp.Hiroshiba.VoicevoxCore; - -public class StyleMeta { - String name; - int id; -} diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Synthesizer.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Synthesizer.java new file mode 100644 index 000000000..dc83d5bb2 --- /dev/null +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Synthesizer.java @@ -0,0 +1,72 @@ +package jp.Hiroshiba.VoicevoxCore; + +public class Synthesizer implements AutoCloseable { + protected long internal; + + private Synthesizer(OpenJtalk openJtalk, SynthesizerBuilder builder) { + rsNewWithInitialize(openJtalk, builder); + } + + public void loadVoiceModel(VoiceModel voiceModel) { + rsLoadVoiceModel(voiceModel); + } + + public void close() { + rsDrop(); + } + + private native void rsNewWithInitialize(OpenJtalk openJtalk, SynthesizerBuilder builder); + + private native void rsLoadVoiceModel(VoiceModel voiceModel); + + private native void rsDrop(); + + static { + System.loadLibrary("voicevox_core_java_api"); + } + + public static SynthesizerBuilder builder(OpenJtalk openJtalk) { + return new SynthesizerBuilder(openJtalk); + } + + public static class SynthesizerBuilder { + private OpenJtalk openJtalk; + @SuppressWarnings("unused") + private AccelerationMode accelerationMode; + @SuppressWarnings("unused") + private int cpuNumThreads; + @SuppressWarnings("unused") + private boolean loadAllModels; + + public SynthesizerBuilder(OpenJtalk openJtalk) { + this.openJtalk = openJtalk; + } + + public SynthesizerBuilder accelerationMode(AccelerationMode accelerationMode) { + this.accelerationMode = accelerationMode; + return this; + } + + public SynthesizerBuilder cpuNumThreads(int cpuNumThreads) { + this.cpuNumThreads = cpuNumThreads; + return this; + } + + public SynthesizerBuilder loadAllModels(boolean loadAllModels) { + this.loadAllModels = loadAllModels; + return this; + } + + public Synthesizer build() { + Synthesizer synthesizer = new Synthesizer(openJtalk, this); + return synthesizer; + } + } + + public static enum AccelerationMode { + AUTO, + CPU, + GPU, + } + +} diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/VoiceModel.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/VoiceModel.java index cad55d7e8..e14905acd 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/VoiceModel.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/VoiceModel.java @@ -22,4 +22,16 @@ public void close() { static { System.loadLibrary("voicevox_core_java_api"); } + + public static class SpeakerMeta { + String name; + StyleMeta[] styles; + String speakerUuid; + String version; + } + + public static class StyleMeta { + String name; + int id; + } } diff --git a/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/MetaTest.java b/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/MetaTest.java index 065063cb7..2f7e9dfb0 100644 --- a/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/MetaTest.java +++ b/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/MetaTest.java @@ -4,7 +4,6 @@ package jp.Hiroshiba.VoicevoxCore; import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.*; import java.io.File; @@ -15,8 +14,9 @@ void checkMeta() { String cwd = System.getProperty("user.dir"); File path = new File( cwd + "/../../../model/sample.vvm"); - VoiceModel model = new VoiceModel(path.getAbsolutePath()); + try (VoiceModel model = new VoiceModel(path.getAbsolutePath())) { + System.out.println(model); + } - System.out.println(model); } } diff --git a/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/TtsTest.java b/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/TtsTest.java new file mode 100644 index 000000000..ea5d8171a --- /dev/null +++ b/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/TtsTest.java @@ -0,0 +1,37 @@ +/* + * 音声合成のテスト。 + * ttsaudioQuery -> synthesisの順に実行する。 + */ +package jp.Hiroshiba.VoicevoxCore; + +import org.junit.jupiter.api.Test; + +import java.io.File; + +class TtsTest { + VoiceModel model() { + // cwdはvoicevox_core/crates/voicevox_core_java_api/lib + String cwd = System.getProperty("user.dir"); + File path = new File( + cwd + "/../../../model/sample.vvm"); + + return new VoiceModel(path.getAbsolutePath()); + + } + + OpenJtalk openJtalk() { + String cwd = System.getProperty("user.dir"); + File path = new File( + cwd + "/../../test_util/data/open_jtalk_dic_utf_8-1.11"); + return new OpenJtalk(path.getAbsolutePath()); + } + + @Test + void checkTts() { + try (VoiceModel model = model(); + OpenJtalk openJtalk = new OpenJtalk(); + Synthesizer synthesizer = Synthesizer.builder(openJtalk).build()) { + synthesizer.loadVoiceModel(model); + } + } +} diff --git a/crates/voicevox_core_java_api/src/common.rs b/crates/voicevox_core_java_api/src/common.rs index c33484e92..6e736a327 100644 --- a/crates/voicevox_core_java_api/src/common.rs +++ b/crates/voicevox_core_java_api/src/common.rs @@ -62,10 +62,29 @@ pub static RUNTIME: Lazy = Lazy::new(|| { #[macro_export] macro_rules! object { + ($name: literal) => { + concat!("jp/Hiroshiba/VoicevoxCore/", $name) + }; +} +#[macro_export] +macro_rules! object_type { ($name: literal) => { concat!("Ljp/Hiroshiba/VoicevoxCore/", $name, ";") }; } +#[macro_export] +macro_rules! enum_object { + ($env: ident, $name: literal, $variant: literal) => { + $env.get_static_field(object!($name), $variant, object_type!($name)) + .unwrap_or_else(|_| { + panic!( + "Failed to get field {}", + concat!($variant, "L", object!($name), ";") + ) + }) + .l() + }; +} pub fn throw_if_err(mut env: JNIEnv, fallback: T, inner: F) -> T where diff --git a/crates/voicevox_core_java_api/src/lib.rs b/crates/voicevox_core_java_api/src/lib.rs index 79f36841b..db6d09968 100644 --- a/crates/voicevox_core_java_api/src/lib.rs +++ b/crates/voicevox_core_java_api/src/lib.rs @@ -1,6 +1,8 @@ mod common; mod open_jtalk; +mod synthesizer; mod voice_model; pub use crate::open_jtalk::*; +pub use crate::synthesizer::*; pub use crate::voice_model::*; diff --git a/crates/voicevox_core_java_api/src/open_jtalk.rs b/crates/voicevox_core_java_api/src/open_jtalk.rs index 5b3012cb4..05e8a8ed5 100644 --- a/crates/voicevox_core_java_api/src/open_jtalk.rs +++ b/crates/voicevox_core_java_api/src/open_jtalk.rs @@ -1,3 +1,5 @@ +use std::sync::Arc; + use crate::common::throw_if_err; use jni::{ objects::{JObject, JString}, @@ -11,7 +13,7 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_OpenJtalk_rsNewWithoutDic< throw_if_err(env, (), |env| { let internal = voicevox_core::OpenJtalk::new_without_dic(); - unsafe { env.set_rust_field(&this, "internal", internal) }?; + unsafe { env.set_rust_field(&this, "internal", Arc::new(internal)) }?; Ok(()) }) } @@ -27,7 +29,7 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_OpenJtalk_rsNewWithInitial let open_jtalk_dict_dir = open_jtalk_dict_dir.to_str()?; let internal = voicevox_core::OpenJtalk::new_with_initialize(open_jtalk_dict_dir)?; - unsafe { env.set_rust_field(&this, "internal", internal) }?; + unsafe { env.set_rust_field(&this, "internal", Arc::new(internal)) }?; Ok(()) }) @@ -40,7 +42,7 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_OpenJtalk_rsDrop<'local>( ) { throw_if_err(env, (), |env| { let internal = - unsafe { env.get_rust_field::<_, _, voicevox_core::OpenJtalk>(&this, "internal") }?; + unsafe { env.get_rust_field::<_, _, Arc>(&this, "internal") }?; drop(internal); unsafe { env.take_rust_field(&this, "internal") }?; Ok(()) diff --git a/crates/voicevox_core_java_api/src/synthesizer.rs b/crates/voicevox_core_java_api/src/synthesizer.rs new file mode 100644 index 000000000..52dd24800 --- /dev/null +++ b/crates/voicevox_core_java_api/src/synthesizer.rs @@ -0,0 +1,98 @@ +use crate::{ + common::{throw_if_err, RUNTIME}, + enum_object, object, object_type, +}; + +use anyhow::anyhow; +use jni::{objects::JObject, JNIEnv}; +use std::sync::{Arc, Mutex}; + +#[no_mangle] +pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsNewWithInitialize<'local>( + env: JNIEnv<'local>, + this: JObject<'local>, + open_jtalk: JObject<'local>, + builder: JObject<'local>, +) { + throw_if_err(env, (), |env| { + let mut options = voicevox_core::InitializeOptions::default(); + + let acceleration_mode = env + .get_field( + &builder, + "accelerationMode", + object_type!("Synthesizer$AccelerationMode"), + )? + .l()?; + + if !acceleration_mode.is_null() { + let auto = enum_object!(env, "Synthesizer$AccelerationMode", "AUTO")?; + let cpu = enum_object!(env, "Synthesizer$AccelerationMode", "CPU")?; + let gpu = enum_object!(env, "Synthesizer$AccelerationMode", "GPU")?; + options.acceleration_mode = if env.is_same_object(&acceleration_mode, auto)? { + voicevox_core::AccelerationMode::Auto + } else if env.is_same_object(&acceleration_mode, cpu)? { + voicevox_core::AccelerationMode::Cpu + } else if env.is_same_object(&acceleration_mode, gpu)? { + voicevox_core::AccelerationMode::Gpu + } else { + return Err(anyhow!("invalid acceleration mode".to_string(),)); + }; + } + let cpu_num_threads = env.get_field(&builder, "cpuNumThreads", "I")?; + if let Ok(cpu_num_threads) = cpu_num_threads.i() { + options.cpu_num_threads = cpu_num_threads as u16; + } + + let load_all_models = env.get_field(&builder, "loadAllModels", "Z")?; + if let Ok(load_all_models) = load_all_models.z() { + options.load_all_models = load_all_models; + } + + let open_jtalk = unsafe { + env.get_rust_field::<_, _, Arc>(&open_jtalk, "internal")? + .clone() + }; + let internal = voicevox_core::Synthesizer::new_with_initialize( + open_jtalk.clone(), + Box::leak(Box::new(options)), + ); + unsafe { env.set_rust_field(&this, "internal", Mutex::new(internal))? }; + Ok(()) + }) +} + +#[no_mangle] +pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsLoadVoiceModel<'local>( + env: JNIEnv<'local>, + this: JObject<'local>, + model: JObject<'local>, +) { + throw_if_err(env, (), |env| { + let model = unsafe { + env.get_rust_field::<_, _, Arc>(&model, "internal")? + .clone() + }; + let internal = unsafe { + env.get_rust_field::<_, _, Mutex>(&this, "internal")? + }; + let mut internal = internal.lock().unwrap(); + RUNTIME.block_on(internal.load_voice_model(&model))?; + Ok(()) + }) +} + +#[no_mangle] +pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsDrop<'local>( + env: JNIEnv<'local>, + this: JObject<'local>, +) { + throw_if_err(env, (), |env| { + let internal = unsafe { + env.get_rust_field::<_, _, Mutex>(&this, "internal") + }?; + drop(internal); + unsafe { env.take_rust_field(&this, "internal") }?; + Ok(()) + }) +} diff --git a/crates/voicevox_core_java_api/src/voice_model.rs b/crates/voicevox_core_java_api/src/voice_model.rs index 48ed8e3f7..e70b80bf8 100644 --- a/crates/voicevox_core_java_api/src/voice_model.rs +++ b/crates/voicevox_core_java_api/src/voice_model.rs @@ -1,6 +1,8 @@ +use std::sync::Arc; + use crate::{ common::{throw_if_err, RUNTIME}, - object, + object_type, }; use jni::{ objects::{JObject, JString, JValueGen}, @@ -27,11 +29,11 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_VoiceModel_rsFromPath<'loc )?; let speakers = env.new_object_array( internal.metas().len() as i32, - object!("SpeakerMeta"), + object_type!("VoiceModel$SpeakerMeta"), JObject::null(), )?; for (i, meta) in internal.metas().iter().enumerate() { - let j_meta = env.new_object(object!("SpeakerMeta"), "()V", &[])?; + let j_meta = env.new_object(object_type!("VoiceModel$SpeakerMeta"), "()V", &[])?; env.set_field( &j_meta, "name", @@ -40,11 +42,11 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_VoiceModel_rsFromPath<'loc )?; let j_styles = env.new_object_array( meta.styles().len() as i32, - object!("StyleMeta"), + object_type!("VoiceModel$StyleMeta"), JObject::null(), )?; for (j, style) in meta.styles().iter().enumerate() { - let j_style = env.new_object(object!("StyleMeta"), "()V", &[])?; + let j_style = env.new_object(object_type!("VoiceModel$StyleMeta"), "()V", &[])?; env.set_field( &j_style, "name", @@ -62,7 +64,7 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_VoiceModel_rsFromPath<'loc env.set_field( &j_meta, "styles", - concat!("[", object!("StyleMeta")), + concat!("[", object_type!("VoiceModel$StyleMeta")), JValueGen::Object(&j_styles), )?; env.set_field( @@ -80,7 +82,7 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_VoiceModel_rsFromPath<'loc env.set_object_array_element(&speakers, i as i32, j_meta)?; } - unsafe { env.set_rust_field(&this, "internal", internal) }?; + unsafe { env.set_rust_field(&this, "internal", Arc::new(internal)) }?; Ok(()) }) From baf3ba329e0c9e6ca525a0d30abf117552bf76c7 Mon Sep 17 00:00:00 2001 From: sevenc-nanashi Date: Wed, 2 Aug 2023 10:22:22 +0900 Subject: [PATCH 08/99] =?UTF-8?q?Fix:=20SEGV=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crates/voicevox_core/src/status.rs | 2 +- crates/voicevox_core_java_api/src/synthesizer.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/voicevox_core/src/status.rs b/crates/voicevox_core/src/status.rs index 68f839a6b..4befbd7ca 100644 --- a/crates/voicevox_core/src/status.rs +++ b/crates/voicevox_core/src/status.rs @@ -76,7 +76,7 @@ impl Status { merged_metas: VoiceModelMeta::default(), light_session_options: SessionOptions::new(cpu_num_threads, false), heavy_session_options: SessionOptions::new(cpu_num_threads, use_gpu), - id_relations: BTreeMap::default(), + id_relations: BTreeMap::new(), } } diff --git a/crates/voicevox_core_java_api/src/synthesizer.rs b/crates/voicevox_core_java_api/src/synthesizer.rs index 52dd24800..41375cc9d 100644 --- a/crates/voicevox_core_java_api/src/synthesizer.rs +++ b/crates/voicevox_core_java_api/src/synthesizer.rs @@ -53,10 +53,10 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsNewWithIniti env.get_rust_field::<_, _, Arc>(&open_jtalk, "internal")? .clone() }; - let internal = voicevox_core::Synthesizer::new_with_initialize( + let internal = RUNTIME.block_on(voicevox_core::Synthesizer::new_with_initialize( open_jtalk.clone(), Box::leak(Box::new(options)), - ); + ))?; unsafe { env.set_rust_field(&this, "internal", Mutex::new(internal))? }; Ok(()) }) From 2ce8cd55ffe48c73bb885bece1c0dad52146e824 Mon Sep 17 00:00:00 2001 From: sevenc-nanashi Date: Wed, 2 Aug 2023 11:07:21 +0900 Subject: [PATCH 09/99] =?UTF-8?q?Change:=20Meta=E7=B3=BB=E3=82=92final?= =?UTF-8?q?=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Hiroshiba/VoicevoxCore/Synthesizer.java | 12 ++ .../jp/Hiroshiba/VoicevoxCore/VoiceModel.java | 34 ++++-- .../jp/Hiroshiba/VoicevoxCore/TtsTest.java | 37 ------ .../voicevox_core_java_api/src/synthesizer.rs | 57 ++++++++- .../voicevox_core_java_api/src/voice_model.rs | 112 ++++++++++-------- 5 files changed, 156 insertions(+), 96 deletions(-) delete mode 100644 crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/TtsTest.java diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Synthesizer.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Synthesizer.java index dc83d5bb2..ea880563b 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Synthesizer.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Synthesizer.java @@ -11,6 +11,14 @@ public void loadVoiceModel(VoiceModel voiceModel) { rsLoadVoiceModel(voiceModel); } + public void unloadVoiceModel(String voiceModelId) { + rsUnloadVoiceModel(voiceModelId); + } + + public boolean isLoadedVoiceModel(String voiceModelId) { + return rsIsLoadedVoiceModel(voiceModelId); + } + public void close() { rsDrop(); } @@ -19,6 +27,10 @@ public void close() { private native void rsLoadVoiceModel(VoiceModel voiceModel); + private native void rsUnloadVoiceModel(String voiceModelId); + + private native boolean rsIsLoadedVoiceModel(String voiceModelId); + private native void rsDrop(); static { diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/VoiceModel.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/VoiceModel.java index e14905acd..81aeb3678 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/VoiceModel.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/VoiceModel.java @@ -4,11 +4,13 @@ public class VoiceModel implements AutoCloseable { protected long internal; - public String id; - public SpeakerMeta[] metas; + final public String id; + final public SpeakerMeta[] metas; public VoiceModel(String modelPath) { rsFromPath(modelPath); + id = rsGetId(); + metas = rsGetMetas(); } public void close() { @@ -17,6 +19,10 @@ public void close() { private native void rsFromPath(String modelPath); + private native String rsGetId(); + + private native SpeakerMeta[] rsGetMetas(); + private native void rsDrop(); static { @@ -24,14 +30,26 @@ public void close() { } public static class SpeakerMeta { - String name; - StyleMeta[] styles; - String speakerUuid; - String version; + final String name; + final StyleMeta[] styles; + final String speakerUuid; + final String version; + + protected SpeakerMeta(String name, StyleMeta[] styles, String speakerUuid, String version) { + this.name = name; + this.styles = styles; + this.speakerUuid = speakerUuid; + this.version = version; + } } public static class StyleMeta { - String name; - int id; + final String name; + final int id; + + protected StyleMeta(String name, int id) { + this.name = name; + this.id = id; + } } } diff --git a/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/TtsTest.java b/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/TtsTest.java deleted file mode 100644 index ea5d8171a..000000000 --- a/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/TtsTest.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * 音声合成のテスト。 - * ttsaudioQuery -> synthesisの順に実行する。 - */ -package jp.Hiroshiba.VoicevoxCore; - -import org.junit.jupiter.api.Test; - -import java.io.File; - -class TtsTest { - VoiceModel model() { - // cwdはvoicevox_core/crates/voicevox_core_java_api/lib - String cwd = System.getProperty("user.dir"); - File path = new File( - cwd + "/../../../model/sample.vvm"); - - return new VoiceModel(path.getAbsolutePath()); - - } - - OpenJtalk openJtalk() { - String cwd = System.getProperty("user.dir"); - File path = new File( - cwd + "/../../test_util/data/open_jtalk_dic_utf_8-1.11"); - return new OpenJtalk(path.getAbsolutePath()); - } - - @Test - void checkTts() { - try (VoiceModel model = model(); - OpenJtalk openJtalk = new OpenJtalk(); - Synthesizer synthesizer = Synthesizer.builder(openJtalk).build()) { - synthesizer.loadVoiceModel(model); - } - } -} diff --git a/crates/voicevox_core_java_api/src/synthesizer.rs b/crates/voicevox_core_java_api/src/synthesizer.rs index 41375cc9d..8c712f7b5 100644 --- a/crates/voicevox_core_java_api/src/synthesizer.rs +++ b/crates/voicevox_core_java_api/src/synthesizer.rs @@ -4,7 +4,11 @@ use crate::{ }; use anyhow::anyhow; -use jni::{objects::JObject, JNIEnv}; +use jni::{ + objects::{JObject, JString}, + sys::jboolean, + JNIEnv, +}; use std::sync::{Arc, Mutex}; #[no_mangle] @@ -76,12 +80,59 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsLoadVoiceMod let internal = unsafe { env.get_rust_field::<_, _, Mutex>(&this, "internal")? }; - let mut internal = internal.lock().unwrap(); - RUNTIME.block_on(internal.load_voice_model(&model))?; + { + let mut internal = internal.lock().unwrap(); + RUNTIME.block_on(internal.load_voice_model(&model))?; + } Ok(()) }) } +#[no_mangle] +pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsUnloadVoiceModel<'local>( + env: JNIEnv<'local>, + this: JObject<'local>, + model_id: JString<'local>, +) { + throw_if_err(env, (), |env| { + let model_id: String = env.get_string(&model_id)?.into(); + + let internal = unsafe { + env.get_rust_field::<_, _, Mutex>(&this, "internal")? + }; + + { + let mut internal = internal.lock().unwrap(); + + internal.unload_voice_model(&voicevox_core::VoiceModelId::new(model_id))?; + } + + Ok(()) + }) +} + +#[no_mangle] +pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsIsLoadedVoiceModel<'local>( + env: JNIEnv<'local>, + this: JObject<'local>, + model_id: JString<'local>, +) -> jboolean { + throw_if_err(env, false, |env| { + let model_id: String = env.get_string(&model_id)?.into(); + + let internal = unsafe { + env.get_rust_field::<_, _, Mutex>(&this, "internal")? + }; + + let is_loaded = { + let internal = internal.lock().unwrap(); + internal.is_loaded_voice_model(&voicevox_core::VoiceModelId::new(model_id)) + }; + + Ok(is_loaded) + }) as jboolean +} + #[no_mangle] pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsDrop<'local>( env: JNIEnv<'local>, diff --git a/crates/voicevox_core_java_api/src/voice_model.rs b/crates/voicevox_core_java_api/src/voice_model.rs index e70b80bf8..590905045 100644 --- a/crates/voicevox_core_java_api/src/voice_model.rs +++ b/crates/voicevox_core_java_api/src/voice_model.rs @@ -6,6 +6,7 @@ use crate::{ }; use jni::{ objects::{JObject, JString, JValueGen}, + sys::jobject, JNIEnv, }; @@ -21,70 +22,85 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_VoiceModel_rsFromPath<'loc let internal = RUNTIME.block_on(voicevox_core::VoiceModel::from_path(model_path))?; - env.set_field( - &this, - "id", - "Ljava/lang/String;", - JValueGen::Object(&env.new_string(internal.id().raw_voice_model_id())?.into()), - )?; - let speakers = env.new_object_array( + unsafe { env.set_rust_field(&this, "internal", Arc::new(internal)) }?; + + Ok(()) + }) +} + +#[no_mangle] +pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_VoiceModel_rsGetId<'local>( + env: JNIEnv<'local>, + this: JObject<'local>, +) -> jobject { + throw_if_err(env, std::ptr::null_mut(), |env| { + let internal = unsafe { + env.get_rust_field::<_, _, Arc>(&this, "internal") + }? + .clone(); + + let id = internal.id().raw_voice_model_id(); + + let id = env.new_string(id)?; + + Ok(id.into_raw()) + }) +} + +#[no_mangle] +pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_VoiceModel_rsGetMetas<'local>( + env: JNIEnv<'local>, + this: JObject<'local>, +) -> jobject { + throw_if_err(env, std::ptr::null_mut(), |env| { + let internal = unsafe { + env.get_rust_field::<_, _, Arc>(&this, "internal") + }? + .clone(); + let j_speakers = env.new_object_array( internal.metas().len() as i32, object_type!("VoiceModel$SpeakerMeta"), JObject::null(), )?; for (i, meta) in internal.metas().iter().enumerate() { - let j_meta = env.new_object(object_type!("VoiceModel$SpeakerMeta"), "()V", &[])?; - env.set_field( - &j_meta, - "name", - "Ljava/lang/String;", - JValueGen::Object(&env.new_string(meta.name())?.into()), - )?; let j_styles = env.new_object_array( meta.styles().len() as i32, object_type!("VoiceModel$StyleMeta"), JObject::null(), )?; for (j, style) in meta.styles().iter().enumerate() { - let j_style = env.new_object(object_type!("VoiceModel$StyleMeta"), "()V", &[])?; - env.set_field( - &j_style, - "name", - "Ljava/lang/String;", - JValueGen::Object(&env.new_string(style.name())?.into()), - )?; - env.set_field( - &j_style, - "id", - "I", - JValueGen::Int(style.id().raw_id() as i32), + let j_style = env.new_object( + object_type!("VoiceModel$StyleMeta"), + concat!("(", "Ljava/lang/String;", "I", ")V"), + &[ + JValueGen::Object(&env.new_string(style.name())?.into()), + JValueGen::Int(style.id().raw_id() as i32), + ], )?; env.set_object_array_element(&j_styles, j as i32, j_style)?; } - env.set_field( - &j_meta, - "styles", - concat!("[", object_type!("VoiceModel$StyleMeta")), - JValueGen::Object(&j_styles), - )?; - env.set_field( - &j_meta, - "speakerUuid", - "Ljava/lang/String;", - JValueGen::Object(&env.new_string(meta.speaker_uuid())?.into()), - )?; - env.set_field( - &j_meta, - "version", - "Ljava/lang/String;", - JValueGen::Object(&env.new_string(meta.version().raw_version())?.into()), - )?; - env.set_object_array_element(&speakers, i as i32, j_meta)?; + let j_meta = env.new_object( + object_type!("VoiceModel$SpeakerMeta"), + concat!( + "(", + "Ljava/lang/String;", + "[", + object_type!("VoiceModel$StyleMeta"), + "Ljava/lang/String;", + "Ljava/lang/String;", + ")V" + ), + &[ + JValueGen::Object(&env.new_string(meta.name())?.into()), + JValueGen::Object(&j_styles.into()), + JValueGen::Object(&env.new_string(meta.speaker_uuid())?.into()), + JValueGen::Object(&env.new_string(meta.version().raw_version())?.into()), + ], + )?; + env.set_object_array_element(&j_speakers, i as i32, j_meta)?; } - unsafe { env.set_rust_field(&this, "internal", Arc::new(internal)) }?; - - Ok(()) + Ok(j_speakers.into_raw()) }) } From fd5479348c0afc1f8022ee2c64fc8278ac44c545 Mon Sep 17 00:00:00 2001 From: sevenc-nanashi Date: Wed, 2 Aug 2023 11:07:33 +0900 Subject: [PATCH 10/99] Change: TtsTest -> SynthesizerTest --- .../VoicevoxCore/SynthesizerTest.java | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/SynthesizerTest.java 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 new file mode 100644 index 000000000..9d32b2f1f --- /dev/null +++ b/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/SynthesizerTest.java @@ -0,0 +1,52 @@ +/* + * 音声合成のテスト。 + * ttsaudioQuery -> synthesisの順に実行する。 + */ +package jp.Hiroshiba.VoicevoxCore; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.io.File; + +class SynthesizerTest { + VoiceModel model() { + // cwdはvoicevox_core/crates/voicevox_core_java_api/lib + String cwd = System.getProperty("user.dir"); + File path = new File( + cwd + "/../../../model/sample.vvm"); + + return new VoiceModel(path.getAbsolutePath()); + + } + + OpenJtalk openJtalk() { + String cwd = System.getProperty("user.dir"); + File path = new File( + cwd + "/../../test_util/data/open_jtalk_dic_utf_8-1.11"); + return new OpenJtalk(path.getAbsolutePath()); + } + + @Test + void checkModel() { + try (VoiceModel model = model(); + OpenJtalk openJtalk = new OpenJtalk(); + Synthesizer synthesizer = Synthesizer.builder(openJtalk).build()) { + synthesizer.loadVoiceModel(model); + assertTrue(synthesizer.isLoadedVoiceModel(model.id)); + synthesizer.unloadVoiceModel(model.id); + assertFalse(synthesizer.isLoadedVoiceModel(model.id)); + } + } + + @Test + void checkTts() { + try (VoiceModel model = model(); + OpenJtalk openJtalk = new OpenJtalk(); + Synthesizer synthesizer = Synthesizer.builder(openJtalk).build()) { + synthesizer.loadVoiceModel(model); + } + } +} From c3c7971c92ecd5f31feafa132358f11f00b797af Mon Sep 17 00:00:00 2001 From: sevenc-nanashi Date: Wed, 2 Aug 2023 20:29:05 +0900 Subject: [PATCH 11/99] =?UTF-8?q?Add:=20AudioQuery=E7=B3=BB=E3=82=92?= =?UTF-8?q?=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cargo.lock | 1 + crates/voicevox_core_java_api/Cargo.toml | 2 +- .../voicevox_core_java_api/lib/build.gradle | 12 +++ .../Hiroshiba/VoicevoxCore/AccentPhrase.java | 42 ++++++++++ .../jp/Hiroshiba/VoicevoxCore/AudioQuery.java | 76 +++++++++++++++++++ .../java/jp/Hiroshiba/VoicevoxCore/Mora.java | 54 +++++++++++++ .../Hiroshiba/VoicevoxCore/Synthesizer.java | 28 +++++++ .../jp/Hiroshiba/VoicevoxCore/VoiceModel.java | 26 +++++++ .../VoicevoxCore/SynthesizerTest.java | 24 +++--- crates/voicevox_core_java_api/src/common.rs | 4 +- .../voicevox_core_java_api/src/synthesizer.rs | 56 ++++++++++++-- .../voicevox_core_java_api/src/voice_model.rs | 15 ++-- 12 files changed, 315 insertions(+), 25 deletions(-) create mode 100644 crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/AccentPhrase.java create mode 100644 crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/AudioQuery.java create mode 100644 crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Mora.java diff --git a/Cargo.lock b/Cargo.lock index da6dfb914..992d6773e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4156,6 +4156,7 @@ dependencies = [ "easy-ext", "jni", "once_cell", + "serde_json", "tokio", "tracing", "tracing-subscriber", diff --git a/crates/voicevox_core_java_api/Cargo.toml b/crates/voicevox_core_java_api/Cargo.toml index ceba708bc..358d5a399 100644 --- a/crates/voicevox_core_java_api/Cargo.toml +++ b/crates/voicevox_core_java_api/Cargo.toml @@ -14,8 +14,8 @@ chrono = "0.4.26" easy-ext.workspace = true jni = "0.21.1" once_cell.workspace = true +serde_json.workspace = true tokio.workspace = true tracing = { workspace = true, features = ["log"] } tracing-subscriber.workspace = true voicevox_core.workspace = true - diff --git a/crates/voicevox_core_java_api/lib/build.gradle b/crates/voicevox_core_java_api/lib/build.gradle index 8e6bde364..6891ef181 100644 --- a/crates/voicevox_core_java_api/lib/build.gradle +++ b/crates/voicevox_core_java_api/lib/build.gradle @@ -26,6 +26,18 @@ dependencies { // This dependency is used internally, and not exposed to consumers on their own compile classpath. implementation 'com.google.guava:guava:31.1-jre' + + // https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core + implementation group: 'com.fasterxml.jackson.core', name: 'jackson-core', version: '2.13.0' + + // https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind + implementation group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.13.0' + + // https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations + implementation group: 'com.fasterxml.jackson.core', name: 'jackson-annotations', version: '2.13.0' + + // https://mvnrepository.com/artifact/com.google.code.gson/gson + implementation group: 'com.google.code.gson', name: 'gson', version: '2.10.1' } // 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/AccentPhrase.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/AccentPhrase.java new file mode 100644 index 000000000..3f35d9f43 --- /dev/null +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/AccentPhrase.java @@ -0,0 +1,42 @@ +package jp.Hiroshiba.VoicevoxCore; + +import java.util.List; +import java.util.ArrayList; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.google.gson.annotations.Expose; +import com.google.gson.annotations.SerializedName; + +public class AccentPhrase { + @JsonProperty("moras") + @SerializedName("moras") + @Expose + @Nonnull + public List moras; + + @JsonProperty("accent") + @SerializedName("accent") + @Expose + public int accent; + + @JsonProperty("pause_mora") + @SerializedName("pause_mora") + @Expose + @Nullable + public Mora pauseMora; + + @JsonProperty("is_interrogative") + @SerializedName("is_interrogative") + @Expose + public boolean isInterrogative; + + public AccentPhrase() { + this.moras = new ArrayList<>(); + this.accent = 0; + this.pauseMora = null; + this.isInterrogative = false; + } +} diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/AudioQuery.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/AudioQuery.java new file mode 100644 index 000000000..fa8ecc7a8 --- /dev/null +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/AudioQuery.java @@ -0,0 +1,76 @@ +package jp.Hiroshiba.VoicevoxCore; + +import java.util.ArrayList; +import java.util.List; + +import javax.annotation.Nonnull; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.google.gson.annotations.Expose; +import com.google.gson.annotations.SerializedName; + +public class AudioQuery { + @JsonProperty("accent_phrases") + @SerializedName("accent_phrases") + @Expose + @Nonnull + public List accentPhrases; + + @JsonProperty("speed_scale") + @SerializedName("speed_scale") + @Expose + public double speedScale; + + @JsonProperty("pitch_scale") + @SerializedName("pitch_scale") + @Expose + public double pitchScale; + + @JsonProperty("intonation_scale") + @SerializedName("intonation_scale") + @Expose + public double intonationScale; + + @JsonProperty("volume_scale") + @SerializedName("volume_scale") + @Expose + public double volumeScale; + + @JsonProperty("pre_phoneme_length") + @SerializedName("pre_phoneme_length") + @Expose + public double prePhonemeLength; + + @JsonProperty("post_phoneme_length") + @SerializedName("post_phoneme_length") + @Expose + public double postPhonemeLength; + + @JsonProperty("output_sampling_rate") + @SerializedName("output_sampling_rate") + @Expose + public int outputSamplingRate; + + @JsonProperty("output_stereo") + @SerializedName("output_stereo") + @Expose + public boolean outputStereo; + + @JsonProperty("kana") + @SerializedName("kana") + @Expose + @Nonnull + public String kana; + + public AudioQuery() { + this.accentPhrases = new ArrayList<>(); + this.speedScale = 1.0; + this.pitchScale = 0.0; + this.intonationScale = 1.0; + this.volumeScale = 1.0; + this.prePhonemeLength = 0.1; + this.postPhonemeLength = 0.1; + this.outputSamplingRate = 24000; + this.kana = ""; + } +} diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Mora.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Mora.java new file mode 100644 index 000000000..52ba99c0a --- /dev/null +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Mora.java @@ -0,0 +1,54 @@ +package jp.Hiroshiba.VoicevoxCore; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.google.gson.annotations.Expose; +import com.google.gson.annotations.SerializedName; + +public class Mora { + @JsonProperty("text") + @SerializedName("text") + @Expose + @Nonnull + @SuppressWarnings("NullableProblems") + public String text; + + @JsonProperty("consonant") + @SerializedName("consonant") + @Expose + @Nullable + public String consonant; + + @JsonProperty("consonant_length") + @SerializedName("consonant_length") + @Expose + public java.lang.Double consonantLength; + + @JsonProperty("vowel") + @SerializedName("vowel") + @Expose + @Nonnull + @SuppressWarnings("NullableProblems") + public String vowel; + + @JsonProperty("vowel_length") + @SerializedName("vowel_length") + @Expose + public double vowelLength; + + @JsonProperty("pitch") + @SerializedName("pitch") + @Expose + public double pitch; + + public Mora() { + this.text = ""; + this.consonant = ""; + this.consonantLength = 0.0; + this.vowel = ""; + this.vowelLength = 0.0; + this.pitch = 0.0; + } +} diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Synthesizer.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Synthesizer.java index ea880563b..5827957e6 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Synthesizer.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Synthesizer.java @@ -1,5 +1,11 @@ package jp.Hiroshiba.VoicevoxCore; +import java.util.EnumSet; + +import javax.annotation.Nonnull; + +import com.google.gson.Gson; + public class Synthesizer implements AutoCloseable { protected long internal; @@ -19,6 +25,22 @@ public boolean isLoadedVoiceModel(String voiceModelId) { return rsIsLoadedVoiceModel(voiceModelId); } + @Nonnull + public AudioQuery audioQuery(String text, int styleId, EnumSet options) { + boolean kana = options.contains(AudioQueryOption.KANA); + String queryJson = rsAudioQuery(text, styleId, kana); + Gson gson = new Gson(); + + System.out.println(queryJson); + + AudioQuery audioQuery = gson.fromJson(queryJson, AudioQuery.class); + System.out.println(audioQuery); + if (audioQuery == null) { + throw new NullPointerException("audio_query"); + } + return audioQuery; + } + public void close() { rsDrop(); } @@ -31,6 +53,9 @@ public void close() { private native boolean rsIsLoadedVoiceModel(String voiceModelId); + @Nonnull + private native String rsAudioQuery(String text, int styleId, boolean kana); + private native void rsDrop(); static { @@ -81,4 +106,7 @@ public static enum AccelerationMode { GPU, } + public static enum AudioQueryOption { + KANA, + } } diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/VoiceModel.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/VoiceModel.java index 81aeb3678..672ec5722 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/VoiceModel.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/VoiceModel.java @@ -1,10 +1,14 @@ package jp.Hiroshiba.VoicevoxCore; +import javax.annotation.Nonnull; + public class VoiceModel implements AutoCloseable { protected long internal; + @Nonnull final public String id; + @Nonnull final public SpeakerMeta[] metas; public VoiceModel(String modelPath) { @@ -19,8 +23,10 @@ public void close() { private native void rsFromPath(String modelPath); + @Nonnull private native String rsGetId(); + @Nonnull private native SpeakerMeta[] rsGetMetas(); private native void rsDrop(); @@ -30,12 +36,28 @@ public void close() { } public static class SpeakerMeta { + @Nonnull final String name; + @Nonnull final StyleMeta[] styles; + @Nonnull final String speakerUuid; + @Nonnull final String version; protected SpeakerMeta(String name, StyleMeta[] styles, String speakerUuid, String version) { + if (name == null) { + throw new NullPointerException("name"); + } + if (styles == null) { + throw new NullPointerException("styles"); + } + if (speakerUuid == null) { + throw new NullPointerException("speakerUuid"); + } + if (version == null) { + throw new NullPointerException("version"); + } this.name = name; this.styles = styles; this.speakerUuid = speakerUuid; @@ -44,10 +66,14 @@ protected SpeakerMeta(String name, StyleMeta[] styles, String speakerUuid, Strin } public static class StyleMeta { + @Nonnull final String name; final int id; protected StyleMeta(String name, int id) { + if (name == null) { + throw new NullPointerException("name"); + } this.name = name; this.id = id; } 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 9d32b2f1f..6510e76ef 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 @@ -5,34 +5,37 @@ package jp.Hiroshiba.VoicevoxCore; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.Timeout; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; -import java.io.File; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.EnumSet; +@Timeout(10) class SynthesizerTest { VoiceModel model() { // cwdはvoicevox_core/crates/voicevox_core_java_api/lib String cwd = System.getProperty("user.dir"); - File path = new File( - cwd + "/../../../model/sample.vvm"); + Path path = Paths.get(cwd, "..", "..", "..", "model", "sample.vvm"); - return new VoiceModel(path.getAbsolutePath()); + return new VoiceModel(path.toString()); } OpenJtalk openJtalk() { String cwd = System.getProperty("user.dir"); - File path = new File( - cwd + "/../../test_util/data/open_jtalk_dic_utf_8-1.11"); - return new OpenJtalk(path.getAbsolutePath()); + Path path = Paths.get(cwd, "..", "..", "test_util", "data", "open_jtalk_dic_utf_8-1.11"); + + return new OpenJtalk(path.toString()); } @Test void checkModel() { try (VoiceModel model = model(); - OpenJtalk openJtalk = new OpenJtalk(); + OpenJtalk openJtalk = openJtalk(); Synthesizer synthesizer = Synthesizer.builder(openJtalk).build()) { synthesizer.loadVoiceModel(model); assertTrue(synthesizer.isLoadedVoiceModel(model.id)); @@ -42,11 +45,12 @@ void checkModel() { } @Test - void checkTts() { + void checkAudioQuery() { try (VoiceModel model = model(); - OpenJtalk openJtalk = new OpenJtalk(); + OpenJtalk openJtalk = openJtalk(); Synthesizer synthesizer = Synthesizer.builder(openJtalk).build()) { synthesizer.loadVoiceModel(model); + synthesizer.audioQuery("こんにちは", model.metas[0].styles[0].id, EnumSet.noneOf(Synthesizer.AudioQueryOption.class)); } } } diff --git a/crates/voicevox_core_java_api/src/common.rs b/crates/voicevox_core_java_api/src/common.rs index 6e736a327..ae67b5584 100644 --- a/crates/voicevox_core_java_api/src/common.rs +++ b/crates/voicevox_core_java_api/src/common.rs @@ -11,7 +11,7 @@ pub static RUNTIME: Lazy = Lazy::new(|| { .with_filter( android_logger::FilterBuilder::new() .parse( - "error,voicevox_core=info,voicevox_core_java_api=info,onnxruntime=info", + "error,voicevox_core=info,voicevox_core_java_api=info,onnxruntime=error", ) .build(), ), @@ -29,7 +29,7 @@ pub static RUNTIME: Lazy = Lazy::new(|| { .with_env_filter(if env::var_os(EnvFilter::DEFAULT_ENV).is_some() { EnvFilter::from_default_env() } else { - "error,voicevox_core=info,voicevox_core_c_api=info,onnxruntime=info".into() + "error,voicevox_core=info,voicevox_core_c_api=info,onnxruntime=error".into() }) .with_timer(local_time as fn(&mut Writer<'_>) -> _) .with_ansi(out().is_terminal() && env_allows_ansi()) diff --git a/crates/voicevox_core_java_api/src/synthesizer.rs b/crates/voicevox_core_java_api/src/synthesizer.rs index 8c712f7b5..9d3ee249b 100644 --- a/crates/voicevox_core_java_api/src/synthesizer.rs +++ b/crates/voicevox_core_java_api/src/synthesizer.rs @@ -6,7 +6,7 @@ use crate::{ use anyhow::anyhow; use jni::{ objects::{JObject, JString}, - sys::jboolean, + sys::{jboolean, jint, jobject}, JNIEnv, }; use std::sync::{Arc, Mutex}; @@ -61,7 +61,7 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsNewWithIniti open_jtalk.clone(), Box::leak(Box::new(options)), ))?; - unsafe { env.set_rust_field(&this, "internal", Mutex::new(internal))? }; + unsafe { env.set_rust_field(&this, "internal", Arc::new(Mutex::new(internal)))? }; Ok(()) }) } @@ -78,7 +78,8 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsLoadVoiceMod .clone() }; let internal = unsafe { - env.get_rust_field::<_, _, Mutex>(&this, "internal")? + env.get_rust_field::<_, _, Arc>>(&this, "internal")? + .clone() }; { let mut internal = internal.lock().unwrap(); @@ -98,7 +99,8 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsUnloadVoiceM let model_id: String = env.get_string(&model_id)?.into(); let internal = unsafe { - env.get_rust_field::<_, _, Mutex>(&this, "internal")? + env.get_rust_field::<_, _, Arc>>(&this, "internal")? + .clone() }; { @@ -121,7 +123,8 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsIsLoadedVoic let model_id: String = env.get_string(&model_id)?.into(); let internal = unsafe { - env.get_rust_field::<_, _, Mutex>(&this, "internal")? + env.get_rust_field::<_, _, Arc>>(&this, "internal")? + .clone() }; let is_loaded = { @@ -133,6 +136,44 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsIsLoadedVoic }) as jboolean } +#[no_mangle] +pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsAudioQuery<'local>( + env: JNIEnv<'local>, + this: JObject<'local>, + text: JString<'local>, + style_id: jint, + kana: jboolean, +) -> jobject { + throw_if_err(env, std::ptr::null_mut(), |env| { + let text: String = env.get_string(&text)?.into(); + let style_id = style_id as u32; + + let internal = unsafe { + env.get_rust_field::<_, _, Arc>>(&this, "internal")? + .clone() + }; + + let audio_query = { + let internal = internal.lock().unwrap(); + let options = voicevox_core::AudioQueryOptions { + kana: kana != 0, + // ..Default::default() + }; + RUNTIME.block_on(internal.audio_query( + &text, + voicevox_core::StyleId::new(style_id), + &options, + ))? + }; + + let query_json = serde_json::to_string(&audio_query)?; + + let j_audio_query = env.new_string(query_json)?; + + Ok(j_audio_query.into_raw()) + }) +} + #[no_mangle] pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsDrop<'local>( env: JNIEnv<'local>, @@ -140,8 +181,9 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsDrop<'local> ) { throw_if_err(env, (), |env| { let internal = unsafe { - env.get_rust_field::<_, _, Mutex>(&this, "internal") - }?; + env.get_rust_field::<_, _, Arc>>(&this, "internal")? + .clone() + }; drop(internal); unsafe { env.take_rust_field(&this, "internal") }?; Ok(()) diff --git a/crates/voicevox_core_java_api/src/voice_model.rs b/crates/voicevox_core_java_api/src/voice_model.rs index 590905045..099aab665 100644 --- a/crates/voicevox_core_java_api/src/voice_model.rs +++ b/crates/voicevox_core_java_api/src/voice_model.rs @@ -71,7 +71,12 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_VoiceModel_rsGetMetas<'loc for (j, style) in meta.styles().iter().enumerate() { let j_style = env.new_object( object_type!("VoiceModel$StyleMeta"), - concat!("(", "Ljava/lang/String;", "I", ")V"), + concat!( + "(", + "Ljava/lang/String;", // name + "I", // id + ")V" + ), &[ JValueGen::Object(&env.new_string(style.name())?.into()), JValueGen::Int(style.id().raw_id() as i32), @@ -84,11 +89,11 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_VoiceModel_rsGetMetas<'loc object_type!("VoiceModel$SpeakerMeta"), concat!( "(", - "Ljava/lang/String;", - "[", + "Ljava/lang/String;", // name + "[", // styles object_type!("VoiceModel$StyleMeta"), - "Ljava/lang/String;", - "Ljava/lang/String;", + "Ljava/lang/String;", // speakerUuid + "Ljava/lang/String;", // version ")V" ), &[ From 034b32655a488a605e042c655fcbfd050f24a96d Mon Sep 17 00:00:00 2001 From: sevenc-nanashi Date: Wed, 2 Aug 2023 20:47:36 +0900 Subject: [PATCH 12/99] =?UTF-8?q?Change:=20SpeakerMeta=E7=B3=BB=E3=82=92JS?= =?UTF-8?q?ON=E3=83=99=E3=83=BC=E3=82=B9=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../jp/Hiroshiba/VoicevoxCore/VoiceModel.java | 67 ++++++++++++------- crates/voicevox_core_java_api/src/common.rs | 10 ++- .../voicevox_core_java_api/src/open_jtalk.rs | 5 +- .../voicevox_core_java_api/src/voice_model.rs | 61 ++--------------- 4 files changed, 55 insertions(+), 88 deletions(-) diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/VoiceModel.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/VoiceModel.java index 672ec5722..4c6f28e21 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/VoiceModel.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/VoiceModel.java @@ -2,6 +2,11 @@ import javax.annotation.Nonnull; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.google.gson.Gson; +import com.google.gson.annotations.Expose; +import com.google.gson.annotations.SerializedName; + public class VoiceModel implements AutoCloseable { protected long internal; @@ -14,7 +19,14 @@ public class VoiceModel public VoiceModel(String modelPath) { rsFromPath(modelPath); id = rsGetId(); - metas = rsGetMetas(); + String metasJson = rsGetMetasJson(); + Gson gson = new Gson(); + SpeakerMeta[] rawMetas = gson.fromJson(metasJson, SpeakerMeta[].class); + if (rawMetas == null) { + throw new RuntimeException("Failed to parse metasJson"); + } + metas = rawMetas; + } public void close() { @@ -27,7 +39,7 @@ public void close() { private native String rsGetId(); @Nonnull - private native SpeakerMeta[] rsGetMetas(); + private native String rsGetMetasJson(); private native void rsDrop(); @@ -36,46 +48,51 @@ public void close() { } public static class SpeakerMeta { + @JsonProperty("name") + @SerializedName("name") + @Expose @Nonnull final String name; + @JsonProperty("styles") + @SerializedName("styles") + @Expose @Nonnull final StyleMeta[] styles; + @JsonProperty("speaker_uuid") + @SerializedName("speaker_uuid") + @Expose @Nonnull final String speakerUuid; + @JsonProperty("version") + @SerializedName("version") + @Expose @Nonnull final String version; - protected SpeakerMeta(String name, StyleMeta[] styles, String speakerUuid, String version) { - if (name == null) { - throw new NullPointerException("name"); - } - if (styles == null) { - throw new NullPointerException("styles"); - } - if (speakerUuid == null) { - throw new NullPointerException("speakerUuid"); - } - if (version == null) { - throw new NullPointerException("version"); - } - this.name = name; - this.styles = styles; - this.speakerUuid = speakerUuid; - this.version = version; + private SpeakerMeta() { + this.name = ""; + this.styles = new StyleMeta[0]; + this.speakerUuid = ""; + this.version = ""; } } public static class StyleMeta { + @JsonProperty("name") + @SerializedName("name") + @Expose @Nonnull final String name; + @JsonProperty("id") + @SerializedName("id") + @Expose final int id; - protected StyleMeta(String name, int id) { - if (name == null) { - throw new NullPointerException("name"); - } - this.name = name; - this.id = id; + private StyleMeta() { + // GSONからコンストラクトするため、このメソッドは呼ばれることは無い。 + // このメソッドは@Nonnullを満たすために必要。 + this.name = ""; + this.id = 0; } } } diff --git a/crates/voicevox_core_java_api/src/common.rs b/crates/voicevox_core_java_api/src/common.rs index ae67b5584..9515e1de6 100644 --- a/crates/voicevox_core_java_api/src/common.rs +++ b/crates/voicevox_core_java_api/src/common.rs @@ -9,12 +9,10 @@ pub static RUNTIME: Lazy = Lazy::new(|| { android_logger::Config::default() .with_tag("VoicevoxCore") .with_filter( - android_logger::FilterBuilder::new() - .parse( - "error,voicevox_core=info,voicevox_core_java_api=info,onnxruntime=error", - ) - .build(), - ), + android_logger::FilterBuilder::new() + .parse("error,voicevox_core=info,voicevox_core_java_api=info,onnxruntime=error") + .build(), + ), ); } else { // TODO: Android以外でのログ出力を良い感じにする。(System.Loggerを使う?) diff --git a/crates/voicevox_core_java_api/src/open_jtalk.rs b/crates/voicevox_core_java_api/src/open_jtalk.rs index 05e8a8ed5..6296a4cf4 100644 --- a/crates/voicevox_core_java_api/src/open_jtalk.rs +++ b/crates/voicevox_core_java_api/src/open_jtalk.rs @@ -41,8 +41,9 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_OpenJtalk_rsDrop<'local>( this: JObject<'local>, ) { throw_if_err(env, (), |env| { - let internal = - unsafe { env.get_rust_field::<_, _, Arc>(&this, "internal") }?; + let internal = unsafe { + env.get_rust_field::<_, _, Arc>(&this, "internal") + }?; drop(internal); unsafe { env.take_rust_field(&this, "internal") }?; Ok(()) diff --git a/crates/voicevox_core_java_api/src/voice_model.rs b/crates/voicevox_core_java_api/src/voice_model.rs index 099aab665..d569998ed 100644 --- a/crates/voicevox_core_java_api/src/voice_model.rs +++ b/crates/voicevox_core_java_api/src/voice_model.rs @@ -1,11 +1,8 @@ use std::sync::Arc; -use crate::{ - common::{throw_if_err, RUNTIME}, - object_type, -}; +use crate::common::{throw_if_err, RUNTIME}; use jni::{ - objects::{JObject, JString, JValueGen}, + objects::{JObject, JString}, sys::jobject, JNIEnv, }; @@ -48,7 +45,7 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_VoiceModel_rsGetId<'local> } #[no_mangle] -pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_VoiceModel_rsGetMetas<'local>( +pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_VoiceModel_rsGetMetasJson<'local>( env: JNIEnv<'local>, this: JObject<'local>, ) -> jobject { @@ -57,55 +54,9 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_VoiceModel_rsGetMetas<'loc env.get_rust_field::<_, _, Arc>(&this, "internal") }? .clone(); - let j_speakers = env.new_object_array( - internal.metas().len() as i32, - object_type!("VoiceModel$SpeakerMeta"), - JObject::null(), - )?; - for (i, meta) in internal.metas().iter().enumerate() { - let j_styles = env.new_object_array( - meta.styles().len() as i32, - object_type!("VoiceModel$StyleMeta"), - JObject::null(), - )?; - for (j, style) in meta.styles().iter().enumerate() { - let j_style = env.new_object( - object_type!("VoiceModel$StyleMeta"), - concat!( - "(", - "Ljava/lang/String;", // name - "I", // id - ")V" - ), - &[ - JValueGen::Object(&env.new_string(style.name())?.into()), - JValueGen::Int(style.id().raw_id() as i32), - ], - )?; - env.set_object_array_element(&j_styles, j as i32, j_style)?; - } - - let j_meta = env.new_object( - object_type!("VoiceModel$SpeakerMeta"), - concat!( - "(", - "Ljava/lang/String;", // name - "[", // styles - object_type!("VoiceModel$StyleMeta"), - "Ljava/lang/String;", // speakerUuid - "Ljava/lang/String;", // version - ")V" - ), - &[ - JValueGen::Object(&env.new_string(meta.name())?.into()), - JValueGen::Object(&j_styles.into()), - JValueGen::Object(&env.new_string(meta.speaker_uuid())?.into()), - JValueGen::Object(&env.new_string(meta.version().raw_version())?.into()), - ], - )?; - env.set_object_array_element(&j_speakers, i as i32, j_meta)?; - } - Ok(j_speakers.into_raw()) + let metas = internal.metas(); + let metas_json = serde_json::to_string(&metas)?; + Ok(env.new_string(metas_json)?.into_raw()) }) } From 6825efcfcaf92d80ba51d8c4bcd65ea15eb9b813 Mon Sep 17 00:00:00 2001 From: sevenc-nanashi Date: Wed, 2 Aug 2023 22:22:47 +0900 Subject: [PATCH 13/99] =?UTF-8?q?Add:=20accent=5Fphrases=E3=82=92=E8=BF=BD?= =?UTF-8?q?=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Hiroshiba/VoicevoxCore/Synthesizer.java | 34 +++++++++++++++++ .../voicevox_core_java_api/src/synthesizer.rs | 38 +++++++++++++++++++ 2 files changed, 72 insertions(+) diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Synthesizer.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Synthesizer.java index 5827957e6..60613ba21 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Synthesizer.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Synthesizer.java @@ -1,6 +1,9 @@ package jp.Hiroshiba.VoicevoxCore; +import java.util.ArrayList; +import java.util.Arrays; import java.util.EnumSet; +import java.util.List; import javax.annotation.Nonnull; @@ -41,6 +44,18 @@ public AudioQuery audioQuery(String text, int styleId, EnumSet return audioQuery; } + @Nonnull + public List accentPhrases(String text, EnumSet options) { + boolean kana = options.contains(AccentPhrasesOption.KANA); + String accentPhrasesJson = rsAccentPhrases(text, kana); + Gson gson = new Gson(); + AccentPhrase[] rawAccentPhrases = gson.fromJson(accentPhrasesJson, AccentPhrase[].class); + if (rawAccentPhrases == null) { + throw new NullPointerException("accent_phrases"); + } + return new ArrayList<>(Arrays.asList(rawAccentPhrases)); + } + public void close() { rsDrop(); } @@ -56,6 +71,12 @@ public void close() { @Nonnull private native String rsAudioQuery(String text, int styleId, boolean kana); + @Nonnull + private native String rsAccentPhrases(String text, boolean kana); + + @Nonnull + private native String rsGetAudioQueryJson(); + private native void rsDrop(); static { @@ -109,4 +130,17 @@ public static enum AccelerationMode { public static enum AudioQueryOption { KANA, } + + public static enum AccentPhrasesOption { + KANA, + } + + public static enum SynthesisOption { + ENABLE_INTERROGATIVE_UPSPEAK + } + + public static enum TtsOption { + KANA, + ENABLE_INTERROGATIVE_UPSPEAK + } } diff --git a/crates/voicevox_core_java_api/src/synthesizer.rs b/crates/voicevox_core_java_api/src/synthesizer.rs index 9d3ee249b..576157073 100644 --- a/crates/voicevox_core_java_api/src/synthesizer.rs +++ b/crates/voicevox_core_java_api/src/synthesizer.rs @@ -174,6 +174,44 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsAudioQuery<' }) } +#[no_mangle] +pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsAccentPhrases<'local>( + env: JNIEnv<'local>, + this: JObject<'local>, + text: JString<'local>, + style_id: jint, + kana: jboolean, +) -> jobject { + throw_if_err(env, std::ptr::null_mut(), |env| { + let text: String = env.get_string(&text)?.into(); + let style_id = style_id as u32; + + let internal = unsafe { + env.get_rust_field::<_, _, Arc>>(&this, "internal")? + .clone() + }; + + let accent_phrases = { + let internal = internal.lock().unwrap(); + let options = voicevox_core::AccentPhrasesOptions { + kana: kana != 0, + // ..Default::default() + }; + RUNTIME.block_on(internal.create_accent_phrases( + &text, + voicevox_core::StyleId::new(style_id), + &options, + ))? + }; + + let query_json = serde_json::to_string(&accent_phrases)?; + + let j_accent_phrases = env.new_string(query_json)?; + + Ok(j_accent_phrases.into_raw()) + }) +} + #[no_mangle] pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsDrop<'local>( env: JNIEnv<'local>, From cca1c1745d6e57943a4543b4553e44f12b1ef71b Mon Sep 17 00:00:00 2001 From: sevenc-nanashi Date: Wed, 2 Aug 2023 22:35:57 +0900 Subject: [PATCH 14/99] =?UTF-8?q?Add:=20=E3=83=86=E3=82=B9=E3=83=88?= =?UTF-8?q?=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Hiroshiba/VoicevoxCore/Synthesizer.java | 26 ++++++- .../VoicevoxCore/SynthesizerTest.java | 15 +++- .../voicevox_core_java_api/src/synthesizer.rs | 75 +++++++++++++++++++ 3 files changed, 111 insertions(+), 5 deletions(-) diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Synthesizer.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Synthesizer.java index 60613ba21..9618810cb 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Synthesizer.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Synthesizer.java @@ -45,9 +45,9 @@ public AudioQuery audioQuery(String text, int styleId, EnumSet } @Nonnull - public List accentPhrases(String text, EnumSet options) { + public List accentPhrases(String text, int styleId, EnumSet options) { boolean kana = options.contains(AccentPhrasesOption.KANA); - String accentPhrasesJson = rsAccentPhrases(text, kana); + String accentPhrasesJson = rsAccentPhrases(text, styleId, kana); Gson gson = new Gson(); AccentPhrase[] rawAccentPhrases = gson.fromJson(accentPhrasesJson, AccentPhrase[].class); if (rawAccentPhrases == null) { @@ -56,6 +56,21 @@ public List accentPhrases(String text, EnumSet(Arrays.asList(rawAccentPhrases)); } + @Nonnull + public byte[] synthesis(AudioQuery audioQuery, int styleId, EnumSet options) { + boolean enableInterrogativeUpspeak = options.contains(SynthesisOption.ENABLE_INTERROGATIVE_UPSPEAK); + Gson gson = new Gson(); + String queryJson = gson.toJson(audioQuery); + return rsSynthesis(queryJson, styleId, enableInterrogativeUpspeak); + } + + @Nonnull + public byte[] tts(String text, int styleId, EnumSet options) { + boolean kana = options.contains(TtsOption.KANA); + boolean enableInterrogativeUpspeak = options.contains(TtsOption.ENABLE_INTERROGATIVE_UPSPEAK); + return rsTts(text, styleId, kana, enableInterrogativeUpspeak); + } + public void close() { rsDrop(); } @@ -72,10 +87,13 @@ public void close() { private native String rsAudioQuery(String text, int styleId, boolean kana); @Nonnull - private native String rsAccentPhrases(String text, boolean kana); + private native String rsAccentPhrases(String text, int styleId, boolean kana); + + @Nonnull + private native byte[] rsSynthesis(String queryJson, int styleId, boolean enableInterrogativeUpspeak); @Nonnull - private native String rsGetAudioQueryJson(); + private native byte[] rsTts(String text, int styleId, boolean kana, boolean enableInterrogativeUpspeak); private native void rsDrop(); 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 6510e76ef..271e02703 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 @@ -50,7 +50,20 @@ void checkAudioQuery() { OpenJtalk openJtalk = openJtalk(); Synthesizer synthesizer = Synthesizer.builder(openJtalk).build()) { synthesizer.loadVoiceModel(model); - synthesizer.audioQuery("こんにちは", model.metas[0].styles[0].id, EnumSet.noneOf(Synthesizer.AudioQueryOption.class)); + AudioQuery query = synthesizer.audioQuery("こんにちは", model.metas[0].styles[0].id, + EnumSet.noneOf(Synthesizer.AudioQueryOption.class)); + + synthesizer.synthesis(query, model.metas[0].styles[0].id, EnumSet.noneOf(Synthesizer.SynthesisOption.class)); + } + } + + @Test + void checkTts() { + try (VoiceModel model = model(); + OpenJtalk openJtalk = openJtalk(); + Synthesizer synthesizer = Synthesizer.builder(openJtalk).build()) { + synthesizer.loadVoiceModel(model); + synthesizer.tts("こんにちは", model.metas[0].styles[0].id, EnumSet.noneOf(Synthesizer.TtsOption.class)); } } } diff --git a/crates/voicevox_core_java_api/src/synthesizer.rs b/crates/voicevox_core_java_api/src/synthesizer.rs index 576157073..d06528988 100644 --- a/crates/voicevox_core_java_api/src/synthesizer.rs +++ b/crates/voicevox_core_java_api/src/synthesizer.rs @@ -212,6 +212,81 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsAccentPhrase }) } +#[no_mangle] +pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsSynthesis<'local>( + env: JNIEnv<'local>, + this: JObject<'local>, + query_json: JString<'local>, + style_id: jint, + enable_interrogative_upspeak: jboolean, +) -> jobject { + throw_if_err(env, std::ptr::null_mut(), |env| { + let audio_query: String = env.get_string(&query_json)?.into(); + let audio_query: voicevox_core::AudioQueryModel = serde_json::from_str(&audio_query)?; + let style_id = style_id as u32; + + let internal = unsafe { + env.get_rust_field::<_, _, Arc>>(&this, "internal")? + .clone() + }; + + let wave = { + let internal = internal.lock().unwrap(); + let options = voicevox_core::SynthesisOptions { + enable_interrogative_upspeak: enable_interrogative_upspeak != 0, + // ..Default::default() + }; + RUNTIME.block_on(internal.synthesis( + &audio_query, + voicevox_core::StyleId::new(style_id), + &options, + ))? + }; + + let j_bytes = env.byte_array_from_slice(&wave)?; + + Ok(j_bytes.into_raw()) + }) +} + +#[no_mangle] +pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsTts<'local>( + env: JNIEnv<'local>, + this: JObject<'local>, + query_json: JString<'local>, + style_id: jint, + kana: jboolean, + enable_interrogative_upspeak: jboolean, +) -> jobject { + throw_if_err(env, std::ptr::null_mut(), |env| { + let text: String = env.get_string(&query_json)?.into(); + let style_id = style_id as u32; + + let internal = unsafe { + env.get_rust_field::<_, _, Arc>>(&this, "internal")? + .clone() + }; + + let wave = { + let internal = internal.lock().unwrap(); + let options = voicevox_core::TtsOptions { + kana: kana != 0, + enable_interrogative_upspeak: enable_interrogative_upspeak != 0, + // ..Default::default() + }; + RUNTIME.block_on(internal.tts( + &text, + voicevox_core::StyleId::new(style_id), + &options, + ))? + }; + + let j_bytes = env.byte_array_from_slice(&wave)?; + + Ok(j_bytes.into_raw()) + }) +} + #[no_mangle] pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsDrop<'local>( env: JNIEnv<'local>, From 18ec0ac9953603e083d104e2edf81ed0f1b46d6b Mon Sep 17 00:00:00 2001 From: sevenc-nanashi Date: Thu, 3 Aug 2023 07:32:15 +0900 Subject: [PATCH 15/99] =?UTF-8?q?Add:=20AccentPhrases=E3=81=AE=E6=93=8D?= =?UTF-8?q?=E4=BD=9C=E7=B3=BB=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Hiroshiba/VoicevoxCore/Synthesizer.java | 32 ++++++- .../jp/Hiroshiba/VoicevoxCore/MetaTest.java | 4 +- .../VoicevoxCore/SynthesizerTest.java | 43 +++++++++ .../voicevox_core_java_api/src/synthesizer.rs | 94 +++++++++++++++++++ 4 files changed, 169 insertions(+), 4 deletions(-) diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Synthesizer.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Synthesizer.java index 9618810cb..d9fddbcaf 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Synthesizer.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Synthesizer.java @@ -45,7 +45,7 @@ public AudioQuery audioQuery(String text, int styleId, EnumSet } @Nonnull - public List accentPhrases(String text, int styleId, EnumSet options) { + public List createAccentPhrases(String text, int styleId, EnumSet options) { boolean kana = options.contains(AccentPhrasesOption.KANA); String accentPhrasesJson = rsAccentPhrases(text, styleId, kana); Gson gson = new Gson(); @@ -56,6 +56,27 @@ public List accentPhrases(String text, int styleId, EnumSet(Arrays.asList(rawAccentPhrases)); } + @Nonnull + public List replaceMoraData(List accentPhrases, int styleId) { + String accentPhrasesJson = new Gson().toJson(accentPhrases); + String replacedAccentPhrasesJson = rsReplaceMoraData(accentPhrasesJson, styleId, false); + return new ArrayList<>(Arrays.asList(new Gson().fromJson(replacedAccentPhrasesJson, AccentPhrase[].class))); + } + + @Nonnull + public List replacePhonemeLength(List accentPhrases, int styleId) { + String accentPhrasesJson = new Gson().toJson(accentPhrases); + String replacedAccentPhrasesJson = rsReplacePhonemeLength(accentPhrasesJson, styleId, false); + return new ArrayList<>(Arrays.asList(new Gson().fromJson(replacedAccentPhrasesJson, AccentPhrase[].class))); + } + + @Nonnull + public List replaceMoraPitch(List accentPhrases, int styleId) { + String accentPhrasesJson = new Gson().toJson(accentPhrases); + String replacedAccentPhrasesJson = rsReplaceMoraPitch(accentPhrasesJson, styleId, false); + return new ArrayList<>(Arrays.asList(new Gson().fromJson(replacedAccentPhrasesJson, AccentPhrase[].class))); + } + @Nonnull public byte[] synthesis(AudioQuery audioQuery, int styleId, EnumSet options) { boolean enableInterrogativeUpspeak = options.contains(SynthesisOption.ENABLE_INTERROGATIVE_UPSPEAK); @@ -89,6 +110,15 @@ public void close() { @Nonnull private native String rsAccentPhrases(String text, int styleId, boolean kana); + @Nonnull + private native String rsReplaceMoraData(String accentPhrasesJson, int styleId, boolean kana); + + @Nonnull + private native String rsReplacePhonemeLength(String accentPhrasesJson, int styleId, boolean kana); + + @Nonnull + private native String rsReplaceMoraPitch(String accentPhrasesJson, int styleId, boolean kana); + @Nonnull private native byte[] rsSynthesis(String queryJson, int styleId, boolean enableInterrogativeUpspeak); diff --git a/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/MetaTest.java b/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/MetaTest.java index 2f7e9dfb0..c92b2b06d 100644 --- a/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/MetaTest.java +++ b/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/MetaTest.java @@ -9,14 +9,12 @@ class MetaTest { @Test - void checkMeta() { + void checkLoad() { // cwdはvoicevox_core/crates/voicevox_core_java_api/lib String cwd = System.getProperty("user.dir"); File path = new File( cwd + "/../../../model/sample.vvm"); try (VoiceModel model = new VoiceModel(path.getAbsolutePath())) { - System.out.println(model); } - } } 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 271e02703..b9c04b72e 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 @@ -13,6 +13,7 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.EnumSet; +import java.util.List; @Timeout(10) class SynthesizerTest { @@ -32,6 +33,28 @@ OpenJtalk openJtalk() { return new OpenJtalk(path.toString()); } + @FunctionalInterface + interface MoraCheckCallback { + boolean check(Mora mora, Mora otherMora); + } + + boolean checkAllMoras( + List accentPhrases, + List otherAccentPhrases, + MoraCheckCallback checker) { + for (int i = 0; i < accentPhrases.size(); i++) { + AccentPhrase accentPhrase = accentPhrases.get(i); + for (int j = 0; j < accentPhrase.moras.size(); j++) { + Mora mora = accentPhrase.moras.get(j); + Mora otherMora = otherAccentPhrases.get(i).moras.get(j); + if (!checker.check(mora, otherMora)) { + return false; + } + } + } + return true; + } + @Test void checkModel() { try (VoiceModel model = model(); @@ -57,6 +80,26 @@ void checkAudioQuery() { } } + @Test + void checkAccentPhrases() { + try (VoiceModel model = model(); + OpenJtalk openJtalk = openJtalk(); + Synthesizer synthesizer = Synthesizer.builder(openJtalk).build()) { + synthesizer.loadVoiceModel(model); + List accentPhrases = synthesizer.createAccentPhrases("こんにちは", model.metas[0].styles[0].id, + EnumSet.noneOf(Synthesizer.AccentPhrasesOption.class)); + List accentPhrases2 = synthesizer.replaceMoraPitch(accentPhrases, model.metas[1].styles[0].id); + assertTrue(checkAllMoras(accentPhrases, accentPhrases2, (mora, otherMora) -> mora.pitch != otherMora.pitch)); + List accentPhrases3 = synthesizer.replacePhonemeLength(accentPhrases, model.metas[1].styles[0].id); + assertTrue( + checkAllMoras(accentPhrases, accentPhrases3, (mora, otherMora) -> mora.vowelLength != otherMora.vowelLength)); + List accentPhrases4 = synthesizer.replaceMoraData(accentPhrases, model.metas[1].styles[0].id); + assertTrue(checkAllMoras(accentPhrases, accentPhrases4, + (mora, otherMora) -> mora.pitch != otherMora.pitch && mora.vowelLength != otherMora.vowelLength)); + + } + } + @Test void checkTts() { try (VoiceModel model = model(); diff --git a/crates/voicevox_core_java_api/src/synthesizer.rs b/crates/voicevox_core_java_api/src/synthesizer.rs index d06528988..5d2ea8316 100644 --- a/crates/voicevox_core_java_api/src/synthesizer.rs +++ b/crates/voicevox_core_java_api/src/synthesizer.rs @@ -212,6 +212,100 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsAccentPhrase }) } +#[no_mangle] +pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsReplaceMoraData<'local>( + env: JNIEnv<'local>, + this: JObject<'local>, + accent_phrases_json: JString<'local>, + style_id: jint, +) -> jobject { + throw_if_err(env, std::ptr::null_mut(), |env| { + let accent_phrases_json: String = env.get_string(&accent_phrases_json)?.into(); + let accent_phrases: Vec = + serde_json::from_str(&accent_phrases_json)?; + let style_id = style_id as u32; + + let internal = unsafe { + env.get_rust_field::<_, _, Arc>>(&this, "internal")? + .clone() + }; + + let replaced_accent_phrases = { + let internal = internal.lock().unwrap(); + RUNTIME.block_on( + internal.replace_mora_data(&accent_phrases, voicevox_core::StyleId::new(style_id)), + )? + }; + + let replaced_accent_phrases_json = serde_json::to_string(&replaced_accent_phrases)?; + + Ok(env.new_string(replaced_accent_phrases_json)?.into_raw()) + }) +} + +#[no_mangle] +pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsReplacePhonemeLength<'local>( + env: JNIEnv<'local>, + this: JObject<'local>, + accent_phrases_json: JString<'local>, + style_id: jint, +) -> jobject { + throw_if_err(env, std::ptr::null_mut(), |env| { + let accent_phrases_json: String = env.get_string(&accent_phrases_json)?.into(); + let accent_phrases: Vec = + serde_json::from_str(&accent_phrases_json)?; + let style_id = style_id as u32; + + let internal = unsafe { + env.get_rust_field::<_, _, Arc>>(&this, "internal")? + .clone() + }; + + let replaced_accent_phrases = { + let internal = internal.lock().unwrap(); + RUNTIME.block_on( + internal + .replace_phoneme_length(&accent_phrases, voicevox_core::StyleId::new(style_id)), + )? + }; + + let replaced_accent_phrases_json = serde_json::to_string(&replaced_accent_phrases)?; + + Ok(env.new_string(replaced_accent_phrases_json)?.into_raw()) + }) +} + +#[no_mangle] +pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsReplaceMoraPitch<'local>( + env: JNIEnv<'local>, + this: JObject<'local>, + accent_phrases_json: JString<'local>, + style_id: jint, +) -> jobject { + throw_if_err(env, std::ptr::null_mut(), |env| { + let accent_phrases_json: String = env.get_string(&accent_phrases_json)?.into(); + let accent_phrases: Vec = + serde_json::from_str(&accent_phrases_json)?; + let style_id = style_id as u32; + + let internal = unsafe { + env.get_rust_field::<_, _, Arc>>(&this, "internal")? + .clone() + }; + + let replaced_accent_phrases = { + let internal = internal.lock().unwrap(); + RUNTIME.block_on( + internal.replace_mora_pitch(&accent_phrases, voicevox_core::StyleId::new(style_id)), + )? + }; + + let replaced_accent_phrases_json = serde_json::to_string(&replaced_accent_phrases)?; + + Ok(env.new_string(replaced_accent_phrases_json)?.into_raw()) + }) +} + #[no_mangle] pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsSynthesis<'local>( env: JNIEnv<'local>, From 39f7dc80ce8ee94560333e7eb6f262958d478e9a Mon Sep 17 00:00:00 2001 From: sevenc-nanashi Date: Thu, 3 Aug 2023 07:41:03 +0900 Subject: [PATCH 16/99] =?UTF-8?q?Add:=20=E3=83=A6=E3=83=BC=E3=82=B6?= =?UTF-8?q?=E3=83=BC=E8=BE=9E=E6=9B=B8=E3=81=AE=E3=83=86=E3=82=B9=E3=83=88?= =?UTF-8?q?=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../jp/Hiroshiba/VoicevoxCore/UserDict.java | 18 +++++++++++ .../VoicevoxCore/SynthesizerTest.java | 23 ++----------- .../Hiroshiba/VoicevoxCore/UserDictTest.java | 32 +++++++++++++++++++ .../java/jp/Hiroshiba/VoicevoxCore/Utils.java | 22 +++++++++++++ 4 files changed, 74 insertions(+), 21 deletions(-) create mode 100644 crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/UserDict.java create mode 100644 crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/UserDictTest.java create mode 100644 crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/Utils.java diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/UserDict.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/UserDict.java new file mode 100644 index 000000000..ae069106e --- /dev/null +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/UserDict.java @@ -0,0 +1,18 @@ +package jp.Hiroshiba.VoicevoxCore; + +public class UserDict + implements AutoCloseable { + protected long internal; + + public UserDict() { + rsNew(); + } + + public void close() { + rsDrop(); + } + + private native void rsNew(); + + private native void rsDrop(); +} 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 b9c04b72e..fc13c349d 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 @@ -5,34 +5,15 @@ package jp.Hiroshiba.VoicevoxCore; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.Timeout; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; -import java.nio.file.Path; -import java.nio.file.Paths; import java.util.EnumSet; import java.util.List; -@Timeout(10) -class SynthesizerTest { - VoiceModel model() { - // cwdはvoicevox_core/crates/voicevox_core_java_api/lib - String cwd = System.getProperty("user.dir"); - Path path = Paths.get(cwd, "..", "..", "..", "model", "sample.vvm"); - - return new VoiceModel(path.toString()); - - } - - OpenJtalk openJtalk() { - String cwd = System.getProperty("user.dir"); - Path path = Paths.get(cwd, "..", "..", "test_util", "data", "open_jtalk_dic_utf_8-1.11"); - - return new OpenJtalk(path.toString()); - } - +class SynthesizerTest + extends Utils { @FunctionalInterface interface MoraCheckCallback { boolean check(Mora mora, Mora otherMora); diff --git a/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/UserDictTest.java b/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/UserDictTest.java new file mode 100644 index 000000000..8af9a48a5 --- /dev/null +++ b/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/UserDictTest.java @@ -0,0 +1,32 @@ +package jp.Hiroshiba.VoicevoxCore; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.EnumSet; + +import org.junit.jupiter.api.Test; + +class UserDictTest + extends Utils { + + @Test + void checkLoad() { + try (VoiceModel model = model(); + OpenJtalk openJtalk = openJtalk(); + Synthesizer synthesizer = Synthesizer.builder(openJtalk).build(); + UserDict userDict = new UserDict()) { + synthesizer.loadVoiceModel(model); + AudioQuery query1 = synthesizer.audioQuery("this_word_should_not_exist_in_default_dictionary", + model.metas[0].styles[0].id, + EnumSet.noneOf(Synthesizer.AudioQueryOption.class)); + userDict.addWord( + UserDict.word().surface("this_word_should_not_exist_in_default_dictionary").pronunciation("テスト").build()); + openJtalk.useUserDict(userDict); + AudioQuery query2 = synthesizer.audioQuery("this_word_should_not_exist_in_default_dictionary", + model.metas[0].styles[0].id, + EnumSet.noneOf(Synthesizer.AudioQueryOption.class)); + assertTrue(query1.kana != query2.kana); + + } + } +} diff --git a/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/Utils.java b/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/Utils.java new file mode 100644 index 000000000..19b914b80 --- /dev/null +++ b/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/Utils.java @@ -0,0 +1,22 @@ +package jp.Hiroshiba.VoicevoxCore; + +import java.nio.file.Path; +import java.nio.file.Paths; + +class Utils { + VoiceModel model() { + // cwdはvoicevox_core/crates/voicevox_core_java_api/lib + String cwd = System.getProperty("user.dir"); + Path path = Paths.get(cwd, "..", "..", "..", "model", "sample.vvm"); + + return new VoiceModel(path.toString()); + + } + + OpenJtalk openJtalk() { + String cwd = System.getProperty("user.dir"); + Path path = Paths.get(cwd, "..", "..", "test_util", "data", "open_jtalk_dic_utf_8-1.11"); + + return new OpenJtalk(path.toString()); + } +} From 79a8ca5694fddf7f1f7a0327af9d6041be667683 Mon Sep 17 00:00:00 2001 From: sevenc-nanashi Date: Thu, 3 Aug 2023 08:26:25 +0900 Subject: [PATCH 17/99] =?UTF-8?q?Add:=20=E3=83=A6=E3=83=BC=E3=82=B6?= =?UTF-8?q?=E3=83=BC=E8=BE=9E=E6=9B=B8=E3=81=AE=E3=82=A4=E3=83=B3=E3=82=BF?= =?UTF-8?q?=E3=83=BC=E3=83=95=E3=82=A7=E3=82=A4=E3=82=B9=E3=82=92=E8=BF=BD?= =?UTF-8?q?=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../voicevox_core_java_api/lib/build.gradle | 3 + .../jp/Hiroshiba/VoicevoxCore/UserDict.java | 162 ++++++++++++++++++ .../Hiroshiba/VoicevoxCore/UserDictTest.java | 2 +- 3 files changed, 166 insertions(+), 1 deletion(-) diff --git a/crates/voicevox_core_java_api/lib/build.gradle b/crates/voicevox_core_java_api/lib/build.gradle index 6891ef181..4b0c8db64 100644 --- a/crates/voicevox_core_java_api/lib/build.gradle +++ b/crates/voicevox_core_java_api/lib/build.gradle @@ -38,6 +38,9 @@ dependencies { // https://mvnrepository.com/artifact/com.google.code.gson/gson implementation group: 'com.google.code.gson', name: 'gson', version: '2.10.1' + + // https://mvnrepository.com/artifact/jakarta.validation/jakarta.validation-api + implementation group: 'jakarta.validation', name: 'jakarta.validation-api', version: '3.0.2' } // 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/UserDict.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/UserDict.java index ae069106e..014cf9a4d 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/UserDict.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/UserDict.java @@ -1,5 +1,16 @@ package jp.Hiroshiba.VoicevoxCore; +import java.util.HashMap; + +import javax.annotation.Nonnull; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.google.gson.Gson; +import com.google.gson.annotations.Expose; +import com.google.gson.annotations.SerializedName; + public class UserDict implements AutoCloseable { protected long internal; @@ -8,11 +19,162 @@ public UserDict() { rsNew(); } + @Nonnull + public String addWord(Word word) { + return rsAddWord(word); + } + + public void updateWord(String uuid, Word word) { + rsUpdateWord(uuid, word); + } + + public void removeWord(String uuid) { + rsRemoveWord(uuid); + } + + public void load(String path) { + rsLoad(path); + } + + public void save(String path) { + rsSave(path); + } + + @Nonnull + public HashMap getWords() { + String json = rsGetWords(); + Gson gson = new Gson(); + @SuppressWarnings("unchecked") + HashMap words = gson.fromJson(json, HashMap.class); + if (words == null) { + throw new NullPointerException("words"); + } + return words; + } + public void close() { rsDrop(); } private native void rsNew(); + @Nonnull + private native String rsAddWord(Word word); + + private native void rsUpdateWord(String uuid, Word word); + + private native void rsRemoveWord(String uuid); + + private native void rsLoad(String path); + + private native void rsSave(String path); + + @Nonnull + private native String rsGetWords(); + private native void rsDrop(); + + public static class Word { + @JsonProperty("surface") + @SerializedName("surface") + @Expose + @Nonnull + public String surface; + + @JsonProperty("pronunciation") + @SerializedName("pronunciation") + @Expose + @Nonnull + public String pronunciation; + + @JsonProperty("word_type") + @SerializedName("word_type") + @Expose + @Nonnull + public Type wordType; + + @JsonProperty("accent_type") + @SerializedName("accent_type") + @Expose + public int accentType; + + @JsonProperty("priority") + @SerializedName("priority") + @Expose + @Min(1) + @Max(10) + public int priority; + + public Word(String surface, String pronunciation) { + if (surface == null) { + throw new NullPointerException("surface"); + } + if (pronunciation == null) { + throw new NullPointerException("pronunciation"); + } + + this.surface = rsToZenkaku(surface); + rsValidatePronunciation(pronunciation); + this.pronunciation = pronunciation; + this.wordType = Type.COMMON_NOUN; + this.accentType = 0; + this.priority = 5; + } + + public Word wordType(Type wordType) { + if (wordType == null) { + throw new NullPointerException("wordType"); + } + this.wordType = wordType; + return this; + } + + public Word accentType(int accentType) { + if (accentType < 0) { + throw new IllegalArgumentException("accentType"); + } + this.accentType = accentType; + return this; + } + + public Word priority(int priority) { + if (priority < 0 || priority > 10) { + throw new IllegalArgumentException("priority"); + } + this.priority = priority; + return this; + } + + @Nonnull + private native String rsToZenkaku(String surface); + + private native void rsValidatePronunciation(String pronunciation); + + static enum Type { + @JsonProperty("PROPER_NOUN") + @SerializedName("PROPER_NOUN") + @Expose + PROPER_NOUN, + + @JsonProperty("COMMON_NOUN") + @SerializedName("COMMON_NOUN") + @Expose + COMMON_NOUN, + + @JsonProperty("VERB") + @SerializedName("VERB") + @Expose + VERB, + + @JsonProperty("ADJECTIVE") + @SerializedName("ADJECTIVE") + @Expose + ADJECTIVE, + + @JsonProperty("SUFFIX") + @SerializedName("SUFFIX") + @Expose + SUFFIX, + } + } } diff --git a/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/UserDictTest.java b/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/UserDictTest.java index 8af9a48a5..f5067ffc0 100644 --- a/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/UserDictTest.java +++ b/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/UserDictTest.java @@ -20,7 +20,7 @@ void checkLoad() { model.metas[0].styles[0].id, EnumSet.noneOf(Synthesizer.AudioQueryOption.class)); userDict.addWord( - UserDict.word().surface("this_word_should_not_exist_in_default_dictionary").pronunciation("テスト").build()); + new UserDict.Word("this_word_should_not_exist_in_default_dictionary", "テスト")); openJtalk.useUserDict(userDict); AudioQuery query2 = synthesizer.audioQuery("this_word_should_not_exist_in_default_dictionary", model.metas[0].styles[0].id, From 38d5456615e1e7edf608eacfd77b6f75293bf1b3 Mon Sep 17 00:00:00 2001 From: sevenc-nanashi Date: Thu, 3 Aug 2023 09:25:31 +0900 Subject: [PATCH 18/99] =?UTF-8?q?Add:=20=E8=BE=9E=E6=9B=B8=E3=83=AD?= =?UTF-8?q?=E3=83=BC=E3=83=89=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../jp/Hiroshiba/VoicevoxCore/OpenJtalk.java | 6 + .../jp/Hiroshiba/VoicevoxCore/UserDict.java | 24 +- .../VoicevoxCore/SynthesizerTest.java | 16 +- .../Hiroshiba/VoicevoxCore/UserDictTest.java | 4 +- .../java/jp/Hiroshiba/VoicevoxCore/Utils.java | 23 +- crates/voicevox_core_java_api/src/lib.rs | 2 + .../voicevox_core_java_api/src/open_jtalk.rs | 28 ++- .../voicevox_core_java_api/src/synthesizer.rs | 2 +- .../voicevox_core_java_api/src/user_dict.rs | 222 ++++++++++++++++++ .../voicevox_core_java_api/src/voice_model.rs | 13 +- 10 files changed, 305 insertions(+), 35 deletions(-) create mode 100644 crates/voicevox_core_java_api/src/user_dict.rs diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/OpenJtalk.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/OpenJtalk.java index dd53be804..3c5121775 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/OpenJtalk.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/OpenJtalk.java @@ -11,6 +11,10 @@ public OpenJtalk(String openJtalkDictDir) { rsNewWithInitialize(openJtalkDictDir); } + public void useUserDict(UserDict userDict) { + rsUseUserDict(userDict); + } + public void close() { rsDrop(); } @@ -19,6 +23,8 @@ public void close() { private native void rsNewWithInitialize(String openJtalkDictDir); + private native void rsUseUserDict(UserDict userDict); + private native void rsDrop(); static { diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/UserDict.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/UserDict.java index 014cf9a4d..9c198d875 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/UserDict.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/UserDict.java @@ -21,11 +21,17 @@ public UserDict() { @Nonnull public String addWord(Word word) { - return rsAddWord(word); + Gson gson = new Gson(); + String wordJson = gson.toJson(word); + + return rsAddWord(wordJson); } public void updateWord(String uuid, Word word) { - rsUpdateWord(uuid, word); + Gson gson = new Gson(); + String wordJson = gson.toJson(word); + + rsUpdateWord(uuid, wordJson); } public void removeWord(String uuid) { @@ -59,9 +65,9 @@ public void close() { private native void rsNew(); @Nonnull - private native String rsAddWord(Word word); + private native String rsAddWord(String word); - private native void rsUpdateWord(String uuid, Word word); + private native void rsUpdateWord(String uuid, String word); private native void rsRemoveWord(String uuid); @@ -74,6 +80,11 @@ public void close() { private native void rsDrop(); + @Nonnull + private static native String rsToZenkaku(String surface); + + private static native void rsValidatePronunciation(String pronunciation); + public static class Word { @JsonProperty("surface") @SerializedName("surface") @@ -145,11 +156,6 @@ public Word priority(int priority) { return this; } - @Nonnull - private native String rsToZenkaku(String surface); - - private native void rsValidatePronunciation(String pronunciation); - static enum Type { @JsonProperty("PROPER_NOUN") @SerializedName("PROPER_NOUN") 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 fc13c349d..e7869313e 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 @@ -38,8 +38,8 @@ boolean checkAllMoras( @Test void checkModel() { - try (VoiceModel model = model(); - OpenJtalk openJtalk = openJtalk(); + try (VoiceModel model = loadModel(); + OpenJtalk openJtalk = loadOpenJtalk(); Synthesizer synthesizer = Synthesizer.builder(openJtalk).build()) { synthesizer.loadVoiceModel(model); assertTrue(synthesizer.isLoadedVoiceModel(model.id)); @@ -50,8 +50,8 @@ void checkModel() { @Test void checkAudioQuery() { - try (VoiceModel model = model(); - OpenJtalk openJtalk = openJtalk(); + try (VoiceModel model = loadModel(); + OpenJtalk openJtalk = loadOpenJtalk(); Synthesizer synthesizer = Synthesizer.builder(openJtalk).build()) { synthesizer.loadVoiceModel(model); AudioQuery query = synthesizer.audioQuery("こんにちは", model.metas[0].styles[0].id, @@ -63,8 +63,8 @@ void checkAudioQuery() { @Test void checkAccentPhrases() { - try (VoiceModel model = model(); - OpenJtalk openJtalk = openJtalk(); + try (VoiceModel model = loadModel(); + OpenJtalk openJtalk = loadOpenJtalk(); Synthesizer synthesizer = Synthesizer.builder(openJtalk).build()) { synthesizer.loadVoiceModel(model); List accentPhrases = synthesizer.createAccentPhrases("こんにちは", model.metas[0].styles[0].id, @@ -83,8 +83,8 @@ void checkAccentPhrases() { @Test void checkTts() { - try (VoiceModel model = model(); - OpenJtalk openJtalk = openJtalk(); + try (VoiceModel model = loadModel(); + OpenJtalk openJtalk = loadOpenJtalk(); Synthesizer synthesizer = Synthesizer.builder(openJtalk).build()) { synthesizer.loadVoiceModel(model); synthesizer.tts("こんにちは", model.metas[0].styles[0].id, EnumSet.noneOf(Synthesizer.TtsOption.class)); diff --git a/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/UserDictTest.java b/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/UserDictTest.java index f5067ffc0..21724a5a3 100644 --- a/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/UserDictTest.java +++ b/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/UserDictTest.java @@ -11,8 +11,8 @@ class UserDictTest @Test void checkLoad() { - try (VoiceModel model = model(); - OpenJtalk openJtalk = openJtalk(); + try (VoiceModel model = loadModel(); + OpenJtalk openJtalk = loadOpenJtalk(); Synthesizer synthesizer = Synthesizer.builder(openJtalk).build(); UserDict userDict = new UserDict()) { synthesizer.loadVoiceModel(model); diff --git a/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/Utils.java b/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/Utils.java index 19b914b80..42cfd7474 100644 --- a/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/Utils.java +++ b/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/Utils.java @@ -1,22 +1,29 @@ package jp.Hiroshiba.VoicevoxCore; -import java.nio.file.Path; -import java.nio.file.Paths; +import java.io.File; class Utils { - VoiceModel model() { + VoiceModel loadModel() { // cwdはvoicevox_core/crates/voicevox_core_java_api/lib String cwd = System.getProperty("user.dir"); - Path path = Paths.get(cwd, "..", "..", "..", "model", "sample.vvm"); + File path = new File(cwd + "/../../../model/sample.vvm"); - return new VoiceModel(path.toString()); + try { + return new VoiceModel(path.getCanonicalPath()); + } catch (Exception e) { + throw new RuntimeException(e); + } } - OpenJtalk openJtalk() { + OpenJtalk loadOpenJtalk() { String cwd = System.getProperty("user.dir"); - Path path = Paths.get(cwd, "..", "..", "test_util", "data", "open_jtalk_dic_utf_8-1.11"); + File path = new File(cwd + "/../../test_util/data/open_jtalk_dic_utf_8-1.11"); - return new OpenJtalk(path.toString()); + try { + return new OpenJtalk(path.getCanonicalPath()); + } catch (Exception e) { + throw new RuntimeException(e); + } } } diff --git a/crates/voicevox_core_java_api/src/lib.rs b/crates/voicevox_core_java_api/src/lib.rs index db6d09968..07a74673c 100644 --- a/crates/voicevox_core_java_api/src/lib.rs +++ b/crates/voicevox_core_java_api/src/lib.rs @@ -1,8 +1,10 @@ mod common; mod open_jtalk; mod synthesizer; +mod user_dict; mod voice_model; pub use crate::open_jtalk::*; pub use crate::synthesizer::*; +pub use crate::user_dict::*; pub use crate::voice_model::*; diff --git a/crates/voicevox_core_java_api/src/open_jtalk.rs b/crates/voicevox_core_java_api/src/open_jtalk.rs index 6296a4cf4..4a65f882d 100644 --- a/crates/voicevox_core_java_api/src/open_jtalk.rs +++ b/crates/voicevox_core_java_api/src/open_jtalk.rs @@ -1,4 +1,4 @@ -use std::sync::Arc; +use std::sync::{Arc, Mutex}; use crate::common::throw_if_err; use jni::{ @@ -35,6 +35,32 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_OpenJtalk_rsNewWithInitial }) } +#[no_mangle] +pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_OpenJtalk_rsUseUserDict<'local>( + env: JNIEnv<'local>, + this: JObject<'local>, + user_dict: JObject<'local>, +) { + throw_if_err(env, (), |env| { + let internal = unsafe { + env.get_rust_field::<_, _, Arc>(&this, "internal")? + .clone() + }; + + let user_dict = unsafe { + env.get_rust_field::<_, _, Arc>>(&user_dict, "internal")? + .clone() + }; + + { + let user_dict = user_dict.lock().unwrap(); + internal.use_user_dict(&user_dict)? + } + + Ok(()) + }) +} + #[no_mangle] pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_OpenJtalk_rsDrop<'local>( env: JNIEnv<'local>, diff --git a/crates/voicevox_core_java_api/src/synthesizer.rs b/crates/voicevox_core_java_api/src/synthesizer.rs index 5d2ea8316..06e15fa29 100644 --- a/crates/voicevox_core_java_api/src/synthesizer.rs +++ b/crates/voicevox_core_java_api/src/synthesizer.rs @@ -58,7 +58,7 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsNewWithIniti .clone() }; let internal = RUNTIME.block_on(voicevox_core::Synthesizer::new_with_initialize( - open_jtalk.clone(), + open_jtalk, Box::leak(Box::new(options)), ))?; unsafe { env.set_rust_field(&this, "internal", Arc::new(Mutex::new(internal)))? }; diff --git a/crates/voicevox_core_java_api/src/user_dict.rs b/crates/voicevox_core_java_api/src/user_dict.rs new file mode 100644 index 000000000..5a2e3b37e --- /dev/null +++ b/crates/voicevox_core_java_api/src/user_dict.rs @@ -0,0 +1,222 @@ +use jni::objects::JClass; +use std::sync::{Arc, Mutex}; + +use crate::common::throw_if_err; +use jni::{ + objects::{JObject, JString}, + sys::jobject, + JNIEnv, +}; + +#[no_mangle] +pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsNew<'local>( + env: JNIEnv<'local>, + this: JObject<'local>, +) { + throw_if_err(env, (), |env| { + let internal = voicevox_core::UserDict::new(); + + unsafe { env.set_rust_field(&this, "internal", Arc::new(Mutex::new(internal))) }?; + + Ok(()) + }) +} + +#[no_mangle] +pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsAddWord<'local>( + env: JNIEnv<'local>, + this: JObject<'local>, + word_json: JString<'local>, +) -> jobject { + throw_if_err(env, std::ptr::null_mut(), |env| { + let internal = unsafe { + env.get_rust_field::<_, _, Arc>>(&this, "internal")? + .clone() + }; + + let word_json = env.get_string(&word_json)?; + let word_json = word_json.to_str()?; + + let word: voicevox_core::UserDictWord = serde_json::from_str(word_json)?; + + let uuid = { + let mut internal = internal.lock().unwrap(); + internal.add_word(word)? + }; + + let uuid = uuid.hyphenated().to_string(); + let uuid = env.new_string(uuid)?; + + Ok(uuid.into_raw()) + }) +} + +#[no_mangle] +pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsUpdateWord<'local>( + env: JNIEnv<'local>, + this: JObject<'local>, + uuid: JString<'local>, + word_json: JString<'local>, +) { + throw_if_err(env, (), |env| { + let internal = unsafe { + env.get_rust_field::<_, _, Arc>>(&this, "internal")? + .clone() + }; + + let uuid = env.get_string(&uuid)?; + let uuid = uuid.to_str()?.parse()?; + let word_json = env.get_string(&word_json)?; + let word_json = word_json.to_str()?; + + let word: voicevox_core::UserDictWord = serde_json::from_str(word_json)?; + + { + let mut internal = internal.lock().unwrap(); + internal.update_word(uuid, word)?; + }; + + Ok(()) + }) +} + +#[no_mangle] +pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsRemoveWord<'local>( + env: JNIEnv<'local>, + this: JObject<'local>, + uuid: JString<'local>, +) { + throw_if_err(env, (), |env| { + let internal = unsafe { + env.get_rust_field::<_, _, Arc>>(&this, "internal")? + .clone() + }; + + let uuid = env.get_string(&uuid)?; + let uuid = uuid.to_str()?.parse()?; + + { + let mut internal = internal.lock().unwrap(); + internal.remove_word(uuid)?; + }; + + Ok(()) + }) +} + +#[no_mangle] +pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsLoad<'local>( + env: JNIEnv<'local>, + this: JObject<'local>, + path: JString<'local>, +) { + throw_if_err(env, (), |env| { + let internal = unsafe { + env.get_rust_field::<_, _, Arc>>(&this, "internal")? + .clone() + }; + + let path = env.get_string(&path)?; + let path = path.to_str()?; + + { + let mut internal = internal.lock().unwrap(); + internal.load(path)?; + }; + + Ok(()) + }) +} + +#[no_mangle] +pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsSave<'local>( + env: JNIEnv<'local>, + this: JObject<'local>, + path: JString<'local>, +) { + throw_if_err(env, (), |env| { + let internal = unsafe { + env.get_rust_field::<_, _, Arc>>(&this, "internal")? + .clone() + }; + + let path = env.get_string(&path)?; + let path = path.to_str()?; + + { + let internal = internal.lock().unwrap(); + internal.save(path)?; + }; + + Ok(()) + }) +} + +#[no_mangle] +pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsGetWords<'local>( + env: JNIEnv<'local>, + this: JObject<'local>, +) -> jobject { + throw_if_err(env, std::ptr::null_mut(), |env| { + let internal = unsafe { + env.get_rust_field::<_, _, Arc>>(&this, "internal")? + .clone() + }; + + let words = { + let internal = internal.lock().unwrap(); + serde_json::to_string(internal.words())? + }; + + let words = env.new_string(words)?; + + Ok(words.into_raw()) + }) +} + +#[no_mangle] +pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsDrop<'local>( + env: JNIEnv<'local>, + this: JObject<'local>, +) { + throw_if_err(env, (), |env| { + let internal = + unsafe { env.get_rust_field::<_, _, voicevox_core::VoiceModel>(&this, "internal") }?; + drop(internal); + unsafe { env.take_rust_field(&this, "internal") }?; + Ok(()) + }) +} + +#[no_mangle] +pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsToZenkaku<'local>( + env: JNIEnv<'local>, + _cls: JClass<'local>, + text: JString<'local>, +) -> jobject { + throw_if_err(env, std::ptr::null_mut(), |env| { + let text = env.get_string(&text)?; + let text = text.to_str()?; + + let text = voicevox_core::to_zenkaku(text); + + let text = env.new_string(text)?; + Ok(text.into_raw()) + }) +} + +#[no_mangle] +pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsValidatePronunciation<'local>( + env: JNIEnv<'local>, + _cls: JClass<'local>, + text: JString<'local>, +) { + throw_if_err(env, (), |env| { + let text = env.get_string(&text)?; + let text = text.to_str()?; + + voicevox_core::validate_pronunciation(text)?; + + Ok(()) + }) +} diff --git a/crates/voicevox_core_java_api/src/voice_model.rs b/crates/voicevox_core_java_api/src/voice_model.rs index d569998ed..b09c17e2a 100644 --- a/crates/voicevox_core_java_api/src/voice_model.rs +++ b/crates/voicevox_core_java_api/src/voice_model.rs @@ -32,9 +32,9 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_VoiceModel_rsGetId<'local> ) -> jobject { throw_if_err(env, std::ptr::null_mut(), |env| { let internal = unsafe { - env.get_rust_field::<_, _, Arc>(&this, "internal") - }? - .clone(); + env.get_rust_field::<_, _, Arc>(&this, "internal")? + .clone() + }; let id = internal.id().raw_voice_model_id(); @@ -51,9 +51,10 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_VoiceModel_rsGetMetasJson< ) -> jobject { throw_if_err(env, std::ptr::null_mut(), |env| { let internal = unsafe { - env.get_rust_field::<_, _, Arc>(&this, "internal") - }? - .clone(); + env.get_rust_field::<_, _, Arc>(&this, "internal")? + .clone() + }; + let metas = internal.metas(); let metas_json = serde_json::to_string(&metas)?; Ok(env.new_string(metas_json)?.into_raw()) From da573e83f372649abfb27b95e491dfafcf7d7c21 Mon Sep 17 00:00:00 2001 From: sevenc-nanashi Date: Thu, 3 Aug 2023 10:00:09 +0900 Subject: [PATCH 19/99] =?UTF-8?q?Add:=20=E3=83=A6=E3=83=BC=E3=82=B6?= =?UTF-8?q?=E3=83=BC=E8=BE=9E=E6=9B=B8=E6=93=8D=E4=BD=9C=E3=81=AE=E3=83=86?= =?UTF-8?q?=E3=82=B9=E3=83=88=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Hiroshiba/VoicevoxCore/Synthesizer.java | 3 -- .../jp/Hiroshiba/VoicevoxCore/UserDict.java | 16 +++++++-- .../Hiroshiba/VoicevoxCore/UserDictTest.java | 35 +++++++++++++++++++ 3 files changed, 48 insertions(+), 6 deletions(-) diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Synthesizer.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Synthesizer.java index d9fddbcaf..295f8b0ad 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Synthesizer.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Synthesizer.java @@ -34,10 +34,7 @@ public AudioQuery audioQuery(String text, int styleId, EnumSet String queryJson = rsAudioQuery(text, styleId, kana); Gson gson = new Gson(); - System.out.println(queryJson); - AudioQuery audioQuery = gson.fromJson(queryJson, AudioQuery.class); - System.out.println(audioQuery); if (audioQuery == null) { throw new NullPointerException("audio_query"); } diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/UserDict.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/UserDict.java index 9c198d875..0a1784fd5 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/UserDict.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/UserDict.java @@ -10,6 +10,7 @@ import com.google.gson.Gson; import com.google.gson.annotations.Expose; import com.google.gson.annotations.SerializedName; +import com.google.gson.internal.LinkedTreeMap; public class UserDict implements AutoCloseable { @@ -51,10 +52,19 @@ public HashMap getWords() { String json = rsGetWords(); Gson gson = new Gson(); @SuppressWarnings("unchecked") - HashMap words = gson.fromJson(json, HashMap.class); - if (words == null) { + HashMap> rawWords = gson.fromJson(json, HashMap.class); + if (rawWords == null) { throw new NullPointerException("words"); } + HashMap words = new HashMap<>(); + rawWords.forEach((uuid, rawWord) -> { + Word word = gson.fromJson(gson.toJson(rawWord), Word.class); + if (word == null) { + throw new NullPointerException("word"); + } + words.put(uuid, word); + }); + return words; } @@ -112,7 +122,7 @@ public static class Word { @JsonProperty("priority") @SerializedName("priority") @Expose - @Min(1) + @Min(0) @Max(10) public int priority; diff --git a/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/UserDictTest.java b/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/UserDictTest.java index 21724a5a3..1dcad83f7 100644 --- a/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/UserDictTest.java +++ b/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/UserDictTest.java @@ -2,6 +2,8 @@ import static org.junit.jupiter.api.Assertions.assertTrue; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.EnumSet; import org.junit.jupiter.api.Test; @@ -9,6 +11,8 @@ class UserDictTest extends Utils { + // 辞書ロードのテスト。 + // 辞書ロード前後でkanaが異なることを確認する @Test void checkLoad() { try (VoiceModel model = loadModel(); @@ -29,4 +33,35 @@ void checkLoad() { } } + + // 辞書操作のテスト。 + @Test + void checkManipulation() + throws Exception { + try (UserDict userDict = new UserDict()) { + // 単語追加 + String uuid = userDict.addWord(new UserDict.Word("hoge", "ホゲ")); + assertTrue(userDict.getWords().get(uuid) != null); + + // 単語更新 + userDict.updateWord(uuid, new UserDict.Word("hoge", "ホゲホゲ")); + assertTrue(userDict.getWords().get(uuid).pronunciation.equals("ホゲホゲ")); + + // 単語削除 + userDict.removeWord(uuid); + assertTrue(userDict.getWords().get(uuid) == null); + + // 辞書エクスポート/インポート + Path path = Files.createTempFile("voicevox_user_dict", ".json"); + try ( + UserDict userDict2 = new UserDict()) { + userDict.save(path.toString()); + userDict2.load(path.toString()); + assertTrue(userDict2.getWords().size() == 0); + } finally { + Files.deleteIfExists(path); + } + + } + } } From f172d6ba94bf6f0446877223f16fed90f6f94ab6 Mon Sep 17 00:00:00 2001 From: sevenc-nanashi Date: Thu, 3 Aug 2023 10:11:09 +0900 Subject: [PATCH 20/99] =?UTF-8?q?Add:=20=E3=83=89=E3=82=AD=E3=83=A5?= =?UTF-8?q?=E3=83=A1=E3=83=B3=E3=83=88=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../jp/Hiroshiba/VoicevoxCore/UserDict.java | 48 +++++++++++++++++++ .../Hiroshiba/VoicevoxCore/UserDictTest.java | 13 ++++- .../voicevox_core_java_api/src/user_dict.rs | 31 +++++++++++- 3 files changed, 89 insertions(+), 3 deletions(-) diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/UserDict.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/UserDict.java index 0a1784fd5..33ca3f776 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/UserDict.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/UserDict.java @@ -12,14 +12,22 @@ import com.google.gson.annotations.SerializedName; import com.google.gson.internal.LinkedTreeMap; +/** ユーザー辞書。 */ public class UserDict implements AutoCloseable { protected long internal; + /** ユーザー辞書を作成する。 */ public UserDict() { rsNew(); } + /** + * 単語を追加する。 + * + * @param word 追加する単語。 + * @return 追加した単語のUUID。 + */ @Nonnull public String addWord(Word word) { Gson gson = new Gson(); @@ -28,6 +36,12 @@ public String addWord(Word word) { return rsAddWord(wordJson); } + /** + * 単語を更新する。 + * + * @param uuid 更新する単語のUUID。 + * @param word 新しい単語のデータ。 + */ public void updateWord(String uuid, Word word) { Gson gson = new Gson(); String wordJson = gson.toJson(word); @@ -35,18 +49,47 @@ public void updateWord(String uuid, Word word) { rsUpdateWord(uuid, wordJson); } + /** + * 単語を削除する。 + * + * @param uuid 削除する単語のUUID。 + */ public void removeWord(String uuid) { rsRemoveWord(uuid); } + /** + * ユーザー辞書をインポートする。 + * + * @param dict インポートするユーザー辞書。 + */ + public void importDict(UserDict dict) { + rsImportDict(dict); + } + + /** + * ユーザー辞書を読み込む。 + * + * @param path ユーザー辞書のパス。 + */ public void load(String path) { rsLoad(path); } + /** + * ユーザー辞書を保存する。 + * + * @param path ユーザー辞書のパス。 + */ public void save(String path) { rsSave(path); } + /** + * ユーザー辞書の単語を取得する。 + * + * @return ユーザー辞書の単語。 + */ @Nonnull public HashMap getWords() { String json = rsGetWords(); @@ -68,6 +111,9 @@ public HashMap getWords() { return words; } + /** + * ユーザー辞書を破棄する。 + */ public void close() { rsDrop(); } @@ -81,6 +127,8 @@ public void close() { private native void rsRemoveWord(String uuid); + private native void rsImportDict(UserDict dict); + private native void rsLoad(String path); private native void rsSave(String path); diff --git a/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/UserDictTest.java b/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/UserDictTest.java index 1dcad83f7..be1775d9f 100644 --- a/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/UserDictTest.java +++ b/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/UserDictTest.java @@ -51,13 +51,22 @@ void checkManipulation() userDict.removeWord(uuid); assertTrue(userDict.getWords().get(uuid) == null); - // 辞書エクスポート/インポート + // 辞書のインポート + userDict.addWord(new UserDict.Word("hoge", "ホゲ")); + try ( + UserDict userDict2 = new UserDict()) { + userDict2.addWord(new UserDict.Word("fuga", "フガ")); + userDict.importDict(userDict2); + assertTrue(userDict.getWords().size() == 2); + } + + // 辞書の保存/読み込み Path path = Files.createTempFile("voicevox_user_dict", ".json"); try ( UserDict userDict2 = new UserDict()) { userDict.save(path.toString()); userDict2.load(path.toString()); - assertTrue(userDict2.getWords().size() == 0); + assertTrue(userDict2.getWords().size() == 2); } finally { Files.deleteIfExists(path); } diff --git a/crates/voicevox_core_java_api/src/user_dict.rs b/crates/voicevox_core_java_api/src/user_dict.rs index 5a2e3b37e..aef24d2d9 100644 --- a/crates/voicevox_core_java_api/src/user_dict.rs +++ b/crates/voicevox_core_java_api/src/user_dict.rs @@ -104,6 +104,35 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsRemoveWord<'loc }) } +#[no_mangle] +pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsImportDict<'local>( + env: JNIEnv<'local>, + this: JObject<'local>, + other_dict: JObject<'local>, +) { + throw_if_err(env, (), |env| { + let internal = unsafe { + env.get_rust_field::<_, _, Arc>>(&this, "internal")? + .clone() + }; + let other_dict = unsafe { + env.get_rust_field::<_, _, Arc>>( + &other_dict, + "internal", + )? + .clone() + }; + + { + let mut internal = internal.lock().unwrap(); + let mut other_dict = other_dict.lock().unwrap(); + internal.import(&mut other_dict)?; + } + + Ok(()) + }) +} + #[no_mangle] pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsLoad<'local>( env: JNIEnv<'local>, @@ -215,7 +244,7 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsValidatePronunc let text = env.get_string(&text)?; let text = text.to_str()?; - voicevox_core::validate_pronunciation(text)?; + voicevox_core::validate_pronunciation(text)?; Ok(()) }) From a4187c8840b92ad7243063ef5a8fbb3e715c51c4 Mon Sep 17 00:00:00 2001 From: sevenc-nanashi Date: Thu, 3 Aug 2023 10:45:53 +0900 Subject: [PATCH 21/99] =?UTF-8?q?Add:=20=E3=83=89=E3=82=AD=E3=83=A5?= =?UTF-8?q?=E3=83=A1=E3=83=B3=E3=83=88=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Hiroshiba/VoicevoxCore/AccentPhrase.java | 5 + .../jp/Hiroshiba/VoicevoxCore/AudioQuery.java | 17 ++- .../java/jp/Hiroshiba/VoicevoxCore/Mora.java | 11 +- .../jp/Hiroshiba/VoicevoxCore/OpenJtalk.java | 18 ++- .../Hiroshiba/VoicevoxCore/Synthesizer.java | 104 ++++++++++++++++++ .../jp/Hiroshiba/VoicevoxCore/VoiceModel.java | 18 ++- .../VoicevoxCore/VoicevoxException.java | 1 + 7 files changed, 165 insertions(+), 9 deletions(-) diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/AccentPhrase.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/AccentPhrase.java index 3f35d9f43..2f758d3f4 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/AccentPhrase.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/AccentPhrase.java @@ -10,24 +10,29 @@ import com.google.gson.annotations.Expose; import com.google.gson.annotations.SerializedName; +/** AccentPhrase (アクセント句ごとの情報)。 */ public class AccentPhrase { + /** モーラの配列。 */ @JsonProperty("moras") @SerializedName("moras") @Expose @Nonnull public List moras; + /** アクセント箇所。 */ @JsonProperty("accent") @SerializedName("accent") @Expose public int accent; + /** 後ろに無音を付けるかどうか。 */ @JsonProperty("pause_mora") @SerializedName("pause_mora") @Expose @Nullable public Mora pauseMora; + /** 疑問系かどうか。 */ @JsonProperty("is_interrogative") @SerializedName("is_interrogative") @Expose diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/AudioQuery.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/AudioQuery.java index fa8ecc7a8..3b38ab728 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/AudioQuery.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/AudioQuery.java @@ -9,58 +9,73 @@ import com.google.gson.annotations.Expose; import com.google.gson.annotations.SerializedName; +/** AudioQuery (音声合成用のクエリ)。 */ public class AudioQuery { + /** アクセント句の配列。 */ @JsonProperty("accent_phrases") @SerializedName("accent_phrases") @Expose @Nonnull public List accentPhrases; + /** 全体の話速。 */ @JsonProperty("speed_scale") @SerializedName("speed_scale") @Expose public double speedScale; + /** 全体の音高。 */ @JsonProperty("pitch_scale") @SerializedName("pitch_scale") @Expose public double pitchScale; + /** 全体の抑揚。 */ @JsonProperty("intonation_scale") @SerializedName("intonation_scale") @Expose public double intonationScale; + /** 全体の音量。 */ @JsonProperty("volume_scale") @SerializedName("volume_scale") @Expose public double volumeScale; + /** 音声の前の無音時間。 */ @JsonProperty("pre_phoneme_length") @SerializedName("pre_phoneme_length") @Expose public double prePhonemeLength; + /** 音声の後の無音時間。 */ @JsonProperty("post_phoneme_length") @SerializedName("post_phoneme_length") @Expose public double postPhonemeLength; + /** 音声データの出力サンプリングレート。 */ @JsonProperty("output_sampling_rate") @SerializedName("output_sampling_rate") @Expose public int outputSamplingRate; + /** 音声データをステレオ出力するか否か。 */ @JsonProperty("output_stereo") @SerializedName("output_stereo") @Expose public boolean outputStereo; + /** + * [読み取り専用] AquesTalk風記法。 + * + * {@link Synthesizer#audioQuery} が返すもののみ ``str`` となる。入力としてのAudioQueryでは無視される。 + */ @JsonProperty("kana") @SerializedName("kana") @Expose @Nonnull - public String kana; + final public String kana; public AudioQuery() { this.accentPhrases = new ArrayList<>(); diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Mora.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Mora.java index 52ba99c0a..e1d26a30d 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Mora.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Mora.java @@ -7,7 +7,9 @@ import com.google.gson.annotations.Expose; import com.google.gson.annotations.SerializedName; +/** モーラ(子音+母音)ごとの情報。 */ public class Mora { + /** 文字。 */ @JsonProperty("text") @SerializedName("text") @Expose @@ -15,17 +17,20 @@ public class Mora { @SuppressWarnings("NullableProblems") public String text; + /** 子音の音素。 */ @JsonProperty("consonant") @SerializedName("consonant") @Expose @Nullable public String consonant; + /** 子音の音長。 */ @JsonProperty("consonant_length") @SerializedName("consonant_length") @Expose public java.lang.Double consonantLength; + /** 母音の音素。 */ @JsonProperty("vowel") @SerializedName("vowel") @Expose @@ -33,11 +38,13 @@ public class Mora { @SuppressWarnings("NullableProblems") public String vowel; + /** 母音の音長。 */ @JsonProperty("vowel_length") @SerializedName("vowel_length") @Expose public double vowelLength; + /** 音高。 */ @JsonProperty("pitch") @SerializedName("pitch") @Expose @@ -45,8 +52,8 @@ public class Mora { public Mora() { this.text = ""; - this.consonant = ""; - this.consonantLength = 0.0; + this.consonant = null; + this.consonantLength = null; this.vowel = ""; this.vowelLength = 0.0; this.pitch = 0.0; diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/OpenJtalk.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/OpenJtalk.java index 3c5121775..71c66454d 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/OpenJtalk.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/OpenJtalk.java @@ -1,20 +1,30 @@ package jp.Hiroshiba.VoicevoxCore; +/** テキスト解析器としてのOpen JTalk。 */ public class OpenJtalk implements AutoCloseable { protected long internal; - public OpenJtalk() { - rsNewWithoutDic(); - } - + /** + * Open JTalkの辞書ディレクトリ。 + * + * @param openJtalkDictDir 辞書のディレクトリ。 + */ public OpenJtalk(String openJtalkDictDir) { rsNewWithInitialize(openJtalkDictDir); } + /** + * ユーザー辞書を設定する。 + * + * この関数を呼び出した後にユーザー辞書を変更した場合は、再度この関数を呼ぶ必要がある。 + * + * @param userDict ユーザー辞書。 + */ public void useUserDict(UserDict userDict) { rsUseUserDict(userDict); } + /** Open JTalkを廃棄する。 */ public void close() { rsDrop(); } diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Synthesizer.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Synthesizer.java index 295f8b0ad..eefb06785 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Synthesizer.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Synthesizer.java @@ -9,6 +9,11 @@ import com.google.gson.Gson; +/** + * 音声シンセサイザ。 + * + * @see Synthesizer#builder + */ public class Synthesizer implements AutoCloseable { protected long internal; @@ -16,18 +21,43 @@ private Synthesizer(OpenJtalk openJtalk, SynthesizerBuilder builder) { rsNewWithInitialize(openJtalk, builder); } + /** + * モデルを読み込む。 + * + * @param voiceModel 読み込むモデル。 + */ public void loadVoiceModel(VoiceModel voiceModel) { rsLoadVoiceModel(voiceModel); } + /** + * 音声モデルの読み込みを解除する。 + * + * @param voiceModelId 読み込みを解除する音声モデルのID。 + */ public void unloadVoiceModel(String voiceModelId) { rsUnloadVoiceModel(voiceModelId); } + /** + * 指定した音声モデルのIDが読み込まれているかどうかを返す。 + * + * @param voiceModelId 音声モデルのID。 + * @return 指定した音声モデルのIDが読み込まれているかどうか。 + */ public boolean isLoadedVoiceModel(String voiceModelId) { return rsIsLoadedVoiceModel(voiceModelId); } + /** + * {@link AudioQuery} を生成する。 + * + * @param text テキスト。 + * @param styleId スタイルID。 + * @param options {@link AudioQueryOption} のセット。 + * + * @return 話者とテキストから生成された {@link AudioQuery}。 + */ @Nonnull public AudioQuery audioQuery(String text, int styleId, EnumSet options) { boolean kana = options.contains(AudioQueryOption.KANA); @@ -41,6 +71,15 @@ public AudioQuery audioQuery(String text, int styleId, EnumSet return audioQuery; } + /** + * {@link AccentPhrase} の配列を生成する。 + * + * @param text テキスト。 + * @param styleId スタイルID。 + * @param options {@link AudioQueryOption} のセット。 + * + * @return 話者とテキストから生成された {@link AccentPhrase} の配列。 + */ @Nonnull public List createAccentPhrases(String text, int styleId, EnumSet options) { boolean kana = options.contains(AccentPhrasesOption.KANA); @@ -53,6 +92,14 @@ public List createAccentPhrases(String text, int styleId, EnumSet< return new ArrayList<>(Arrays.asList(rawAccentPhrases)); } + /** + * アクセント句の音高・音素長を変更する。 + * + * @param accentPhrases 変更元のアクセント句の配列。 + * @param styleId スタイルID。 + * + * @return 変更後のアクセント句の配列。 + */ @Nonnull public List replaceMoraData(List accentPhrases, int styleId) { String accentPhrasesJson = new Gson().toJson(accentPhrases); @@ -60,6 +107,14 @@ public List replaceMoraData(List accentPhrases, int return new ArrayList<>(Arrays.asList(new Gson().fromJson(replacedAccentPhrasesJson, AccentPhrase[].class))); } + /** + * アクセント句の音素長を変更する。 + * + * @param accentPhrases 変更元のアクセント句の配列。 + * @param styleId スタイルID。 + * + * @return 変更後のアクセント句の配列。 + */ @Nonnull public List replacePhonemeLength(List accentPhrases, int styleId) { String accentPhrasesJson = new Gson().toJson(accentPhrases); @@ -67,6 +122,14 @@ public List replacePhonemeLength(List accentPhrases, return new ArrayList<>(Arrays.asList(new Gson().fromJson(replacedAccentPhrasesJson, AccentPhrase[].class))); } + /** + * アクセント句の音高を変更する。 + * + * @param accentPhrases 変更元のアクセント句の配列。 + * @param styleId スタイルID。 + * + * @return 変更後のアクセント句の配列。 + */ @Nonnull public List replaceMoraPitch(List accentPhrases, int styleId) { String accentPhrasesJson = new Gson().toJson(accentPhrases); @@ -74,6 +137,15 @@ public List replaceMoraPitch(List accentPhrases, int return new ArrayList<>(Arrays.asList(new Gson().fromJson(replacedAccentPhrasesJson, AccentPhrase[].class))); } + /** + * {@link AudioQuery} から音声合成する。 + * + * @param audioQuery {@link AudioQuery}。 + * @param styleId スタイルID。 + * @param options {@link SynthesisOption} のセット。 + * + * @return WAVデータ。 + */ @Nonnull public byte[] synthesis(AudioQuery audioQuery, int styleId, EnumSet options) { boolean enableInterrogativeUpspeak = options.contains(SynthesisOption.ENABLE_INTERROGATIVE_UPSPEAK); @@ -82,6 +154,15 @@ public byte[] synthesis(AudioQuery audioQuery, int styleId, EnumSet options) { boolean kana = options.contains(TtsOption.KANA); @@ -89,6 +170,9 @@ public byte[] tts(String text, int styleId, EnumSet options) { return rsTts(text, styleId, kana, enableInterrogativeUpspeak); } + /** + * 音声シンセサイザを破棄する。 + */ public void close() { rsDrop(); } @@ -132,6 +216,9 @@ public static SynthesizerBuilder builder(OpenJtalk openJtalk) { return new SynthesizerBuilder(openJtalk); } + /** + * 音声シンセサイザのビルダー。 + */ public static class SynthesizerBuilder { private OpenJtalk openJtalk; @SuppressWarnings("unused") @@ -145,47 +232,64 @@ public SynthesizerBuilder(OpenJtalk openJtalk) { this.openJtalk = openJtalk; } + /** ハードウェアアクセラレーションモードを設定する。 */ public SynthesizerBuilder accelerationMode(AccelerationMode accelerationMode) { this.accelerationMode = accelerationMode; return this; } + /** CPU利用数を指定。0を指定すると環境に合わせたCPUが利用される。 */ public SynthesizerBuilder cpuNumThreads(int cpuNumThreads) { this.cpuNumThreads = cpuNumThreads; return this; } + /** 全てのモデルを読み込むかどうか。 */ public SynthesizerBuilder loadAllModels(boolean loadAllModels) { this.loadAllModels = loadAllModels; return this; } + /** {@link Synthesizer} を構築する。 */ public Synthesizer build() { Synthesizer synthesizer = new Synthesizer(openJtalk, this); return synthesizer; } } + /** ハードウェアアクセラレーションモード。 */ public static enum AccelerationMode { + /** 実行環境に合わせて自動的に選択する。 */ AUTO, + /** CPUに設定する。 */ CPU, + /** GPUに設定する。 */ GPU, } + /** {@link Synthesizer#audioQuery} のオプション。 */ public static enum AudioQueryOption { + /** 入力テキストをAquesTalk風記法として解釈するかどうか。 */ KANA, } + /** {@link Synthesizer#accentPhrases} のオプション。 */ public static enum AccentPhrasesOption { + /** 入力テキストをAquesTalk風記法として解釈するかどうか。 */ KANA, } + /** {@link Synthesizer#synthesis} のオプション。 */ public static enum SynthesisOption { + /** 疑問文の調整を有効にするかどうか。 */ ENABLE_INTERROGATIVE_UPSPEAK } + /** {@link Synthesizer#tts} のオプション。 */ public static enum TtsOption { + /** 入力テキストをAquesTalk風記法として解釈するかどうか。 */ KANA, + /** 疑問文の調整を有効にするかどうか。 */ ENABLE_INTERROGATIVE_UPSPEAK } } diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/VoiceModel.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/VoiceModel.java index 4c6f28e21..5f30eb5a2 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/VoiceModel.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/VoiceModel.java @@ -7,12 +7,15 @@ import com.google.gson.annotations.Expose; import com.google.gson.annotations.SerializedName; +/** 音声モデル。 */ public class VoiceModel implements AutoCloseable { protected long internal; + /** ID。 */ @Nonnull final public String id; + /** メタ情報。 */ @Nonnull final public SpeakerMeta[] metas; @@ -29,6 +32,9 @@ public VoiceModel(String modelPath) { } + /** + * 音声モデルを廃棄する。 + */ public void close() { rsDrop(); } @@ -47,22 +53,27 @@ public void close() { System.loadLibrary("voicevox_core_java_api"); } + /** 話者(speaker)のメタ情報。 */ public static class SpeakerMeta { + /** 話者名。 */ @JsonProperty("name") @SerializedName("name") @Expose @Nonnull final String name; + /** 話者に属するスタイル。 */ @JsonProperty("styles") @SerializedName("styles") @Expose @Nonnull final StyleMeta[] styles; + /** 話者のUUID。 */ @JsonProperty("speaker_uuid") @SerializedName("speaker_uuid") @Expose @Nonnull final String speakerUuid; + /** 話者のバージョン。 */ @JsonProperty("version") @SerializedName("version") @Expose @@ -70,6 +81,8 @@ public static class SpeakerMeta { final String version; private SpeakerMeta() { + // GSONからコンストラクトするため、このメソッドは呼ばれることは無い。 + // このメソッドは@Nonnullを満たすために必要。 this.name = ""; this.styles = new StyleMeta[0]; this.speakerUuid = ""; @@ -77,20 +90,21 @@ private SpeakerMeta() { } } + /** スタイル(style)のメタ情報。 */ public static class StyleMeta { + /** スタイル名。 */ @JsonProperty("name") @SerializedName("name") @Expose @Nonnull final String name; + /** スタイルID。 */ @JsonProperty("id") @SerializedName("id") @Expose final int id; private StyleMeta() { - // GSONからコンストラクトするため、このメソッドは呼ばれることは無い。 - // このメソッドは@Nonnullを満たすために必要。 this.name = ""; this.id = 0; } diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/VoicevoxException.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/VoicevoxException.java index 8dfe8e8a7..c2049a822 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/VoicevoxException.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/VoicevoxException.java @@ -1,5 +1,6 @@ package jp.Hiroshiba.VoicevoxCore; +/** VOICEVOX COREのエラー。 */ public class VoicevoxException extends RuntimeException { public VoicevoxException(String message) { super(message); From 7a1a4c6c3b7bad6708d860790c1a3fb6c5f4bc22 Mon Sep 17 00:00:00 2001 From: sevenc-nanashi Date: Thu, 3 Aug 2023 10:53:34 +0900 Subject: [PATCH 22/99] =?UTF-8?q?Fix:=20=E3=82=B9=E3=82=B3=E3=83=BC?= =?UTF-8?q?=E3=83=97=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../jp/Hiroshiba/VoicevoxCore/OpenJtalk.java | 2 +- .../Hiroshiba/VoicevoxCore/Synthesizer.java | 31 +++++++++++++++---- .../jp/Hiroshiba/VoicevoxCore/UserDict.java | 2 +- .../jp/Hiroshiba/VoicevoxCore/VoiceModel.java | 2 +- 4 files changed, 28 insertions(+), 9 deletions(-) diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/OpenJtalk.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/OpenJtalk.java index 71c66454d..166c491c3 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/OpenJtalk.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/OpenJtalk.java @@ -2,7 +2,7 @@ /** テキスト解析器としてのOpen JTalk。 */ public class OpenJtalk implements AutoCloseable { - protected long internal; + long internal; /** * Open JTalkの辞書ディレクトリ。 diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Synthesizer.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Synthesizer.java index eefb06785..c725ad40e 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Synthesizer.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Synthesizer.java @@ -15,7 +15,7 @@ * @see Synthesizer#builder */ public class Synthesizer implements AutoCloseable { - protected long internal; + long internal; private Synthesizer(OpenJtalk openJtalk, SynthesizerBuilder builder) { rsNewWithInitialize(openJtalk, builder); @@ -232,25 +232,44 @@ public SynthesizerBuilder(OpenJtalk openJtalk) { this.openJtalk = openJtalk; } - /** ハードウェアアクセラレーションモードを設定する。 */ + /** + * ハードウェアアクセラレーションモードを設定する。 + * + * @param accelerationMode ハードウェアアクセラレーションモード。 + * @return ビルダー。 + */ public SynthesizerBuilder accelerationMode(AccelerationMode accelerationMode) { this.accelerationMode = accelerationMode; return this; } - /** CPU利用数を指定。0を指定すると環境に合わせたCPUが利用される。 */ + /** + * CPU利用数を指定する。0を指定すると環境に合わせたCPUが利用される。 + * + * @param cpuNumThreads CPU利用数。 + * @return ビルダー。 + */ public SynthesizerBuilder cpuNumThreads(int cpuNumThreads) { this.cpuNumThreads = cpuNumThreads; return this; } - /** 全てのモデルを読み込むかどうか。 */ + /** + * 全てのモデルを読み込むかどうか。 + * + * @param loadAllModels 全てのモデルを読み込むかどうか。 + * @return ビルダー。 + */ public SynthesizerBuilder loadAllModels(boolean loadAllModels) { this.loadAllModels = loadAllModels; return this; } - /** {@link Synthesizer} を構築する。 */ + /** + * {@link Synthesizer} を構築する。 + * + * @return {@link Synthesizer}。 + */ public Synthesizer build() { Synthesizer synthesizer = new Synthesizer(openJtalk, this); return synthesizer; @@ -273,7 +292,7 @@ public static enum AudioQueryOption { KANA, } - /** {@link Synthesizer#accentPhrases} のオプション。 */ + /** {@link Synthesizer#createAccentPhrases} のオプション。 */ public static enum AccentPhrasesOption { /** 入力テキストをAquesTalk風記法として解釈するかどうか。 */ KANA, diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/UserDict.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/UserDict.java index 33ca3f776..fbc003eef 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/UserDict.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/UserDict.java @@ -15,7 +15,7 @@ /** ユーザー辞書。 */ public class UserDict implements AutoCloseable { - protected long internal; + long internal; /** ユーザー辞書を作成する。 */ public UserDict() { diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/VoiceModel.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/VoiceModel.java index 5f30eb5a2..d2c25ee84 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/VoiceModel.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/VoiceModel.java @@ -10,7 +10,7 @@ /** 音声モデル。 */ public class VoiceModel implements AutoCloseable { - protected long internal; + long internal; /** ID。 */ @Nonnull From 263895006c4ee5a3e949dcc70f7cd522c2e66744 Mon Sep 17 00:00:00 2001 From: sevenc-nanashi Date: Thu, 3 Aug 2023 11:01:10 +0900 Subject: [PATCH 23/99] =?UTF-8?q?Fix:=20clippy=E3=81=AB=E5=BC=95=E3=81=A3?= =?UTF-8?q?=E3=81=8B=E3=81=8B=E3=81=A3=E3=81=A6=E3=81=84=E3=81=9F=E3=81=AE?= =?UTF-8?q?=E3=82=92=E4=BF=AE=E6=AD=A3=EF=BD=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crates/voicevox_core_java_api/src/user_dict.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/voicevox_core_java_api/src/user_dict.rs b/crates/voicevox_core_java_api/src/user_dict.rs index aef24d2d9..012db3e2f 100644 --- a/crates/voicevox_core_java_api/src/user_dict.rs +++ b/crates/voicevox_core_java_api/src/user_dict.rs @@ -125,8 +125,8 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsImportDict<'loc { let mut internal = internal.lock().unwrap(); - let mut other_dict = other_dict.lock().unwrap(); - internal.import(&mut other_dict)?; + let other_dict = other_dict.lock().unwrap(); + internal.import(&other_dict)?; } Ok(()) From 2480bc4f5f3df10255822b5551b6f731f536db8c Mon Sep 17 00:00:00 2001 From: sevenc-nanashi Date: Thu, 3 Aug 2023 11:14:20 +0900 Subject: [PATCH 24/99] =?UTF-8?q?Add:=20workflow=E3=82=92=E8=BF=BD?= =?UTF-8?q?=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/test.yml | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index bb609b0b7..8a5e29069 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -284,3 +284,34 @@ jobs: pip install -r requirements-test.txt pytest + build-and-test-java-api: + strategy: + fail-fast: false + matrix: + include: + - os: windows-latest + - os: macos-latest + - os: ubuntu-latest + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v3 + - name: Set up Rust + uses: ./.github/actions/rust-toolchain-from-File + - name: Set up Java + uses: actions/setup-java@v2 + with: + java-version: "8" + distribution: "adopt" + - name: Build + run: cargo build -p voicevox_core_java_api -vv + - name: 必要なDLLをコピーしてテストを実行 + working-directory: crates/voicevox_core_java_api + run: + cp -v ../../target/debug/build/onnxruntime-sys-*/out/onnxruntime_*/onnxruntime-*/lib/onnxruntime.dll . || true + cp -v ../../target/debug/build/onnxruntime-sys-*/out/onnxruntime_*/onnxruntime-*/lib/libonnxruntime.so.* . || true + cp -v ../../target/debug/build/onnxruntime-sys-*/out/onnxruntime_*/onnxruntime-*/lib/libonnxruntime.*.dylib . || true + export LD_LIBRARY_PATH="${{ github.workspace }}/target/debug:." + if [ "${{ matrix.os }}" = "windows-latest" ]; then + export PATH="$PATH;${LD_LIBRARY_PATH//:/;}" + fi + ./gradlew test From b8e42d92e9a2704d208f71203de06f494fc3d03c Mon Sep 17 00:00:00 2001 From: sevenc-nanashi Date: Thu, 3 Aug 2023 11:15:25 +0900 Subject: [PATCH 25/99] =?UTF-8?q?Fix:=20=E3=83=91=E3=82=A4=E3=83=97?= =?UTF-8?q?=E5=BF=98=E3=82=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 8a5e29069..9155ad3d6 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -306,7 +306,7 @@ jobs: run: cargo build -p voicevox_core_java_api -vv - name: 必要なDLLをコピーしてテストを実行 working-directory: crates/voicevox_core_java_api - run: + run: | cp -v ../../target/debug/build/onnxruntime-sys-*/out/onnxruntime_*/onnxruntime-*/lib/onnxruntime.dll . || true cp -v ../../target/debug/build/onnxruntime-sys-*/out/onnxruntime_*/onnxruntime-*/lib/libonnxruntime.so.* . || true cp -v ../../target/debug/build/onnxruntime-sys-*/out/onnxruntime_*/onnxruntime-*/lib/libonnxruntime.*.dylib . || true From 08fa0c8152c0ab134be5982b288c0cd428a3e8d3 Mon Sep 17 00:00:00 2001 From: sevenc-nanashi Date: Thu, 3 Aug 2023 12:05:10 +0900 Subject: [PATCH 26/99] Fix: Typo --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 9155ad3d6..81828022c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -296,7 +296,7 @@ jobs: steps: - uses: actions/checkout@v3 - name: Set up Rust - uses: ./.github/actions/rust-toolchain-from-File + uses: ./.github/actions/rust-toolchain-from-file - name: Set up Java uses: actions/setup-java@v2 with: From bfd93535b5cc7d3b05ba45ec17bbcfb817d167d4 Mon Sep 17 00:00:00 2001 From: sevenc-nanashi Date: Thu, 3 Aug 2023 12:14:27 +0900 Subject: [PATCH 27/99] =?UTF-8?q?Add:=20Info=E3=83=95=E3=83=A9=E3=82=B0?= =?UTF-8?q?=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/test.yml | 2 +- crates/voicevox_core_java_api/lib/build.gradle | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 81828022c..8d2de5769 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -314,4 +314,4 @@ jobs: if [ "${{ matrix.os }}" = "windows-latest" ]; then export PATH="$PATH;${LD_LIBRARY_PATH//:/;}" fi - ./gradlew test + ./gradlew test --info diff --git a/crates/voicevox_core_java_api/lib/build.gradle b/crates/voicevox_core_java_api/lib/build.gradle index 4b0c8db64..e100e9786 100644 --- a/crates/voicevox_core_java_api/lib/build.gradle +++ b/crates/voicevox_core_java_api/lib/build.gradle @@ -54,3 +54,5 @@ tasks.named('test') { // Use JUnit Platform for unit tests. useJUnitPlatform() } +compileJava.options.encoding = 'UTF-8' +compileTestJava.options.encoding = 'UTF-8' From 04f48f1a8426f2a0f3c53769fa936be45ede8be6 Mon Sep 17 00:00:00 2001 From: sevenc-nanashi Date: Thu, 3 Aug 2023 12:59:40 +0900 Subject: [PATCH 28/99] =?UTF-8?q?Fix:=20=E7=B5=B6=E5=AF=BE=E3=83=91?= =?UTF-8?q?=E3=82=B9=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/test.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 8d2de5769..ec27b9e81 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -310,8 +310,9 @@ jobs: cp -v ../../target/debug/build/onnxruntime-sys-*/out/onnxruntime_*/onnxruntime-*/lib/onnxruntime.dll . || true cp -v ../../target/debug/build/onnxruntime-sys-*/out/onnxruntime_*/onnxruntime-*/lib/libonnxruntime.so.* . || true cp -v ../../target/debug/build/onnxruntime-sys-*/out/onnxruntime_*/onnxruntime-*/lib/libonnxruntime.*.dylib . || true - export LD_LIBRARY_PATH="${{ github.workspace }}/target/debug:." if [ "${{ matrix.os }}" = "windows-latest" ]; then - export PATH="$PATH;${LD_LIBRARY_PATH//:/;}" + export PATH="$PATH;${{ github.workspace }}/target/debug;$(pwd)" + else + export LD_LIBRARY_PATH="${{ github.workspace }}/target/debug:$(pwd)" fi ./gradlew test --info From c4bb56f9f45bdfff27b930de580140b6d4a1eb34 Mon Sep 17 00:00:00 2001 From: sevenc-nanashi Date: Thu, 3 Aug 2023 13:09:48 +0900 Subject: [PATCH 29/99] =?UTF-8?q?Change:=20$PWD=E3=82=92=E4=BD=BF=E3=81=86?= =?UTF-8?q?=E7=94=A8=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/test.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index ec27b9e81..cef9f8b08 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -311,8 +311,8 @@ jobs: cp -v ../../target/debug/build/onnxruntime-sys-*/out/onnxruntime_*/onnxruntime-*/lib/libonnxruntime.so.* . || true cp -v ../../target/debug/build/onnxruntime-sys-*/out/onnxruntime_*/onnxruntime-*/lib/libonnxruntime.*.dylib . || true if [ "${{ matrix.os }}" = "windows-latest" ]; then - export PATH="$PATH;${{ github.workspace }}/target/debug;$(pwd)" + export PATH="$PATH;${{ github.workspace }}/target/debug;$PWD" else - export LD_LIBRARY_PATH="${{ github.workspace }}/target/debug:$(pwd)" + export LD_LIBRARY_PATH="${{ github.workspace }}/target/debug:$PWD" fi ./gradlew test --info From 45502d44542c43fd202f0e6adfde0a5d3bada676 Mon Sep 17 00:00:00 2001 From: sevenc-nanashi Date: Thu, 3 Aug 2023 13:10:21 +0900 Subject: [PATCH 30/99] =?UTF-8?q?Add:=20test=5Futil=E3=82=92=E3=82=B3?= =?UTF-8?q?=E3=83=B3=E3=83=91=E3=82=A4=E3=83=AB=E3=81=99=E3=82=8B=E3=82=88?= =?UTF-8?q?=E3=81=86=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cargo.lock | 1 + crates/voicevox_core_java_api/Cargo.toml | 3 +++ 2 files changed, 4 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index 992d6773e..e8eebdfbc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4157,6 +4157,7 @@ dependencies = [ "jni", "once_cell", "serde_json", + "test_util", "tokio", "tracing", "tracing-subscriber", diff --git a/crates/voicevox_core_java_api/Cargo.toml b/crates/voicevox_core_java_api/Cargo.toml index 358d5a399..25683377e 100644 --- a/crates/voicevox_core_java_api/Cargo.toml +++ b/crates/voicevox_core_java_api/Cargo.toml @@ -19,3 +19,6 @@ tokio.workspace = true tracing = { workspace = true, features = ["log"] } tracing-subscriber.workspace = true voicevox_core.workspace = true + +[dev-dependencies] +test_util.workspace = true From b86bcf56eb6f033273cbc403484c00314eaf0407 Mon Sep 17 00:00:00 2001 From: sevenc-nanashi Date: Thu, 3 Aug 2023 13:30:50 +0900 Subject: [PATCH 31/99] Change: Utils -> TestUtils --- .github/workflows/test.yml | 4 +++- .../test/java/jp/Hiroshiba/VoicevoxCore/SynthesizerTest.java | 2 +- .../jp/Hiroshiba/VoicevoxCore/{Utils.java => TestUtils.java} | 2 +- .../src/test/java/jp/Hiroshiba/VoicevoxCore/UserDictTest.java | 2 +- 4 files changed, 6 insertions(+), 4 deletions(-) rename crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/{Utils.java => TestUtils.java} (97%) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index cef9f8b08..1449aaba5 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -303,7 +303,9 @@ jobs: java-version: "8" distribution: "adopt" - name: Build - run: cargo build -p voicevox_core_java_api -vv + run: | + cargo build -p voicevox_core_java_api -vv + cargo build -p test_util -vv - name: 必要なDLLをコピーしてテストを実行 working-directory: crates/voicevox_core_java_api run: | 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 e7869313e..64ccc823b 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 @@ -13,7 +13,7 @@ import java.util.List; class SynthesizerTest - extends Utils { + extends TestUtilstils { @FunctionalInterface interface MoraCheckCallback { boolean check(Mora mora, Mora otherMora); diff --git a/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/Utils.java b/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/TestUtils.java similarity index 97% rename from crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/Utils.java rename to crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/TestUtils.java index 42cfd7474..3a1db9a92 100644 --- a/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/Utils.java +++ b/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/TestUtils.java @@ -2,7 +2,7 @@ import java.io.File; -class Utils { +class TestUtils { VoiceModel loadModel() { // cwdはvoicevox_core/crates/voicevox_core_java_api/lib String cwd = System.getProperty("user.dir"); diff --git a/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/UserDictTest.java b/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/UserDictTest.java index be1775d9f..bf66dd391 100644 --- a/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/UserDictTest.java +++ b/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/UserDictTest.java @@ -9,7 +9,7 @@ import org.junit.jupiter.api.Test; class UserDictTest - extends Utils { + extends TestUtilstils { // 辞書ロードのテスト。 // 辞書ロード前後でkanaが異なることを確認する From 348bdc20235ab93616fb335ee0376bd025375452 Mon Sep 17 00:00:00 2001 From: sevenc-nanashi Date: Thu, 3 Aug 2023 13:35:51 +0900 Subject: [PATCH 32/99] =?UTF-8?q?Fix:=20=E4=BA=8C=E9=87=8D=E5=A4=89?= =?UTF-8?q?=E6=9B=B4=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../test/java/jp/Hiroshiba/VoicevoxCore/SynthesizerTest.java | 2 +- .../src/test/java/jp/Hiroshiba/VoicevoxCore/UserDictTest.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) 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 64ccc823b..ed3a4b1c6 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 @@ -13,7 +13,7 @@ import java.util.List; class SynthesizerTest - extends TestUtilstils { + extends TestUtils { @FunctionalInterface interface MoraCheckCallback { boolean check(Mora mora, Mora otherMora); diff --git a/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/UserDictTest.java b/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/UserDictTest.java index bf66dd391..d606f34eb 100644 --- a/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/UserDictTest.java +++ b/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/UserDictTest.java @@ -9,7 +9,7 @@ import org.junit.jupiter.api.Test; class UserDictTest - extends TestUtilstils { + extends TestUtils { // 辞書ロードのテスト。 // 辞書ロード前後でkanaが異なることを確認する From 7d22f64e6fa0e61ea898b68e641801ee602c284a Mon Sep 17 00:00:00 2001 From: sevenc-nanashi Date: Thu, 3 Aug 2023 13:51:20 +0900 Subject: [PATCH 33/99] =?UTF-8?q?Add:=20DYLD=5FPATH=E3=82=92=E8=BF=BD?= =?UTF-8?q?=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/test.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 1449aaba5..8e573d873 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -313,7 +313,9 @@ jobs: cp -v ../../target/debug/build/onnxruntime-sys-*/out/onnxruntime_*/onnxruntime-*/lib/libonnxruntime.so.* . || true cp -v ../../target/debug/build/onnxruntime-sys-*/out/onnxruntime_*/onnxruntime-*/lib/libonnxruntime.*.dylib . || true if [ "${{ matrix.os }}" = "windows-latest" ]; then - export PATH="$PATH;${{ github.workspace }}/target/debug;$PWD" + export PATH="${{ github.workspace }}/target/debug;$PWD;$PATH" + elif [ "${{ matrix.os }}" = "macos-latest" ]; then + export DYLD_LIBRARY_PATH="${{ github.workspace }}/target/debug:$PWD" else export LD_LIBRARY_PATH="${{ github.workspace }}/target/debug:$PWD" fi From 4ceb4b5e7a169c7ef87de7de35a030397bfdc7d4 Mon Sep 17 00:00:00 2001 From: sevenc-nanashi Date: Thu, 3 Aug 2023 20:33:55 +0900 Subject: [PATCH 34/99] =?UTF-8?q?Add:=20javadoc=E3=81=AEworkflow=E3=82=92?= =?UTF-8?q?=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/generate_document.yml | 15 +++++++++++---- docs/apis/index.html | 1 + 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/.github/workflows/generate_document.yml b/.github/workflows/generate_document.yml index 40fc29c24..12e19efe3 100644 --- a/.github/workflows/generate_document.yml +++ b/.github/workflows/generate_document.yml @@ -20,6 +20,11 @@ jobs: uses: actions/setup-python@v4 with: python-version: "3.8" + - name: Setup Java + uses: actions/setup-java@v2 + with: + java-version: "8" + distribution: "adopt" - name: Install cargo-binstall uses: taiki-e/install-action@cargo-binstall - name: Create a venv @@ -42,10 +47,12 @@ jobs: maturin develop --manifest-path ./crates/voicevox_core_python_api/Cargo.toml --locked - name: Generate Sphinx document run: sphinx-build docs/apis/python_api public/apis/python_api - - name: Uplaod api document - uses: actions/upload-pages-artifact@v1 - with: - path: public + - name: Generate Javadoc + run: | + cd crates/voicevox_core_java_api + ./gradlew javadoc + cd ../.. + cp -r crates/voicevox_core_java_api/build/docs/javadoc public/apis/java_api deploy_api_github_pages: runs-on: ubuntu-latest needs: diff --git a/docs/apis/index.html b/docs/apis/index.html index 9b580db6c..639602f9f 100644 --- a/docs/apis/index.html +++ b/docs/apis/index.html @@ -8,6 +8,7 @@

From 6461932daaa88097194743c558789052db2b1542 Mon Sep 17 00:00:00 2001 From: sevenc-nanashi Date: Thu, 3 Aug 2023 20:37:37 +0900 Subject: [PATCH 35/99] =?UTF-8?q?Delete:=20Jackson=E3=82=B5=E3=83=9D?= =?UTF-8?q?=E3=83=BC=E3=83=88=E3=82=92=E5=89=8A=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crates/voicevox_core_java_api/lib/build.gradle | 9 --------- .../jp/Hiroshiba/VoicevoxCore/AccentPhrase.java | 5 ----- .../java/jp/Hiroshiba/VoicevoxCore/AudioQuery.java | 13 +------------ .../main/java/jp/Hiroshiba/VoicevoxCore/Mora.java | 7 ------- .../java/jp/Hiroshiba/VoicevoxCore/UserDict.java | 11 ----------- .../java/jp/Hiroshiba/VoicevoxCore/VoiceModel.java | 7 ------- 6 files changed, 1 insertion(+), 51 deletions(-) diff --git a/crates/voicevox_core_java_api/lib/build.gradle b/crates/voicevox_core_java_api/lib/build.gradle index e100e9786..ec507de7b 100644 --- a/crates/voicevox_core_java_api/lib/build.gradle +++ b/crates/voicevox_core_java_api/lib/build.gradle @@ -27,15 +27,6 @@ dependencies { // This dependency is used internally, and not exposed to consumers on their own compile classpath. implementation 'com.google.guava:guava:31.1-jre' - // https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core - implementation group: 'com.fasterxml.jackson.core', name: 'jackson-core', version: '2.13.0' - - // https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind - implementation group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.13.0' - - // https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations - implementation group: 'com.fasterxml.jackson.core', name: 'jackson-annotations', version: '2.13.0' - // https://mvnrepository.com/artifact/com.google.code.gson/gson implementation group: 'com.google.code.gson', name: 'gson', version: '2.10.1' diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/AccentPhrase.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/AccentPhrase.java index 2f758d3f4..96f3b4fed 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/AccentPhrase.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/AccentPhrase.java @@ -6,34 +6,29 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; -import com.fasterxml.jackson.annotation.JsonProperty; import com.google.gson.annotations.Expose; import com.google.gson.annotations.SerializedName; /** AccentPhrase (アクセント句ごとの情報)。 */ public class AccentPhrase { /** モーラの配列。 */ - @JsonProperty("moras") @SerializedName("moras") @Expose @Nonnull public List moras; /** アクセント箇所。 */ - @JsonProperty("accent") @SerializedName("accent") @Expose public int accent; /** 後ろに無音を付けるかどうか。 */ - @JsonProperty("pause_mora") @SerializedName("pause_mora") @Expose @Nullable public Mora pauseMora; /** 疑問系かどうか。 */ - @JsonProperty("is_interrogative") @SerializedName("is_interrogative") @Expose public boolean isInterrogative; diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/AudioQuery.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/AudioQuery.java index 3b38ab728..bc13c8239 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/AudioQuery.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/AudioQuery.java @@ -5,63 +5,53 @@ import javax.annotation.Nonnull; -import com.fasterxml.jackson.annotation.JsonProperty; import com.google.gson.annotations.Expose; import com.google.gson.annotations.SerializedName; /** AudioQuery (音声合成用のクエリ)。 */ public class AudioQuery { /** アクセント句の配列。 */ - @JsonProperty("accent_phrases") @SerializedName("accent_phrases") @Expose @Nonnull public List accentPhrases; /** 全体の話速。 */ - @JsonProperty("speed_scale") @SerializedName("speed_scale") @Expose public double speedScale; /** 全体の音高。 */ - @JsonProperty("pitch_scale") @SerializedName("pitch_scale") @Expose public double pitchScale; /** 全体の抑揚。 */ - @JsonProperty("intonation_scale") @SerializedName("intonation_scale") @Expose public double intonationScale; /** 全体の音量。 */ - @JsonProperty("volume_scale") @SerializedName("volume_scale") @Expose public double volumeScale; /** 音声の前の無音時間。 */ - @JsonProperty("pre_phoneme_length") @SerializedName("pre_phoneme_length") @Expose public double prePhonemeLength; /** 音声の後の無音時間。 */ - @JsonProperty("post_phoneme_length") @SerializedName("post_phoneme_length") @Expose public double postPhonemeLength; /** 音声データの出力サンプリングレート。 */ - @JsonProperty("output_sampling_rate") @SerializedName("output_sampling_rate") @Expose public int outputSamplingRate; /** 音声データをステレオ出力するか否か。 */ - @JsonProperty("output_stereo") @SerializedName("output_stereo") @Expose public boolean outputStereo; @@ -69,9 +59,8 @@ public class AudioQuery { /** * [読み取り専用] AquesTalk風記法。 * - * {@link Synthesizer#audioQuery} が返すもののみ ``str`` となる。入力としてのAudioQueryでは無視される。 + * {@link Synthesizer#audioQuery} が返すもののみ String となる。入力としてのAudioQueryでは無視される。 */ - @JsonProperty("kana") @SerializedName("kana") @Expose @Nonnull diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Mora.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Mora.java index e1d26a30d..66622b909 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Mora.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Mora.java @@ -3,14 +3,12 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; -import com.fasterxml.jackson.annotation.JsonProperty; import com.google.gson.annotations.Expose; import com.google.gson.annotations.SerializedName; /** モーラ(子音+母音)ごとの情報。 */ public class Mora { /** 文字。 */ - @JsonProperty("text") @SerializedName("text") @Expose @Nonnull @@ -18,20 +16,17 @@ public class Mora { public String text; /** 子音の音素。 */ - @JsonProperty("consonant") @SerializedName("consonant") @Expose @Nullable public String consonant; /** 子音の音長。 */ - @JsonProperty("consonant_length") @SerializedName("consonant_length") @Expose public java.lang.Double consonantLength; /** 母音の音素。 */ - @JsonProperty("vowel") @SerializedName("vowel") @Expose @Nonnull @@ -39,13 +34,11 @@ public class Mora { public String vowel; /** 母音の音長。 */ - @JsonProperty("vowel_length") @SerializedName("vowel_length") @Expose public double vowelLength; /** 音高。 */ - @JsonProperty("pitch") @SerializedName("pitch") @Expose public double pitch; diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/UserDict.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/UserDict.java index fbc003eef..9cbc9135b 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/UserDict.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/UserDict.java @@ -6,7 +6,6 @@ import jakarta.validation.constraints.Max; import jakarta.validation.constraints.Min; -import com.fasterxml.jackson.annotation.JsonProperty; import com.google.gson.Gson; import com.google.gson.annotations.Expose; import com.google.gson.annotations.SerializedName; @@ -144,30 +143,25 @@ public void close() { private static native void rsValidatePronunciation(String pronunciation); public static class Word { - @JsonProperty("surface") @SerializedName("surface") @Expose @Nonnull public String surface; - @JsonProperty("pronunciation") @SerializedName("pronunciation") @Expose @Nonnull public String pronunciation; - @JsonProperty("word_type") @SerializedName("word_type") @Expose @Nonnull public Type wordType; - @JsonProperty("accent_type") @SerializedName("accent_type") @Expose public int accentType; - @JsonProperty("priority") @SerializedName("priority") @Expose @Min(0) @@ -215,27 +209,22 @@ public Word priority(int priority) { } static enum Type { - @JsonProperty("PROPER_NOUN") @SerializedName("PROPER_NOUN") @Expose PROPER_NOUN, - @JsonProperty("COMMON_NOUN") @SerializedName("COMMON_NOUN") @Expose COMMON_NOUN, - @JsonProperty("VERB") @SerializedName("VERB") @Expose VERB, - @JsonProperty("ADJECTIVE") @SerializedName("ADJECTIVE") @Expose ADJECTIVE, - @JsonProperty("SUFFIX") @SerializedName("SUFFIX") @Expose SUFFIX, diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/VoiceModel.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/VoiceModel.java index d2c25ee84..2e4f05732 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/VoiceModel.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/VoiceModel.java @@ -2,7 +2,6 @@ import javax.annotation.Nonnull; -import com.fasterxml.jackson.annotation.JsonProperty; import com.google.gson.Gson; import com.google.gson.annotations.Expose; import com.google.gson.annotations.SerializedName; @@ -56,25 +55,21 @@ public void close() { /** 話者(speaker)のメタ情報。 */ public static class SpeakerMeta { /** 話者名。 */ - @JsonProperty("name") @SerializedName("name") @Expose @Nonnull final String name; /** 話者に属するスタイル。 */ - @JsonProperty("styles") @SerializedName("styles") @Expose @Nonnull final StyleMeta[] styles; /** 話者のUUID。 */ - @JsonProperty("speaker_uuid") @SerializedName("speaker_uuid") @Expose @Nonnull final String speakerUuid; /** 話者のバージョン。 */ - @JsonProperty("version") @SerializedName("version") @Expose @Nonnull @@ -93,13 +88,11 @@ private SpeakerMeta() { /** スタイル(style)のメタ情報。 */ public static class StyleMeta { /** スタイル名。 */ - @JsonProperty("name") @SerializedName("name") @Expose @Nonnull final String name; /** スタイルID。 */ - @JsonProperty("id") @SerializedName("id") @Expose final int id; From da74a88301b349a14b1e376d47c3ad7159aa543b Mon Sep 17 00:00:00 2001 From: sevenc-nanashi Date: Sat, 5 Aug 2023 08:20:29 +0900 Subject: [PATCH 36/99] =?UTF-8?q?Fix:=20generate=5Fdocument=E3=82=92?= =?UTF-8?q?=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/generate_document.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/generate_document.yml b/.github/workflows/generate_document.yml index 12e19efe3..846b610a7 100644 --- a/.github/workflows/generate_document.yml +++ b/.github/workflows/generate_document.yml @@ -52,7 +52,8 @@ jobs: cd crates/voicevox_core_java_api ./gradlew javadoc cd ../.. - cp -r crates/voicevox_core_java_api/build/docs/javadoc public/apis/java_api + mkdir -p public/apis/java_api + cp -r crates/voicevox_core_java_api/build/docs/javadoc/* public/apis/java_api deploy_api_github_pages: runs-on: ubuntu-latest needs: From 583a957d56cd3af72ad1588eb33e07e618e35235 Mon Sep 17 00:00:00 2001 From: sevenc-nanashi Date: Sat, 5 Aug 2023 08:22:26 +0900 Subject: [PATCH 37/99] =?UTF-8?q?Add:=20=E7=92=B0=E5=A2=83=E5=A4=89?= =?UTF-8?q?=E6=95=B0=E3=81=A7=E3=83=91=E3=82=B9=E3=82=92=E6=8C=87=E5=AE=9A?= =?UTF-8?q?=E3=81=A7=E3=81=8D=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/test.yml | 9 ++++++--- .../java/jp/Hiroshiba/VoicevoxCore/Dll.java | 17 +++++++++++++++++ .../jp/Hiroshiba/VoicevoxCore/OpenJtalk.java | 6 +----- .../jp/Hiroshiba/VoicevoxCore/Synthesizer.java | 6 +----- .../jp/Hiroshiba/VoicevoxCore/UserDict.java | 3 +-- .../jp/Hiroshiba/VoicevoxCore/VoiceModel.java | 7 +------ 6 files changed, 27 insertions(+), 21 deletions(-) create mode 100644 crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Dll.java diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 8e573d873..577d7fb0e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -313,10 +313,13 @@ jobs: cp -v ../../target/debug/build/onnxruntime-sys-*/out/onnxruntime_*/onnxruntime-*/lib/libonnxruntime.so.* . || true cp -v ../../target/debug/build/onnxruntime-sys-*/out/onnxruntime_*/onnxruntime-*/lib/libonnxruntime.*.dylib . || true if [ "${{ matrix.os }}" = "windows-latest" ]; then - export PATH="${{ github.workspace }}/target/debug;$PWD;$PATH" + export VV_DLL_PATH="${{ github.workspace }}/target/debug/voicevox_core_java_api.dll" + export ORT_DLL_PATH="$PWD/onnxruntime.dll" elif [ "${{ matrix.os }}" = "macos-latest" ]; then - export DYLD_LIBRARY_PATH="${{ github.workspace }}/target/debug:$PWD" + export VV_DLL_PATH="${{ github.workspace }}/target/debug/libvoicevox_core_java_api.dylib" + export ORT_DLL_PATH="$PWD/libonnxruntime.dylib" else - export LD_LIBRARY_PATH="${{ github.workspace }}/target/debug:$PWD" + export VV_DLL_PATH="${{ github.workspace }}/target/debug/libvoicevox_core_java_api.so" + export ORT_DLL_PATH="$PWD/libonnxruntime.so" fi ./gradlew test --info 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 new file mode 100644 index 000000000..f8b9693f4 --- /dev/null +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Dll.java @@ -0,0 +1,17 @@ +package jp.Hiroshiba.VoicevoxCore; + +/** ライブラリを読み込むためだけのクラス。 */ +abstract class Dll { + static { + String ortPath = System.getenv("ORT_DLL_PATH"); + if (ortPath != null) { + System.load(ortPath); + } + String vvDllPath = System.getenv("VV_DLL_PATH"); + if (vvDllPath != null) { + System.load(vvDllPath); + } else { + System.loadLibrary("voicevox_core_java_api"); + } + } +} diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/OpenJtalk.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/OpenJtalk.java index 166c491c3..211f7820d 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/OpenJtalk.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/OpenJtalk.java @@ -1,7 +1,7 @@ package jp.Hiroshiba.VoicevoxCore; /** テキスト解析器としてのOpen JTalk。 */ -public class OpenJtalk implements AutoCloseable { +public class OpenJtalk extends Dll implements AutoCloseable { long internal; /** @@ -36,8 +36,4 @@ public void close() { private native void rsUseUserDict(UserDict userDict); private native void rsDrop(); - - static { - System.loadLibrary("voicevox_core_java_api"); - } } diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Synthesizer.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Synthesizer.java index c725ad40e..7c2260672 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Synthesizer.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Synthesizer.java @@ -14,7 +14,7 @@ * * @see Synthesizer#builder */ -public class Synthesizer implements AutoCloseable { +public class Synthesizer extends Dll implements AutoCloseable { long internal; private Synthesizer(OpenJtalk openJtalk, SynthesizerBuilder builder) { @@ -208,10 +208,6 @@ public void close() { private native void rsDrop(); - static { - System.loadLibrary("voicevox_core_java_api"); - } - public static SynthesizerBuilder builder(OpenJtalk openJtalk) { return new SynthesizerBuilder(openJtalk); } diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/UserDict.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/UserDict.java index 9cbc9135b..728fe1939 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/UserDict.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/UserDict.java @@ -12,8 +12,7 @@ import com.google.gson.internal.LinkedTreeMap; /** ユーザー辞書。 */ -public class UserDict - implements AutoCloseable { +public class UserDict extends Dll implements AutoCloseable { long internal; /** ユーザー辞書を作成する。 */ diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/VoiceModel.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/VoiceModel.java index 2e4f05732..3e36d262e 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/VoiceModel.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/VoiceModel.java @@ -7,8 +7,7 @@ import com.google.gson.annotations.SerializedName; /** 音声モデル。 */ -public class VoiceModel - implements AutoCloseable { +public class VoiceModel extends Dll implements AutoCloseable { long internal; /** ID。 */ @@ -48,10 +47,6 @@ public void close() { private native void rsDrop(); - static { - System.loadLibrary("voicevox_core_java_api"); - } - /** 話者(speaker)のメタ情報。 */ public static class SpeakerMeta { /** 話者名。 */ From 3509323168d4ce880d0c5d7a6f2cac640ee415df Mon Sep 17 00:00:00 2001 From: sevenc-nanashi Date: Sat, 5 Aug 2023 09:59:46 +0900 Subject: [PATCH 38/99] =?UTF-8?q?Fix:=20onnxruntime=E3=81=AE=E5=90=8D?= =?UTF-8?q?=E5=89=8D=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/test.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 577d7fb0e..7c1ff5aa2 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -317,9 +317,11 @@ jobs: export ORT_DLL_PATH="$PWD/onnxruntime.dll" elif [ "${{ matrix.os }}" = "macos-latest" ]; then export VV_DLL_PATH="${{ github.workspace }}/target/debug/libvoicevox_core_java_api.dylib" - export ORT_DLL_PATH="$PWD/libonnxruntime.dylib" + ORT_NAME="$(ls "$PWD/libonnxruntime.*.dylib")" + export ORT_DLL_PATH="$PWD/$ORT_NAME" else export VV_DLL_PATH="${{ github.workspace }}/target/debug/libvoicevox_core_java_api.so" - export ORT_DLL_PATH="$PWD/libonnxruntime.so" + ORT_NAME="$(ls "$PWD/libonnxruntime.so.*")" + export ORT_DLL_PATH="$PWD/$ORT_NAME" fi ./gradlew test --info From 302742e90c641d3577041c2c80704e62e4a83784 Mon Sep 17 00:00:00 2001 From: Nanashi Date: Sat, 5 Aug 2023 13:36:32 +0900 Subject: [PATCH 39/99] =?UTF-8?q?Fix:=20=E3=83=91=E3=82=B9=E3=82=92?= =?UTF-8?q?=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/generate_document.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/generate_document.yml b/.github/workflows/generate_document.yml index 846b610a7..def11b9b6 100644 --- a/.github/workflows/generate_document.yml +++ b/.github/workflows/generate_document.yml @@ -53,7 +53,12 @@ jobs: ./gradlew javadoc cd ../.. mkdir -p public/apis/java_api - cp -r crates/voicevox_core_java_api/build/docs/javadoc/* public/apis/java_api + cp -r crates/voicevox_core_java_api/lib/build/docs/javadoc/* public/apis/java_api + - name: Uplaod api document + uses: actions/upload-pages-artifact@v1 + if: ${{ github.ref_name == 'main' }} + with: + path: public deploy_api_github_pages: runs-on: ubuntu-latest needs: From 1ce6ffbbdcf577d542b5e003a5f0c21c1bfe395d Mon Sep 17 00:00:00 2001 From: sevenc-nanashi Date: Sat, 5 Aug 2023 22:53:56 +0900 Subject: [PATCH 40/99] =?UTF-8?q?Fix:=20PWD=E3=82=92=E5=89=8A=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/test.yml | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 7c1ff5aa2..79be5c9a9 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -314,14 +314,13 @@ jobs: cp -v ../../target/debug/build/onnxruntime-sys-*/out/onnxruntime_*/onnxruntime-*/lib/libonnxruntime.*.dylib . || true if [ "${{ matrix.os }}" = "windows-latest" ]; then export VV_DLL_PATH="${{ github.workspace }}/target/debug/voicevox_core_java_api.dll" - export ORT_DLL_PATH="$PWD/onnxruntime.dll" + ORT_NAME="onnxruntime.dll" elif [ "${{ matrix.os }}" = "macos-latest" ]; then export VV_DLL_PATH="${{ github.workspace }}/target/debug/libvoicevox_core_java_api.dylib" - ORT_NAME="$(ls "$PWD/libonnxruntime.*.dylib")" - export ORT_DLL_PATH="$PWD/$ORT_NAME" + ORT_NAME="$(ls "./libonnxruntime.*.dylib")" else export VV_DLL_PATH="${{ github.workspace }}/target/debug/libvoicevox_core_java_api.so" - ORT_NAME="$(ls "$PWD/libonnxruntime.so.*")" - export ORT_DLL_PATH="$PWD/$ORT_NAME" + ORT_NAME="$(ls "./libonnxruntime.so.*")" fi + export ORT_DLL_PATH="$PWD/$ORT_NAME" ./gradlew test --info From 0f01fa8d0064ec274560cfb755fc68511afaf50a Mon Sep 17 00:00:00 2001 From: sevenc-nanashi Date: Sat, 5 Aug 2023 23:06:57 +0900 Subject: [PATCH 41/99] =?UTF-8?q?Fix:=20=E3=82=AF=E3=82=AA=E3=83=BC?= =?UTF-8?q?=E3=83=88=E3=82=92=E5=89=8A=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/test.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 79be5c9a9..85d70365a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -317,10 +317,10 @@ jobs: ORT_NAME="onnxruntime.dll" elif [ "${{ matrix.os }}" = "macos-latest" ]; then export VV_DLL_PATH="${{ github.workspace }}/target/debug/libvoicevox_core_java_api.dylib" - ORT_NAME="$(ls "./libonnxruntime.*.dylib")" + ORT_NAME="$(ls ./libonnxruntime.*.dylib)" else export VV_DLL_PATH="${{ github.workspace }}/target/debug/libvoicevox_core_java_api.so" - ORT_NAME="$(ls "./libonnxruntime.so.*")" + ORT_NAME="$(ls ./libonnxruntime.so.*)" fi export ORT_DLL_PATH="$PWD/$ORT_NAME" ./gradlew test --info From 136d1dd7d6c8ee2ce34c7ed526bcfa9193d0bc8f Mon Sep 17 00:00:00 2001 From: sevenc-nanashi Date: Sat, 5 Aug 2023 23:19:58 +0900 Subject: [PATCH 42/99] =?UTF-8?q?Add:=20=E3=83=89=E3=82=AD=E3=83=A5?= =?UTF-8?q?=E3=83=A1=E3=83=B3=E3=83=88=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Hiroshiba/VoicevoxCore/Synthesizer.java | 19 ++--- .../jp/Hiroshiba/VoicevoxCore/UserDict.java | 76 ++++++++++++++++++- 2 files changed, 85 insertions(+), 10 deletions(-) diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Synthesizer.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Synthesizer.java index 7c2260672..825dc7a88 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Synthesizer.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Synthesizer.java @@ -17,7 +17,7 @@ public class Synthesizer extends Dll implements AutoCloseable { long internal; - private Synthesizer(OpenJtalk openJtalk, SynthesizerBuilder builder) { + private Synthesizer(OpenJtalk openJtalk, Builder builder) { rsNewWithInitialize(openJtalk, builder); } @@ -177,7 +177,7 @@ public void close() { rsDrop(); } - private native void rsNewWithInitialize(OpenJtalk openJtalk, SynthesizerBuilder builder); + private native void rsNewWithInitialize(OpenJtalk openJtalk, Builder builder); private native void rsLoadVoiceModel(VoiceModel voiceModel); @@ -208,14 +208,15 @@ public void close() { private native void rsDrop(); - public static SynthesizerBuilder builder(OpenJtalk openJtalk) { - return new SynthesizerBuilder(openJtalk); + public static Builder builder(OpenJtalk openJtalk) { + return new Builder(openJtalk); } /** * 音声シンセサイザのビルダー。 + * @see Synthesizer#builder */ - public static class SynthesizerBuilder { + public static class Builder { private OpenJtalk openJtalk; @SuppressWarnings("unused") private AccelerationMode accelerationMode; @@ -224,7 +225,7 @@ public static class SynthesizerBuilder { @SuppressWarnings("unused") private boolean loadAllModels; - public SynthesizerBuilder(OpenJtalk openJtalk) { + public Builder(OpenJtalk openJtalk) { this.openJtalk = openJtalk; } @@ -234,7 +235,7 @@ public SynthesizerBuilder(OpenJtalk openJtalk) { * @param accelerationMode ハードウェアアクセラレーションモード。 * @return ビルダー。 */ - public SynthesizerBuilder accelerationMode(AccelerationMode accelerationMode) { + public Builder accelerationMode(AccelerationMode accelerationMode) { this.accelerationMode = accelerationMode; return this; } @@ -245,7 +246,7 @@ public SynthesizerBuilder accelerationMode(AccelerationMode accelerationMode) { * @param cpuNumThreads CPU利用数。 * @return ビルダー。 */ - public SynthesizerBuilder cpuNumThreads(int cpuNumThreads) { + public Builder cpuNumThreads(int cpuNumThreads) { this.cpuNumThreads = cpuNumThreads; return this; } @@ -256,7 +257,7 @@ public SynthesizerBuilder cpuNumThreads(int cpuNumThreads) { * @param loadAllModels 全てのモデルを読み込むかどうか。 * @return ビルダー。 */ - public SynthesizerBuilder loadAllModels(boolean loadAllModels) { + public Builder loadAllModels(boolean loadAllModels) { this.loadAllModels = loadAllModels; return this; } diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/UserDict.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/UserDict.java index 728fe1939..9e6e39ebe 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/UserDict.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/UserDict.java @@ -141,32 +141,65 @@ public void close() { private static native void rsValidatePronunciation(String pronunciation); + /** + * ユーザー辞書の単語。 + */ public static class Word { + /** + * 単語の表層形。 + */ @SerializedName("surface") @Expose @Nonnull public String surface; + /** + * 単語の発音。 + * 発音として有効なカタカナである必要がある。 + */ @SerializedName("pronunciation") @Expose @Nonnull public String pronunciation; + /** + * 単語の種類。 + * + * @see Type + */ @SerializedName("word_type") @Expose @Nonnull public Type wordType; + /** + * アクセント型。 + * 音が下がる場所を指す。 + */ @SerializedName("accent_type") @Expose public int accentType; + /** + * 単語の優先度。 + * 0から10までの整数。 + * 数字が大きいほど優先度が高くなる。 + * 1から9までの値を指定することを推奨。 + */ @SerializedName("priority") @Expose @Min(0) @Max(10) public int priority; + /** + * UserDict.Wordを作成する。 + * + * @param surface 言葉の表層形。 + * @param pronunciation 言葉の発音。 + * + * @throws IllegalArgumentException pronunciationが不正な場合。 + */ public Word(String surface, String pronunciation) { if (surface == null) { throw new NullPointerException("surface"); @@ -183,6 +216,13 @@ public Word(String surface, String pronunciation) { this.priority = 5; } + /** + * 単語の種類を設定する。 + * + * @param wordType 単語の種類。 + * + * @return このインスタンス。 + */ public Word wordType(Type wordType) { if (wordType == null) { throw new NullPointerException("wordType"); @@ -191,6 +231,13 @@ public Word wordType(Type wordType) { return this; } + /** + * アクセント型を設定する。 + * + * @param accentType アクセント型。 + * + * @return このインスタンス。 + */ public Word accentType(int accentType) { if (accentType < 0) { throw new IllegalArgumentException("accentType"); @@ -199,6 +246,15 @@ public Word accentType(int accentType) { return this; } + /** + * 優先度を設定する。 + * + * @param priority 優先度。 + * + * @return このインスタンス。 + * + * @throws IllegalArgumentException priorityが0未満または10より大きい場合。 + */ public Word priority(int priority) { if (priority < 0 || priority > 10) { throw new IllegalArgumentException("priority"); @@ -207,23 +263,41 @@ public Word priority(int priority) { return this; } - static enum Type { + /** + * 単語の種類。 + */ + public static enum Type { + /** + * 固有名詞。 + */ @SerializedName("PROPER_NOUN") @Expose PROPER_NOUN, + /** + * 一般名詞。 + */ @SerializedName("COMMON_NOUN") @Expose COMMON_NOUN, + /** + * 動詞。 + */ @SerializedName("VERB") @Expose VERB, + /** + * 形容詞。 + */ @SerializedName("ADJECTIVE") @Expose ADJECTIVE, + /** + * 語尾。 + */ @SerializedName("SUFFIX") @Expose SUFFIX, From 35d6e49ed23f121b9d31ff9d81a81cafe20e4843 Mon Sep 17 00:00:00 2001 From: sevenc-nanashi Date: Sat, 5 Aug 2023 23:21:57 +0900 Subject: [PATCH 43/99] =?UTF-8?q?Add:=20linguist-vendored=E3=82=92?= =?UTF-8?q?=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crates/voicevox_core_java_api/.gitattributes | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/crates/voicevox_core_java_api/.gitattributes b/crates/voicevox_core_java_api/.gitattributes index 097f9f98d..be5a92fef 100644 --- a/crates/voicevox_core_java_api/.gitattributes +++ b/crates/voicevox_core_java_api/.gitattributes @@ -2,8 +2,10 @@ # https://help.github.com/articles/dealing-with-line-endings/ # # Linux start script should use lf -/gradlew text eol=lf +/gradlew text eol=lf linguist-vendored # These are Windows script files and should use crlf *.bat text eol=crlf +./gradlew linguist-vendored +./gradlew.bat linguist-vendored From a9436326ca9e28e8b51523e130f6cf986b1cf784 Mon Sep 17 00:00:00 2001 From: sevenc-nanashi Date: Sat, 5 Aug 2023 23:41:54 +0900 Subject: [PATCH 44/99] =?UTF-8?q?Change:=20gitattributes=E3=82=92=E7=B5=B1?= =?UTF-8?q?=E5=90=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitattributes | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.gitattributes b/.gitattributes index 1d8371bff..033198ff4 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1 +1,9 @@ /crates/voicevox_core_c_api/include/voicevox_core.h linguist-generated=true + +# Java API +crates/voicevox_core_java_api/gradlew text eol=lf linguist-vendored + +crates/voicevox_core_java_api/**/*.bat text eol=crlf linguist-vendored + +crates/voicevox_core_java_api/gradlew linguist-vendored +crates/voicevox_core_java_api/gradlew.bat linguist-vendored From de16c9b7fcd443def4cc6a3dada279b05ee5a132 Mon Sep 17 00:00:00 2001 From: sevenc-nanashi Date: Sat, 5 Aug 2023 23:44:53 +0900 Subject: [PATCH 45/99] Revert: a9436326ca9e28e8b51523e130f6cf986b1cf784 --- .gitattributes | 8 -------- 1 file changed, 8 deletions(-) diff --git a/.gitattributes b/.gitattributes index 033198ff4..1d8371bff 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,9 +1 @@ /crates/voicevox_core_c_api/include/voicevox_core.h linguist-generated=true - -# Java API -crates/voicevox_core_java_api/gradlew text eol=lf linguist-vendored - -crates/voicevox_core_java_api/**/*.bat text eol=crlf linguist-vendored - -crates/voicevox_core_java_api/gradlew linguist-vendored -crates/voicevox_core_java_api/gradlew.bat linguist-vendored From 6676f4ed1fcbb9c1b35cf1cb16d0b1a599d10ad6 Mon Sep 17 00:00:00 2001 From: sevenc-nanashi Date: Thu, 10 Aug 2023 13:59:02 +0900 Subject: [PATCH 46/99] =?UTF-8?q?Add:=20linguist-generated=E3=82=92?= =?UTF-8?q?=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crates/voicevox_core_java_api/.gitattributes | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/voicevox_core_java_api/.gitattributes b/crates/voicevox_core_java_api/.gitattributes index be5a92fef..79f5b948c 100644 --- a/crates/voicevox_core_java_api/.gitattributes +++ b/crates/voicevox_core_java_api/.gitattributes @@ -2,10 +2,10 @@ # https://help.github.com/articles/dealing-with-line-endings/ # # Linux start script should use lf -/gradlew text eol=lf linguist-vendored +/gradlew text eol=lf linguist-vendored linguist-generated # These are Windows script files and should use crlf *.bat text eol=crlf -./gradlew linguist-vendored -./gradlew.bat linguist-vendored +./gradlew linguist-vendored linguist-generated +./gradlew.bat linguist-vendored linguist-generated From 93f932b8031a9ae93a81ab8a3f8f5a630cd6e1f8 Mon Sep 17 00:00:00 2001 From: sevenc-nanashi Date: Fri, 11 Aug 2023 15:56:55 +0900 Subject: [PATCH 47/99] =?UTF-8?q?Add:=20dll=E8=AA=AD=E3=81=BF=E8=BE=BC?= =?UTF-8?q?=E3=81=BF=E5=91=A8=E3=82=8A=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crates/voicevox_core_java_api/.gitignore | 5 ++ crates/voicevox_core_java_api/README.md | 75 +++++++++++++++++++ .../voicevox_core_java_api/lib/build.gradle | 5 ++ .../java/jp/Hiroshiba/VoicevoxCore/Dll.java | 75 +++++++++++++++++-- .../main/resources/dll/linux-arm64/.gitkeep | 0 .../src/main/resources/dll/linux-x64/.gitkeep | 0 .../src/main/resources/dll/mac-arm64/.gitkeep | 0 .../src/main/resources/dll/mac-x64/.gitkeep | 0 .../main/resources/dll/windows-x64/.gitkeep | 0 .../main/resources/jniLibs/arm64-x8a/.gitkeep | 0 .../main/resources/jniLibs/x86_64/.gitkeep | 0 11 files changed, 152 insertions(+), 8 deletions(-) create mode 100644 crates/voicevox_core_java_api/README.md create mode 100644 crates/voicevox_core_java_api/lib/src/main/resources/dll/linux-arm64/.gitkeep create mode 100644 crates/voicevox_core_java_api/lib/src/main/resources/dll/linux-x64/.gitkeep create mode 100644 crates/voicevox_core_java_api/lib/src/main/resources/dll/mac-arm64/.gitkeep create mode 100644 crates/voicevox_core_java_api/lib/src/main/resources/dll/mac-x64/.gitkeep create mode 100644 crates/voicevox_core_java_api/lib/src/main/resources/dll/windows-x64/.gitkeep create mode 100644 crates/voicevox_core_java_api/lib/src/main/resources/jniLibs/arm64-x8a/.gitkeep create mode 100644 crates/voicevox_core_java_api/lib/src/main/resources/jniLibs/x86_64/.gitkeep diff --git a/crates/voicevox_core_java_api/.gitignore b/crates/voicevox_core_java_api/.gitignore index 832d37e5b..eb1e8b3be 100644 --- a/crates/voicevox_core_java_api/.gitignore +++ b/crates/voicevox_core_java_api/.gitignore @@ -5,3 +5,8 @@ build !lib + +lib/src/main/resources/dll/* +!lib/src/main/resources/dll/**/.gitkeep +lib/src/main/resources/jniLibs/* +!lib/src/main/resources/jniLibs/**/.gitkeep diff --git a/crates/voicevox_core_java_api/README.md b/crates/voicevox_core_java_api/README.md new file mode 100644 index 000000000..7da5f4bd9 --- /dev/null +++ b/crates/voicevox_core_java_api/README.md @@ -0,0 +1,75 @@ +# voicevox_core_java_api + +VOICEVOX CORE の Java バインディング。 + +## 環境構築 + +以下の環境が必要です。 + +- Rustup +- Java 8 + +## ファイル構成 + +```yml +- README.md +- Cargo.toml # Rustプロジェクトとしてのマニフェストファイル。 +- lib: + - build.gradle # Gradle(Java)プロジェクトとしてのマニフェストファイル。 + - src: + - main: + - java: + - jp/Hiroshiba/VoicevoxCore: # Javaのソースコード。 + - Synthesizer.java + - ... + - resources: + - dll: # ライブラリ用のディレクトリ。詳細はDll.javaを参照。 + - windows-x64: + - voicevox_core.dll + - ... + - jniLibs: + - x86_64: + - ... +- src: # Rustのソースコード。jni-rsを使ってJavaとのバインディングを行う。 + - lib.rs + - ... +``` + +## ビルド(開発) + +バインディングは `cargo build` でビルドできます。 +Java プロジェクトを動かすには、`LD_LIBRARY_PATH`(等の環境変数)に `[プロジェクトルート]/target/debug(release)` を追加する必要があります。 + +```console +❯ cargo build +❯ LD_LIBRARY_PATH=/home/user/voicevox_core/target/debug gradle build + +# または +❯ cp ../../target/debug/libvoicevox_core_java_api.so lib/src/main/resources/dll/[target]/libvoicevox_core_java_api.so +❯ gradle build +``` + +## ビルド(リリース) + +`cargo build --release` でビルドできます。 + +```console +❯ cargo build --release +❯ cp ../../target/release/libvoicevox_core_java_api.so lib/src/main/resources/dll/[target]/libvoicevox_core_java_api.so +``` + +## テスト + +`gradle test` でテストできます。 + +```console +❯ gradle test +``` + +## ドキュメント + +`gradle javadoc` でドキュメントを生成できます。 + +```console +❯ gradle javadoc +``` diff --git a/crates/voicevox_core_java_api/lib/build.gradle b/crates/voicevox_core_java_api/lib/build.gradle index ec507de7b..c2afe0385 100644 --- a/crates/voicevox_core_java_api/lib/build.gradle +++ b/crates/voicevox_core_java_api/lib/build.gradle @@ -10,6 +10,8 @@ plugins { id 'java-library' } +version = '999.999.999' + repositories { // Use Maven Central for resolving dependencies. mavenCentral() @@ -32,6 +34,8 @@ 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' } // Apply a specific Java toolchain to ease working on different environments. @@ -45,5 +49,6 @@ tasks.named('test') { // Use JUnit Platform for unit tests. useJUnitPlatform() } + compileJava.options.encoding = 'UTF-8' compileTestJava.options.encoding = 'UTF-8' 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 f8b9693f4..aabf08e8c 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,17 +1,76 @@ package jp.Hiroshiba.VoicevoxCore; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +import ai.onnxruntime.OrtEnvironment; + /** ライブラリを読み込むためだけのクラス。 */ abstract class Dll { + // DLL を読み込む。 + // src/main/resources/dll/[target] 以下に DLL を配置する。 + // targetには以下のいずれかが入る: + // - win-x64 + // - mac-x64 + // - mac-arm64 + // - linux-x64 + // - linux-arm64 static { - String ortPath = System.getenv("ORT_DLL_PATH"); - if (ortPath != null) { - System.load(ortPath); - } - String vvDllPath = System.getenv("VV_DLL_PATH"); - if (vvDllPath != null) { - System.load(vvDllPath); - } else { + String runtimeName = System.getProperty("java.runtime.name"); + if (runtimeName.equals("Android Runtime")) { + // Android ではjniLibsから読み込む。 System.loadLibrary("voicevox_core_java_api"); + } else { + String rawOsName = System.getProperty("os.name"); + String rawOsArch = System.getProperty("os.arch"); + String osName, osArch, dllName; + if (rawOsName.startsWith("Win")) { + osName = "win"; + dllName = "voicevox_core_java_api.dll"; + } else if (rawOsName.startsWith("Mac")) { + osName = "mac"; + dllName = "libvoicevox_core_java_api.dylib"; + } else if (rawOsName.startsWith("Linux")) { + osName = "linux"; + dllName = "libvoicevox_core_java_api.so"; + } else { + throw new RuntimeException("Unsupported OS: " + rawOsName); + } + if (rawOsArch.equals("x86_64")) { + osArch = "x64"; + } else if (rawOsArch.equals("amd64")) { + osArch = "x64"; + } else if (rawOsArch.equals("aarch64")) { + osArch = "arm64"; + } else { + throw new RuntimeException("Unsupported OS architecture: " + rawOsArch); + } + + // ONNX Runtime の DLL を読み込む。 + OrtEnvironment.getEnvironment(); + try (InputStream in = Dll.class.getResourceAsStream("/dll/" + osName + "-" + osArch + "/" + dllName)) { + if (in == null) { + try { + // フォールバック。開発用。 + System.loadLibrary("voicevox_core_java_api"); + } catch (UnsatisfiedLinkError e) { + throw new RuntimeException("Failed to load Voicevox Core DLL", e); + } + } else { + Path tempDir = Paths.get(System.getProperty("java.io.tmpdir")); + tempDir = tempDir.resolve("voicevox_core_java_api"); + tempDir.toFile().mkdirs(); + 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 Voicevox Core DLL", e); + } } } } diff --git a/crates/voicevox_core_java_api/lib/src/main/resources/dll/linux-arm64/.gitkeep b/crates/voicevox_core_java_api/lib/src/main/resources/dll/linux-arm64/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/crates/voicevox_core_java_api/lib/src/main/resources/dll/linux-x64/.gitkeep b/crates/voicevox_core_java_api/lib/src/main/resources/dll/linux-x64/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/crates/voicevox_core_java_api/lib/src/main/resources/dll/mac-arm64/.gitkeep b/crates/voicevox_core_java_api/lib/src/main/resources/dll/mac-arm64/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/crates/voicevox_core_java_api/lib/src/main/resources/dll/mac-x64/.gitkeep b/crates/voicevox_core_java_api/lib/src/main/resources/dll/mac-x64/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/crates/voicevox_core_java_api/lib/src/main/resources/dll/windows-x64/.gitkeep b/crates/voicevox_core_java_api/lib/src/main/resources/dll/windows-x64/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/crates/voicevox_core_java_api/lib/src/main/resources/jniLibs/arm64-x8a/.gitkeep b/crates/voicevox_core_java_api/lib/src/main/resources/jniLibs/arm64-x8a/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/crates/voicevox_core_java_api/lib/src/main/resources/jniLibs/x86_64/.gitkeep b/crates/voicevox_core_java_api/lib/src/main/resources/jniLibs/x86_64/.gitkeep new file mode 100644 index 000000000..e69de29bb From 71e4768ae077d54af090a997c93bffaf459cc765 Mon Sep 17 00:00:00 2001 From: sevenc-nanashi Date: Fri, 11 Aug 2023 16:03:23 +0900 Subject: [PATCH 48/99] =?UTF-8?q?Fix:=20Action=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/test.yml | 64 +++++++++++++++++++------ crates/voicevox_core_java_api/README.md | 2 +- 2 files changed, 51 insertions(+), 15 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e8d7b58e5..e83270e35 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -306,18 +306,54 @@ jobs: - name: 必要なDLLをコピーしてテストを実行 working-directory: crates/voicevox_core_java_api run: | - cp -v ../../target/debug/build/onnxruntime-sys-*/out/onnxruntime_*/onnxruntime-*/lib/onnxruntime.dll . || true - cp -v ../../target/debug/build/onnxruntime-sys-*/out/onnxruntime_*/onnxruntime-*/lib/libonnxruntime.so.* . || true - cp -v ../../target/debug/build/onnxruntime-sys-*/out/onnxruntime_*/onnxruntime-*/lib/libonnxruntime.*.dylib . || true - if [ "${{ matrix.os }}" = "windows-latest" ]; then - export VV_DLL_PATH="${{ github.workspace }}/target/debug/voicevox_core_java_api.dll" - ORT_NAME="onnxruntime.dll" - elif [ "${{ matrix.os }}" = "macos-latest" ]; then - export VV_DLL_PATH="${{ github.workspace }}/target/debug/libvoicevox_core_java_api.dylib" - ORT_NAME="$(ls ./libonnxruntime.*.dylib)" - else - export VV_DLL_PATH="${{ github.workspace }}/target/debug/libvoicevox_core_java_api.so" - ORT_NAME="$(ls ./libonnxruntime.so.*)" - fi - export ORT_DLL_PATH="$PWD/$ORT_NAME" + ARCH="$(uname -m)" + case "${{ matrix.os }}" in + windows-latest) + DLL_NAME="voicevox_core.dll" + case "$ARCH" in + x86_64) + TARGET_NAME="windows-x64" + ;; + *) + echo "Unsupported architecture: $ARCH" + exit 1 + ;; + esac + ;; + macos-latest) + DLL_NAME="libvoicevox_core.dylib" + case "$ARCH" in + x86_64) + TARGET_NAME="macos-x64" + ;; + arm64) + TARGET_NAME="macos-arm64" + ;; + *) + echo "Unsupported architecture: $ARCH" + exit 1 + ;; + esac + ;; + ubuntu-latest) + DLL_NAME="libvoicevox_core.so" + case "$ARCH" in + x86_64) + TARGET_NAME="linux-x64" + ;; + aarch64) + TARGET_NAME="linux-arm64" + ;; + *) + echo "Unsupported architecture: $ARCH" + exit 1 + ;; + esac + ;; + *) + echo "Unsupported OS: ${{ matrix.os }}" + exit 1 + ;; + esac + cp -v ../../target/debug/$DLL_NAME ./lib/src/main/resources/dll/$TARGET_NAME/$DLL_NAME ./gradlew test --info diff --git a/crates/voicevox_core_java_api/README.md b/crates/voicevox_core_java_api/README.md index 7da5f4bd9..10679d85f 100644 --- a/crates/voicevox_core_java_api/README.md +++ b/crates/voicevox_core_java_api/README.md @@ -27,7 +27,7 @@ VOICEVOX CORE の Java バインディング。 - windows-x64: - voicevox_core.dll - ... - - jniLibs: + - jniLibs: # Android用のディレクトリ。 - x86_64: - ... - src: # Rustのソースコード。jni-rsを使ってJavaとのバインディングを行う。 From ff648875a6ca9221a4e82eeade963bc86977a370 Mon Sep 17 00:00:00 2001 From: sevenc-nanashi Date: Fri, 11 Aug 2023 16:08:47 +0900 Subject: [PATCH 49/99] =?UTF-8?q?Fix:=20DLL=5FNAME=E3=82=92=E4=BF=AE?= =?UTF-8?q?=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/test.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e83270e35..c656f44bb 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -309,7 +309,7 @@ jobs: ARCH="$(uname -m)" case "${{ matrix.os }}" in windows-latest) - DLL_NAME="voicevox_core.dll" + DLL_NAME="voicevox_core_java_api.dll" case "$ARCH" in x86_64) TARGET_NAME="windows-x64" @@ -321,7 +321,7 @@ jobs: esac ;; macos-latest) - DLL_NAME="libvoicevox_core.dylib" + DLL_NAME="libvoicevox_core_java_api.dylib" case "$ARCH" in x86_64) TARGET_NAME="macos-x64" @@ -336,7 +336,7 @@ jobs: esac ;; ubuntu-latest) - DLL_NAME="libvoicevox_core.so" + DLL_NAME="libvoicevox_core_java_api.so" case "$ARCH" in x86_64) TARGET_NAME="linux-x64" From 84c4468bee0d9622364551d0e824d8affca50c64 Mon Sep 17 00:00:00 2001 From: sevenc-nanashi Date: Fri, 11 Aug 2023 16:14:47 +0900 Subject: [PATCH 50/99] Fix: macos -> mac --- .github/workflows/test.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index c656f44bb..ccad6cfa4 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -324,10 +324,10 @@ jobs: DLL_NAME="libvoicevox_core_java_api.dylib" case "$ARCH" in x86_64) - TARGET_NAME="macos-x64" + TARGET_NAME="mac-x64" ;; arm64) - TARGET_NAME="macos-arm64" + TARGET_NAME="mac-arm64" ;; *) echo "Unsupported architecture: $ARCH" From 54ea5fc1270d330fe920474f8cad55eb4b2012ed Mon Sep 17 00:00:00 2001 From: sevenc-nanashi Date: Fri, 11 Aug 2023 16:26:27 +0900 Subject: [PATCH 51/99] =?UTF-8?q?Change:=20DLL=E3=81=AE=E8=AA=AC=E6=98=8E?= =?UTF-8?q?=E3=82=92=E7=A7=BB=E5=8B=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crates/voicevox_core_java_api/.gitignore | 8 +-- crates/voicevox_core_java_api/README.md | 49 +++++++++++++------ .../java/jp/Hiroshiba/VoicevoxCore/Dll.java | 12 ++--- 3 files changed, 41 insertions(+), 28 deletions(-) diff --git a/crates/voicevox_core_java_api/.gitignore b/crates/voicevox_core_java_api/.gitignore index eb1e8b3be..0c7fb6035 100644 --- a/crates/voicevox_core_java_api/.gitignore +++ b/crates/voicevox_core_java_api/.gitignore @@ -6,7 +6,7 @@ build !lib -lib/src/main/resources/dll/* -!lib/src/main/resources/dll/**/.gitkeep -lib/src/main/resources/jniLibs/* -!lib/src/main/resources/jniLibs/**/.gitkeep +lib/src/main/resources/dll/*/* +!lib/src/main/resources/dll/*/.gitkeep +lib/src/main/resources/jniLibs/*/* +!lib/src/main/resources/jniLibs/*/.gitkeep diff --git a/crates/voicevox_core_java_api/README.md b/crates/voicevox_core_java_api/README.md index 10679d85f..72a51d791 100644 --- a/crates/voicevox_core_java_api/README.md +++ b/crates/voicevox_core_java_api/README.md @@ -4,10 +4,10 @@ VOICEVOX CORE の Java バインディング。 ## 環境構築 -以下の環境が必要です。 +以下の環境が必要です: - Rustup -- Java 8 +- JDK 8 ## ファイル構成 @@ -17,19 +17,19 @@ VOICEVOX CORE の Java バインディング。 - lib: - build.gradle # Gradle(Java)プロジェクトとしてのマニフェストファイル。 - src: - - main: - - java: - - jp/Hiroshiba/VoicevoxCore: # Javaのソースコード。 - - Synthesizer.java - - ... - - resources: - - dll: # ライブラリ用のディレクトリ。詳細はDll.javaを参照。 - - windows-x64: - - voicevox_core.dll - - ... - - jniLibs: # Android用のディレクトリ。 - - x86_64: + - main: + - java: + - jp/Hiroshiba/VoicevoxCore: # Javaのソースコード。 + - Synthesizer.java - ... + - resources: + - dll: # ライブラリ用のディレクトリ。詳細はDll.javaを参照。 + - windows-x64: + - voicevox_core.dll + - ... + - jniLibs: # Android用のディレクトリ。 + - x86_64: + - ... - src: # Rustのソースコード。jni-rsを使ってJavaとのバインディングを行う。 - lib.rs - ... @@ -38,7 +38,12 @@ VOICEVOX CORE の Java バインディング。 ## ビルド(開発) バインディングは `cargo build` でビルドできます。 -Java プロジェクトを動かすには、`LD_LIBRARY_PATH`(等の環境変数)に `[プロジェクトルート]/target/debug(release)` を追加する必要があります。 +Java プロジェクトを動かすには、 + +- `LD_LIBRARY_PATH`などの環境変数に `[プロジェクトルート]/target/debug`(または`/release`) を追加するか、 +- `lib/src/main/resources/dll/[target]/libvoicevox_core_java_api.so` を作成する + +必要があります。 ```console ❯ cargo build @@ -73,3 +78,17 @@ Java プロジェクトを動かすには、`LD_LIBRARY_PATH`(等の環境変 ```console ❯ gradle javadoc ``` + +## DLL 読み込みについて + +Android では、jniLibs から System.loadLibrary で読み込みます。 + +Android 以外では、src/main/resources/dll 内の適切な DLL を一時ディレクトリにコピーし、System.load で読み込みます。 +DLL の名前は、 + +- Windows:voicevox_core_java_api.dll +- Linux:libvoicevox_core_java_api.so +- MacOS:libvoicevox_core_java_api.dylib + +になります。 +見付からなかった場合は、`System.loadLibrary` で読み込みます。これはデバッグ用です。 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 aabf08e8c..a82512fa4 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 @@ -9,14 +9,6 @@ /** ライブラリを読み込むためだけのクラス。 */ abstract class Dll { - // DLL を読み込む。 - // src/main/resources/dll/[target] 以下に DLL を配置する。 - // targetには以下のいずれかが入る: - // - win-x64 - // - mac-x64 - // - mac-arm64 - // - linux-x64 - // - linux-arm64 static { String runtimeName = System.getProperty("java.runtime.name"); if (runtimeName.equals("Android Runtime")) { @@ -38,7 +30,9 @@ abstract class Dll { } else { throw new RuntimeException("Unsupported OS: " + rawOsName); } - if (rawOsArch.equals("x86_64")) { + if (rawOsArch.equals("x86")) { + osArch = "x86"; + } else if (rawOsArch.equals("x86_64")) { osArch = "x64"; } else if (rawOsArch.equals("amd64")) { osArch = "x64"; From 722818ba567f822b0b9b77df69545d7706154ca2 Mon Sep 17 00:00:00 2001 From: sevenc-nanashi Date: Fri, 11 Aug 2023 16:26:35 +0900 Subject: [PATCH 52/99] =?UTF-8?q?Add:=20windows-x86=E3=82=92=E8=BF=BD?= =?UTF-8?q?=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lib/src/main/resources/dll/windows-x86/.gitkeep | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 crates/voicevox_core_java_api/lib/src/main/resources/dll/windows-x86/.gitkeep diff --git a/crates/voicevox_core_java_api/lib/src/main/resources/dll/windows-x86/.gitkeep b/crates/voicevox_core_java_api/lib/src/main/resources/dll/windows-x86/.gitkeep new file mode 100644 index 000000000..e69de29bb From 241ae7d6a405b90eed71c4ef58f0ef2a367508da Mon Sep 17 00:00:00 2001 From: sevenc-nanashi Date: Fri, 11 Aug 2023 16:31:26 +0900 Subject: [PATCH 53/99] =?UTF-8?q?Add:=20=E3=83=87=E3=83=90=E3=83=83?= =?UTF-8?q?=E3=82=B0=E8=A1=A8=E7=A4=BA=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/test.yml | 1 + .../lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Dll.java | 9 ++++----- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index ccad6cfa4..15283a9f3 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -356,4 +356,5 @@ jobs: ;; esac cp -v ../../target/debug/$DLL_NAME ./lib/src/main/resources/dll/$TARGET_NAME/$DLL_NAME + echo "target = $TARGET_NAME, dll = $DLL_NAME" ./gradlew test --info 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 a82512fa4..0934e4ceb 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 @@ -42,20 +42,19 @@ abstract class Dll { throw new RuntimeException("Unsupported OS architecture: " + rawOsArch); } + String target = osName + "-" + osArch; // ONNX Runtime の DLL を読み込む。 OrtEnvironment.getEnvironment(); - try (InputStream in = Dll.class.getResourceAsStream("/dll/" + osName + "-" + osArch + "/" + dllName)) { + 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", e); + throw new RuntimeException("Failed to load Voicevox Core DLL for " + target, e); } } else { Path tempDir = Paths.get(System.getProperty("java.io.tmpdir")); - tempDir = tempDir.resolve("voicevox_core_java_api"); - tempDir.toFile().mkdirs(); Path dllPath = tempDir.resolve(dllName); dllPath.toFile().deleteOnExit(); Files.copy(in, dllPath); @@ -63,7 +62,7 @@ abstract class Dll { System.load(dllPath.toAbsolutePath().toString()); } } catch (Exception e) { - throw new RuntimeException("Failed to load Voicevox Core DLL", e); + throw new RuntimeException("Failed to load Voicevox Core DLL for " + target, e); } } } From 33322c523dec83c6e4d2fd8b18c8bcc28660c376 Mon Sep 17 00:00:00 2001 From: Nanashi Date: Fri, 11 Aug 2023 16:43:38 +0900 Subject: [PATCH 54/99] Fix: gradle -> gradlew --- crates/voicevox_core_java_api/README.md | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/crates/voicevox_core_java_api/README.md b/crates/voicevox_core_java_api/README.md index 72a51d791..66b40dc62 100644 --- a/crates/voicevox_core_java_api/README.md +++ b/crates/voicevox_core_java_api/README.md @@ -47,36 +47,38 @@ Java プロジェクトを動かすには、 ```console ❯ cargo build -❯ LD_LIBRARY_PATH=/home/user/voicevox_core/target/debug gradle build +❯ LD_LIBRARY_PATH=/home/user/voicevox_core/target/debug ./gradlew build # または ❯ cp ../../target/debug/libvoicevox_core_java_api.so lib/src/main/resources/dll/[target]/libvoicevox_core_java_api.so -❯ gradle build +❯ ./gradlew build ``` ## ビルド(リリース) -`cargo build --release` でビルドできます。 +`cargo build --release` でRust側を、`./gradlew build` でJava側をビルドできます。 +パッケージ化する時はlib/src/main/resources/dll内にdllをコピーしてください。 ```console ❯ cargo build --release ❯ cp ../../target/release/libvoicevox_core_java_api.so lib/src/main/resources/dll/[target]/libvoicevox_core_java_api.so +❯ ./gradlew build ``` ## テスト -`gradle test` でテストできます。 +`./gradlew test` でテストできます。 ```console -❯ gradle test +❯ ./gradlew test ``` ## ドキュメント -`gradle javadoc` でドキュメントを生成できます。 +`./gradlew javadoc` でドキュメントを生成できます。 ```console -❯ gradle javadoc +❯ ./gradlew javadoc ``` ## DLL 読み込みについて From 2064fed3371e26e9e7b5da8e999148e732db4ef4 Mon Sep 17 00:00:00 2001 From: Nanashi Date: Fri, 11 Aug 2023 16:46:46 +0900 Subject: [PATCH 55/99] Fix: win -> windows --- .../lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Dll.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 0934e4ceb..dc0efa6bd 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 @@ -19,7 +19,7 @@ abstract class Dll { String rawOsArch = System.getProperty("os.arch"); String osName, osArch, dllName; if (rawOsName.startsWith("Win")) { - osName = "win"; + osName = "windows"; dllName = "voicevox_core_java_api.dll"; } else if (rawOsName.startsWith("Mac")) { osName = "mac"; From ad080c46e32a54ba22440fbbfdf8ff82d5cbaf07 Mon Sep 17 00:00:00 2001 From: sevenc-nanashi Date: Sun, 13 Aug 2023 08:07:48 +0900 Subject: [PATCH 56/99] Change: close -> finalize --- .../jp/Hiroshiba/VoicevoxCore/OpenJtalk.java | 5 +- .../Hiroshiba/VoicevoxCore/Synthesizer.java | 5 +- .../jp/Hiroshiba/VoicevoxCore/UserDict.java | 5 +- .../jp/Hiroshiba/VoicevoxCore/VoiceModel.java | 5 +- .../jp/Hiroshiba/VoicevoxCore/MetaTest.java | 6 +- .../VoicevoxCore/SynthesizerTest.java | 70 +++++++-------- .../Hiroshiba/VoicevoxCore/UserDictTest.java | 86 +++++++++---------- 7 files changed, 90 insertions(+), 92 deletions(-) diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/OpenJtalk.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/OpenJtalk.java index 211f7820d..93e894eb0 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/OpenJtalk.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/OpenJtalk.java @@ -1,7 +1,7 @@ package jp.Hiroshiba.VoicevoxCore; /** テキスト解析器としてのOpen JTalk。 */ -public class OpenJtalk extends Dll implements AutoCloseable { +public class OpenJtalk extends Dll { long internal; /** @@ -25,7 +25,8 @@ public void useUserDict(UserDict userDict) { } /** Open JTalkを廃棄する。 */ - public void close() { + @Override + protected void finalize() { rsDrop(); } diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Synthesizer.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Synthesizer.java index 825dc7a88..92798a80d 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Synthesizer.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Synthesizer.java @@ -14,7 +14,7 @@ * * @see Synthesizer#builder */ -public class Synthesizer extends Dll implements AutoCloseable { +public class Synthesizer extends Dll { long internal; private Synthesizer(OpenJtalk openJtalk, Builder builder) { @@ -173,7 +173,8 @@ public byte[] tts(String text, int styleId, EnumSet options) { /** * 音声シンセサイザを破棄する。 */ - public void close() { + @Override + protected void finalize() { rsDrop(); } diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/UserDict.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/UserDict.java index 9e6e39ebe..2aa6e369c 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/UserDict.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/UserDict.java @@ -12,7 +12,7 @@ import com.google.gson.internal.LinkedTreeMap; /** ユーザー辞書。 */ -public class UserDict extends Dll implements AutoCloseable { +public class UserDict extends Dll { long internal; /** ユーザー辞書を作成する。 */ @@ -112,7 +112,8 @@ public HashMap getWords() { /** * ユーザー辞書を破棄する。 */ - public void close() { + @Override + protected void finalize() { rsDrop(); } diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/VoiceModel.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/VoiceModel.java index 3e36d262e..8561b7010 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/VoiceModel.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/VoiceModel.java @@ -7,7 +7,7 @@ import com.google.gson.annotations.SerializedName; /** 音声モデル。 */ -public class VoiceModel extends Dll implements AutoCloseable { +public class VoiceModel extends Dll { long internal; /** ID。 */ @@ -33,7 +33,8 @@ public VoiceModel(String modelPath) { /** * 音声モデルを廃棄する。 */ - public void close() { + @Override + protected void finalize() { rsDrop(); } diff --git a/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/MetaTest.java b/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/MetaTest.java index c92b2b06d..d4a3f2740 100644 --- a/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/MetaTest.java +++ b/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/MetaTest.java @@ -5,6 +5,8 @@ import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertNotNull; + import java.io.File; class MetaTest { @@ -14,7 +16,7 @@ void checkLoad() { String cwd = System.getProperty("user.dir"); File path = new File( cwd + "/../../../model/sample.vvm"); - try (VoiceModel model = new VoiceModel(path.getAbsolutePath())) { - } + VoiceModel model = new VoiceModel(path.getAbsolutePath()); + assertNotNull(model.metas); } } 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 ed3a4b1c6..2b35b062f 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 @@ -38,56 +38,52 @@ boolean checkAllMoras( @Test void checkModel() { - try (VoiceModel model = loadModel(); - OpenJtalk openJtalk = loadOpenJtalk(); - Synthesizer synthesizer = Synthesizer.builder(openJtalk).build()) { - synthesizer.loadVoiceModel(model); - assertTrue(synthesizer.isLoadedVoiceModel(model.id)); - synthesizer.unloadVoiceModel(model.id); - assertFalse(synthesizer.isLoadedVoiceModel(model.id)); - } + VoiceModel model = loadModel(); + OpenJtalk openJtalk = loadOpenJtalk(); + Synthesizer synthesizer = Synthesizer.builder(openJtalk).build(); + synthesizer.loadVoiceModel(model); + assertTrue(synthesizer.isLoadedVoiceModel(model.id)); + synthesizer.unloadVoiceModel(model.id); + assertFalse(synthesizer.isLoadedVoiceModel(model.id)); } @Test void checkAudioQuery() { - try (VoiceModel model = loadModel(); - OpenJtalk openJtalk = loadOpenJtalk(); - Synthesizer synthesizer = Synthesizer.builder(openJtalk).build()) { - synthesizer.loadVoiceModel(model); - AudioQuery query = synthesizer.audioQuery("こんにちは", model.metas[0].styles[0].id, - EnumSet.noneOf(Synthesizer.AudioQueryOption.class)); + VoiceModel model = loadModel(); + OpenJtalk openJtalk = loadOpenJtalk(); + Synthesizer synthesizer = Synthesizer.builder(openJtalk).build(); + synthesizer.loadVoiceModel(model); + AudioQuery query = synthesizer.audioQuery("こんにちは", model.metas[0].styles[0].id, + EnumSet.noneOf(Synthesizer.AudioQueryOption.class)); - synthesizer.synthesis(query, model.metas[0].styles[0].id, EnumSet.noneOf(Synthesizer.SynthesisOption.class)); - } + synthesizer.synthesis(query, model.metas[0].styles[0].id, EnumSet.noneOf(Synthesizer.SynthesisOption.class)); } @Test void checkAccentPhrases() { - try (VoiceModel model = loadModel(); - OpenJtalk openJtalk = loadOpenJtalk(); - Synthesizer synthesizer = Synthesizer.builder(openJtalk).build()) { - synthesizer.loadVoiceModel(model); - List accentPhrases = synthesizer.createAccentPhrases("こんにちは", model.metas[0].styles[0].id, - EnumSet.noneOf(Synthesizer.AccentPhrasesOption.class)); - List accentPhrases2 = synthesizer.replaceMoraPitch(accentPhrases, model.metas[1].styles[0].id); - assertTrue(checkAllMoras(accentPhrases, accentPhrases2, (mora, otherMora) -> mora.pitch != otherMora.pitch)); - List accentPhrases3 = synthesizer.replacePhonemeLength(accentPhrases, model.metas[1].styles[0].id); - assertTrue( - checkAllMoras(accentPhrases, accentPhrases3, (mora, otherMora) -> mora.vowelLength != otherMora.vowelLength)); - List accentPhrases4 = synthesizer.replaceMoraData(accentPhrases, model.metas[1].styles[0].id); - assertTrue(checkAllMoras(accentPhrases, accentPhrases4, - (mora, otherMora) -> mora.pitch != otherMora.pitch && mora.vowelLength != otherMora.vowelLength)); + VoiceModel model = loadModel(); + OpenJtalk openJtalk = loadOpenJtalk(); + Synthesizer synthesizer = Synthesizer.builder(openJtalk).build(); + synthesizer.loadVoiceModel(model); + List accentPhrases = synthesizer.createAccentPhrases("こんにちは", model.metas[0].styles[0].id, + EnumSet.noneOf(Synthesizer.AccentPhrasesOption.class)); + List accentPhrases2 = synthesizer.replaceMoraPitch(accentPhrases, model.metas[1].styles[0].id); + assertTrue(checkAllMoras(accentPhrases, accentPhrases2, (mora, otherMora) -> mora.pitch != otherMora.pitch)); + List accentPhrases3 = synthesizer.replacePhonemeLength(accentPhrases, model.metas[1].styles[0].id); + assertTrue( + checkAllMoras(accentPhrases, accentPhrases3, (mora, otherMora) -> mora.vowelLength != otherMora.vowelLength)); + List accentPhrases4 = synthesizer.replaceMoraData(accentPhrases, model.metas[1].styles[0].id); + assertTrue(checkAllMoras(accentPhrases, accentPhrases4, + (mora, otherMora) -> mora.pitch != otherMora.pitch && mora.vowelLength != otherMora.vowelLength)); - } } @Test void checkTts() { - try (VoiceModel model = loadModel(); - OpenJtalk openJtalk = loadOpenJtalk(); - Synthesizer synthesizer = Synthesizer.builder(openJtalk).build()) { - synthesizer.loadVoiceModel(model); - synthesizer.tts("こんにちは", model.metas[0].styles[0].id, EnumSet.noneOf(Synthesizer.TtsOption.class)); - } + VoiceModel model = loadModel(); + OpenJtalk openJtalk = loadOpenJtalk(); + Synthesizer synthesizer = Synthesizer.builder(openJtalk).build(); + synthesizer.loadVoiceModel(model); + synthesizer.tts("こんにちは", model.metas[0].styles[0].id, EnumSet.noneOf(Synthesizer.TtsOption.class)); } } diff --git a/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/UserDictTest.java b/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/UserDictTest.java index d606f34eb..597ef89b6 100644 --- a/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/UserDictTest.java +++ b/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/UserDictTest.java @@ -15,62 +15,58 @@ class UserDictTest // 辞書ロード前後でkanaが異なることを確認する @Test void checkLoad() { - try (VoiceModel model = loadModel(); - OpenJtalk openJtalk = loadOpenJtalk(); - Synthesizer synthesizer = Synthesizer.builder(openJtalk).build(); - UserDict userDict = new UserDict()) { - synthesizer.loadVoiceModel(model); - AudioQuery query1 = synthesizer.audioQuery("this_word_should_not_exist_in_default_dictionary", - model.metas[0].styles[0].id, - EnumSet.noneOf(Synthesizer.AudioQueryOption.class)); - userDict.addWord( - new UserDict.Word("this_word_should_not_exist_in_default_dictionary", "テスト")); - openJtalk.useUserDict(userDict); - AudioQuery query2 = synthesizer.audioQuery("this_word_should_not_exist_in_default_dictionary", - model.metas[0].styles[0].id, - EnumSet.noneOf(Synthesizer.AudioQueryOption.class)); - assertTrue(query1.kana != query2.kana); + VoiceModel model = loadModel(); + OpenJtalk openJtalk = loadOpenJtalk(); + Synthesizer synthesizer = Synthesizer.builder(openJtalk).build(); + UserDict userDict = new UserDict(); + synthesizer.loadVoiceModel(model); + AudioQuery query1 = synthesizer.audioQuery("this_word_should_not_exist_in_default_dictionary", + model.metas[0].styles[0].id, + EnumSet.noneOf(Synthesizer.AudioQueryOption.class)); + userDict.addWord( + new UserDict.Word("this_word_should_not_exist_in_default_dictionary", "テスト")); + openJtalk.useUserDict(userDict); + AudioQuery query2 = synthesizer.audioQuery("this_word_should_not_exist_in_default_dictionary", + model.metas[0].styles[0].id, + EnumSet.noneOf(Synthesizer.AudioQueryOption.class)); + assertTrue(query1.kana != query2.kana); - } } // 辞書操作のテスト。 @Test void checkManipulation() throws Exception { - try (UserDict userDict = new UserDict()) { - // 単語追加 - String uuid = userDict.addWord(new UserDict.Word("hoge", "ホゲ")); - assertTrue(userDict.getWords().get(uuid) != null); - - // 単語更新 - userDict.updateWord(uuid, new UserDict.Word("hoge", "ホゲホゲ")); - assertTrue(userDict.getWords().get(uuid).pronunciation.equals("ホゲホゲ")); + UserDict userDict = new UserDict(); + // 単語追加 + String uuid = userDict.addWord(new UserDict.Word("hoge", "ホゲ")); + assertTrue(userDict.getWords().get(uuid) != null); - // 単語削除 - userDict.removeWord(uuid); - assertTrue(userDict.getWords().get(uuid) == null); + // 単語更新 + userDict.updateWord(uuid, new UserDict.Word("hoge", "ホゲホゲ")); + assertTrue(userDict.getWords().get(uuid).pronunciation.equals("ホゲホゲ")); - // 辞書のインポート - userDict.addWord(new UserDict.Word("hoge", "ホゲ")); - try ( - UserDict userDict2 = new UserDict()) { - userDict2.addWord(new UserDict.Word("fuga", "フガ")); - userDict.importDict(userDict2); - assertTrue(userDict.getWords().size() == 2); - } + // 単語削除 + userDict.removeWord(uuid); + assertTrue(userDict.getWords().get(uuid) == null); - // 辞書の保存/読み込み - Path path = Files.createTempFile("voicevox_user_dict", ".json"); - try ( - UserDict userDict2 = new UserDict()) { - userDict.save(path.toString()); - userDict2.load(path.toString()); - assertTrue(userDict2.getWords().size() == 2); - } finally { - Files.deleteIfExists(path); - } + // 辞書のインポート + userDict.addWord(new UserDict.Word("hoge", "ホゲ")); + UserDict userDict2 = new UserDict(); + userDict2.addWord(new UserDict.Word("fuga", "フガ")); + userDict.importDict(userDict2); + assertTrue(userDict.getWords().size() == 2); + // 辞書の保存/読み込み + Path path = Files.createTempFile("voicevox_user_dict", ".json"); + try { + UserDict userDict3 = new UserDict(); + userDict.save(path.toString()); + userDict3.load(path.toString()); + assertTrue(userDict3.getWords().size() == 2); + } finally { + Files.deleteIfExists(path); } + } } From 2aa4054cfb89822c4244ba76761b52ca7ade8e13 Mon Sep 17 00:00:00 2001 From: sevenc-nanashi Date: Sun, 13 Aug 2023 08:17:28 +0900 Subject: [PATCH 57/99] =?UTF-8?q?Add:=20spotless=E3=82=92=E8=BF=BD?= =?UTF-8?q?=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../voicevox_core_java_api/lib/build.gradle | 8 ++ .../Hiroshiba/VoicevoxCore/AccentPhrase.java | 8 +- .../jp/Hiroshiba/VoicevoxCore/AudioQuery.java | 10 +-- .../java/jp/Hiroshiba/VoicevoxCore/Dll.java | 3 +- .../java/jp/Hiroshiba/VoicevoxCore/Mora.java | 5 +- .../jp/Hiroshiba/VoicevoxCore/OpenJtalk.java | 2 +- .../Hiroshiba/VoicevoxCore/Synthesizer.java | 56 ++++++------ .../jp/Hiroshiba/VoicevoxCore/UserDict.java | 85 ++++++------------- .../jp/Hiroshiba/VoicevoxCore/VoiceModel.java | 19 ++--- .../jp/Hiroshiba/VoicevoxCore/MetaTest.java | 6 +- .../VoicevoxCore/SynthesizerTest.java | 53 ++++++++---- .../jp/Hiroshiba/VoicevoxCore/TestUtils.java | 1 - .../Hiroshiba/VoicevoxCore/UserDictTest.java | 28 +++--- 13 files changed, 131 insertions(+), 153 deletions(-) diff --git a/crates/voicevox_core_java_api/lib/build.gradle b/crates/voicevox_core_java_api/lib/build.gradle index c2afe0385..3fa69dc98 100644 --- a/crates/voicevox_core_java_api/lib/build.gradle +++ b/crates/voicevox_core_java_api/lib/build.gradle @@ -8,6 +8,7 @@ plugins { // Apply the java-library plugin for API and implementation separation. id 'java-library' + id "com.diffplug.spotless" version "6.20.0" } version = '999.999.999' @@ -52,3 +53,10 @@ tasks.named('test') { compileJava.options.encoding = 'UTF-8' compileTestJava.options.encoding = 'UTF-8' + +apply plugin: "com.diffplug.spotless" +spotless { + java { + googleJavaFormat() + } +} diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/AccentPhrase.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/AccentPhrase.java index 96f3b4fed..c5e87f04f 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/AccentPhrase.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/AccentPhrase.java @@ -1,14 +1,12 @@ package jp.Hiroshiba.VoicevoxCore; -import java.util.List; +import com.google.gson.annotations.Expose; +import com.google.gson.annotations.SerializedName; import java.util.ArrayList; - +import java.util.List; import javax.annotation.Nonnull; import javax.annotation.Nullable; -import com.google.gson.annotations.Expose; -import com.google.gson.annotations.SerializedName; - /** AccentPhrase (アクセント句ごとの情報)。 */ public class AccentPhrase { /** モーラの配列。 */ diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/AudioQuery.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/AudioQuery.java index bc13c8239..fa03be9d3 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/AudioQuery.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/AudioQuery.java @@ -1,13 +1,11 @@ package jp.Hiroshiba.VoicevoxCore; +import com.google.gson.annotations.Expose; +import com.google.gson.annotations.SerializedName; import java.util.ArrayList; import java.util.List; - import javax.annotation.Nonnull; -import com.google.gson.annotations.Expose; -import com.google.gson.annotations.SerializedName; - /** AudioQuery (音声合成用のクエリ)。 */ public class AudioQuery { /** アクセント句の配列。 */ @@ -59,12 +57,12 @@ public class AudioQuery { /** * [読み取り専用] AquesTalk風記法。 * - * {@link Synthesizer#audioQuery} が返すもののみ String となる。入力としてのAudioQueryでは無視される。 + *

{@link Synthesizer#audioQuery} が返すもののみ String となる。入力としてのAudioQueryでは無視される。 */ @SerializedName("kana") @Expose @Nonnull - final public String kana; + public final String kana; public AudioQuery() { this.accentPhrases = new ArrayList<>(); 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 dc0efa6bd..b7c88ebde 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,12 +1,11 @@ package jp.Hiroshiba.VoicevoxCore; +import ai.onnxruntime.OrtEnvironment; import java.io.InputStream; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; -import ai.onnxruntime.OrtEnvironment; - /** ライブラリを読み込むためだけのクラス。 */ abstract class Dll { static { diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Mora.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Mora.java index 66622b909..415843b20 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Mora.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Mora.java @@ -1,10 +1,9 @@ package jp.Hiroshiba.VoicevoxCore; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - import com.google.gson.annotations.Expose; import com.google.gson.annotations.SerializedName; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; /** モーラ(子音+母音)ごとの情報。 */ public class Mora { diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/OpenJtalk.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/OpenJtalk.java index 93e894eb0..e17edf0ed 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/OpenJtalk.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/OpenJtalk.java @@ -16,7 +16,7 @@ public OpenJtalk(String openJtalkDictDir) { /** * ユーザー辞書を設定する。 * - * この関数を呼び出した後にユーザー辞書を変更した場合は、再度この関数を呼ぶ必要がある。 + *

この関数を呼び出した後にユーザー辞書を変更した場合は、再度この関数を呼ぶ必要がある。 * * @param userDict ユーザー辞書。 */ diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Synthesizer.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Synthesizer.java index 92798a80d..d1ff972dc 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Synthesizer.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Synthesizer.java @@ -1,14 +1,12 @@ package jp.Hiroshiba.VoicevoxCore; +import com.google.gson.Gson; import java.util.ArrayList; import java.util.Arrays; import java.util.EnumSet; import java.util.List; - import javax.annotation.Nonnull; -import com.google.gson.Gson; - /** * 音声シンセサイザ。 * @@ -52,10 +50,9 @@ public boolean isLoadedVoiceModel(String voiceModelId) { /** * {@link AudioQuery} を生成する。 * - * @param text テキスト。 + * @param text テキスト。 * @param styleId スタイルID。 * @param options {@link AudioQueryOption} のセット。 - * * @return 話者とテキストから生成された {@link AudioQuery}。 */ @Nonnull @@ -74,14 +71,14 @@ public AudioQuery audioQuery(String text, int styleId, EnumSet /** * {@link AccentPhrase} の配列を生成する。 * - * @param text テキスト。 + * @param text テキスト。 * @param styleId スタイルID。 * @param options {@link AudioQueryOption} のセット。 - * * @return 話者とテキストから生成された {@link AccentPhrase} の配列。 */ @Nonnull - public List createAccentPhrases(String text, int styleId, EnumSet options) { + public List createAccentPhrases( + String text, int styleId, EnumSet options) { boolean kana = options.contains(AccentPhrasesOption.KANA); String accentPhrasesJson = rsAccentPhrases(text, styleId, kana); Gson gson = new Gson(); @@ -96,59 +93,59 @@ public List createAccentPhrases(String text, int styleId, EnumSet< * アクセント句の音高・音素長を変更する。 * * @param accentPhrases 変更元のアクセント句の配列。 - * @param styleId スタイルID。 - * + * @param styleId スタイルID。 * @return 変更後のアクセント句の配列。 */ @Nonnull public List replaceMoraData(List accentPhrases, int styleId) { String accentPhrasesJson = new Gson().toJson(accentPhrases); String replacedAccentPhrasesJson = rsReplaceMoraData(accentPhrasesJson, styleId, false); - return new ArrayList<>(Arrays.asList(new Gson().fromJson(replacedAccentPhrasesJson, AccentPhrase[].class))); + return new ArrayList<>( + Arrays.asList(new Gson().fromJson(replacedAccentPhrasesJson, AccentPhrase[].class))); } /** * アクセント句の音素長を変更する。 * * @param accentPhrases 変更元のアクセント句の配列。 - * @param styleId スタイルID。 - * + * @param styleId スタイルID。 * @return 変更後のアクセント句の配列。 */ @Nonnull public List replacePhonemeLength(List accentPhrases, int styleId) { String accentPhrasesJson = new Gson().toJson(accentPhrases); String replacedAccentPhrasesJson = rsReplacePhonemeLength(accentPhrasesJson, styleId, false); - return new ArrayList<>(Arrays.asList(new Gson().fromJson(replacedAccentPhrasesJson, AccentPhrase[].class))); + return new ArrayList<>( + Arrays.asList(new Gson().fromJson(replacedAccentPhrasesJson, AccentPhrase[].class))); } /** * アクセント句の音高を変更する。 * * @param accentPhrases 変更元のアクセント句の配列。 - * @param styleId スタイルID。 - * + * @param styleId スタイルID。 * @return 変更後のアクセント句の配列。 */ @Nonnull public List replaceMoraPitch(List accentPhrases, int styleId) { String accentPhrasesJson = new Gson().toJson(accentPhrases); String replacedAccentPhrasesJson = rsReplaceMoraPitch(accentPhrasesJson, styleId, false); - return new ArrayList<>(Arrays.asList(new Gson().fromJson(replacedAccentPhrasesJson, AccentPhrase[].class))); + return new ArrayList<>( + Arrays.asList(new Gson().fromJson(replacedAccentPhrasesJson, AccentPhrase[].class))); } /** * {@link AudioQuery} から音声合成する。 * * @param audioQuery {@link AudioQuery}。 - * @param styleId スタイルID。 - * @param options {@link SynthesisOption} のセット。 - * + * @param styleId スタイルID。 + * @param options {@link SynthesisOption} のセット。 * @return WAVデータ。 */ @Nonnull public byte[] synthesis(AudioQuery audioQuery, int styleId, EnumSet options) { - boolean enableInterrogativeUpspeak = options.contains(SynthesisOption.ENABLE_INTERROGATIVE_UPSPEAK); + boolean enableInterrogativeUpspeak = + options.contains(SynthesisOption.ENABLE_INTERROGATIVE_UPSPEAK); Gson gson = new Gson(); String queryJson = gson.toJson(audioQuery); return rsSynthesis(queryJson, styleId, enableInterrogativeUpspeak); @@ -157,10 +154,9 @@ public byte[] synthesis(AudioQuery audioQuery, int styleId, EnumSet options) { return rsTts(text, styleId, kana, enableInterrogativeUpspeak); } - /** - * 音声シンセサイザを破棄する。 - */ + /** 音声シンセサイザを破棄する。 */ @Override protected void finalize() { rsDrop(); @@ -202,10 +196,12 @@ protected void finalize() { private native String rsReplaceMoraPitch(String accentPhrasesJson, int styleId, boolean kana); @Nonnull - private native byte[] rsSynthesis(String queryJson, int styleId, boolean enableInterrogativeUpspeak); + private native byte[] rsSynthesis( + String queryJson, int styleId, boolean enableInterrogativeUpspeak); @Nonnull - private native byte[] rsTts(String text, int styleId, boolean kana, boolean enableInterrogativeUpspeak); + private native byte[] rsTts( + String text, int styleId, boolean kana, boolean enableInterrogativeUpspeak); private native void rsDrop(); @@ -215,14 +211,18 @@ public static Builder builder(OpenJtalk openJtalk) { /** * 音声シンセサイザのビルダー。 + * * @see Synthesizer#builder */ public static class Builder { private OpenJtalk openJtalk; + @SuppressWarnings("unused") private AccelerationMode accelerationMode; + @SuppressWarnings("unused") private int cpuNumThreads; + @SuppressWarnings("unused") private boolean loadAllModels; diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/UserDict.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/UserDict.java index 2aa6e369c..32015d3fa 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/UserDict.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/UserDict.java @@ -1,15 +1,13 @@ package jp.Hiroshiba.VoicevoxCore; -import java.util.HashMap; - -import javax.annotation.Nonnull; -import jakarta.validation.constraints.Max; -import jakarta.validation.constraints.Min; - import com.google.gson.Gson; import com.google.gson.annotations.Expose; import com.google.gson.annotations.SerializedName; import com.google.gson.internal.LinkedTreeMap; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; +import java.util.HashMap; +import javax.annotation.Nonnull; /** ユーザー辞書。 */ public class UserDict extends Dll { @@ -98,20 +96,19 @@ public HashMap getWords() { throw new NullPointerException("words"); } HashMap words = new HashMap<>(); - rawWords.forEach((uuid, rawWord) -> { - Word word = gson.fromJson(gson.toJson(rawWord), Word.class); - if (word == null) { - throw new NullPointerException("word"); - } - words.put(uuid, word); - }); + rawWords.forEach( + (uuid, rawWord) -> { + Word word = gson.fromJson(gson.toJson(rawWord), Word.class); + if (word == null) { + throw new NullPointerException("word"); + } + words.put(uuid, word); + }); return words; } - /** - * ユーザー辞書を破棄する。 - */ + /** ユーザー辞書を破棄する。 */ @Override protected void finalize() { rsDrop(); @@ -142,22 +139,15 @@ protected void finalize() { private static native void rsValidatePronunciation(String pronunciation); - /** - * ユーザー辞書の単語。 - */ + /** ユーザー辞書の単語。 */ public static class Word { - /** - * 単語の表層形。 - */ + /** 単語の表層形。 */ @SerializedName("surface") @Expose @Nonnull public String surface; - /** - * 単語の発音。 - * 発音として有効なカタカナである必要がある。 - */ + /** 単語の発音。 発音として有効なカタカナである必要がある。 */ @SerializedName("pronunciation") @Expose @Nonnull @@ -173,20 +163,12 @@ public static class Word { @Nonnull public Type wordType; - /** - * アクセント型。 - * 音が下がる場所を指す。 - */ + /** アクセント型。 音が下がる場所を指す。 */ @SerializedName("accent_type") @Expose public int accentType; - /** - * 単語の優先度。 - * 0から10までの整数。 - * 数字が大きいほど優先度が高くなる。 - * 1から9までの値を指定することを推奨。 - */ + /** 単語の優先度。 0から10までの整数。 数字が大きいほど優先度が高くなる。 1から9までの値を指定することを推奨。 */ @SerializedName("priority") @Expose @Min(0) @@ -196,9 +178,8 @@ public static class Word { /** * UserDict.Wordを作成する。 * - * @param surface 言葉の表層形。 + * @param surface 言葉の表層形。 * @param pronunciation 言葉の発音。 - * * @throws IllegalArgumentException pronunciationが不正な場合。 */ public Word(String surface, String pronunciation) { @@ -221,7 +202,6 @@ public Word(String surface, String pronunciation) { * 単語の種類を設定する。 * * @param wordType 単語の種類。 - * * @return このインスタンス。 */ public Word wordType(Type wordType) { @@ -236,7 +216,6 @@ public Word wordType(Type wordType) { * アクセント型を設定する。 * * @param accentType アクセント型。 - * * @return このインスタンス。 */ public Word accentType(int accentType) { @@ -251,9 +230,7 @@ public Word accentType(int accentType) { * 優先度を設定する。 * * @param priority 優先度。 - * * @return このインスタンス。 - * * @throws IllegalArgumentException priorityが0未満または10より大きい場合。 */ public Word priority(int priority) { @@ -264,41 +241,29 @@ public Word priority(int priority) { return this; } - /** - * 単語の種類。 - */ + /** 単語の種類。 */ public static enum Type { - /** - * 固有名詞。 - */ + /** 固有名詞。 */ @SerializedName("PROPER_NOUN") @Expose PROPER_NOUN, - /** - * 一般名詞。 - */ + /** 一般名詞。 */ @SerializedName("COMMON_NOUN") @Expose COMMON_NOUN, - /** - * 動詞。 - */ + /** 動詞。 */ @SerializedName("VERB") @Expose VERB, - /** - * 形容詞。 - */ + /** 形容詞。 */ @SerializedName("ADJECTIVE") @Expose ADJECTIVE, - /** - * 語尾。 - */ + /** 語尾。 */ @SerializedName("SUFFIX") @Expose SUFFIX, diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/VoiceModel.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/VoiceModel.java index 8561b7010..739f15c85 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/VoiceModel.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/VoiceModel.java @@ -1,21 +1,19 @@ package jp.Hiroshiba.VoicevoxCore; -import javax.annotation.Nonnull; - import com.google.gson.Gson; import com.google.gson.annotations.Expose; import com.google.gson.annotations.SerializedName; +import javax.annotation.Nonnull; /** 音声モデル。 */ public class VoiceModel extends Dll { long internal; /** ID。 */ - @Nonnull - final public String id; + @Nonnull public final String id; + /** メタ情報。 */ - @Nonnull - final public SpeakerMeta[] metas; + @Nonnull public final SpeakerMeta[] metas; public VoiceModel(String modelPath) { rsFromPath(modelPath); @@ -27,12 +25,9 @@ public VoiceModel(String modelPath) { throw new RuntimeException("Failed to parse metasJson"); } metas = rawMetas; - } - /** - * 音声モデルを廃棄する。 - */ + /** 音声モデルを廃棄する。 */ @Override protected void finalize() { rsDrop(); @@ -55,16 +50,19 @@ public static class SpeakerMeta { @Expose @Nonnull final String name; + /** 話者に属するスタイル。 */ @SerializedName("styles") @Expose @Nonnull final StyleMeta[] styles; + /** 話者のUUID。 */ @SerializedName("speaker_uuid") @Expose @Nonnull final String speakerUuid; + /** 話者のバージョン。 */ @SerializedName("version") @Expose @@ -88,6 +86,7 @@ public static class StyleMeta { @Expose @Nonnull final String name; + /** スタイルID。 */ @SerializedName("id") @Expose diff --git a/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/MetaTest.java b/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/MetaTest.java index d4a3f2740..0bd8716c9 100644 --- a/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/MetaTest.java +++ b/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/MetaTest.java @@ -3,19 +3,17 @@ */ package jp.Hiroshiba.VoicevoxCore; -import org.junit.jupiter.api.Test; - import static org.junit.jupiter.api.Assertions.assertNotNull; import java.io.File; +import org.junit.jupiter.api.Test; class MetaTest { @Test void checkLoad() { // cwdはvoicevox_core/crates/voicevox_core_java_api/lib String cwd = System.getProperty("user.dir"); - File path = new File( - cwd + "/../../../model/sample.vvm"); + File path = new File(cwd + "/../../../model/sample.vvm"); VoiceModel model = new VoiceModel(path.getAbsolutePath()); assertNotNull(model.metas); } 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 2b35b062f..89f53c658 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,16 +4,14 @@ */ package jp.Hiroshiba.VoicevoxCore; -import org.junit.jupiter.api.Test; - import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.EnumSet; import java.util.List; +import org.junit.jupiter.api.Test; -class SynthesizerTest - extends TestUtils { +class SynthesizerTest extends TestUtils { @FunctionalInterface interface MoraCheckCallback { boolean check(Mora mora, Mora otherMora); @@ -53,10 +51,14 @@ void checkAudioQuery() { OpenJtalk openJtalk = loadOpenJtalk(); Synthesizer synthesizer = Synthesizer.builder(openJtalk).build(); synthesizer.loadVoiceModel(model); - AudioQuery query = synthesizer.audioQuery("こんにちは", model.metas[0].styles[0].id, - EnumSet.noneOf(Synthesizer.AudioQueryOption.class)); + AudioQuery query = + synthesizer.audioQuery( + "こんにちは", + model.metas[0].styles[0].id, + EnumSet.noneOf(Synthesizer.AudioQueryOption.class)); - synthesizer.synthesis(query, model.metas[0].styles[0].id, EnumSet.noneOf(Synthesizer.SynthesisOption.class)); + synthesizer.synthesis( + query, model.metas[0].styles[0].id, EnumSet.noneOf(Synthesizer.SynthesisOption.class)); } @Test @@ -65,17 +67,31 @@ void checkAccentPhrases() { OpenJtalk openJtalk = loadOpenJtalk(); Synthesizer synthesizer = Synthesizer.builder(openJtalk).build(); synthesizer.loadVoiceModel(model); - List accentPhrases = synthesizer.createAccentPhrases("こんにちは", model.metas[0].styles[0].id, - EnumSet.noneOf(Synthesizer.AccentPhrasesOption.class)); - List accentPhrases2 = synthesizer.replaceMoraPitch(accentPhrases, model.metas[1].styles[0].id); - assertTrue(checkAllMoras(accentPhrases, accentPhrases2, (mora, otherMora) -> mora.pitch != otherMora.pitch)); - List accentPhrases3 = synthesizer.replacePhonemeLength(accentPhrases, model.metas[1].styles[0].id); + List accentPhrases = + synthesizer.createAccentPhrases( + "こんにちは", + model.metas[0].styles[0].id, + EnumSet.noneOf(Synthesizer.AccentPhrasesOption.class)); + List accentPhrases2 = + synthesizer.replaceMoraPitch(accentPhrases, model.metas[1].styles[0].id); assertTrue( - checkAllMoras(accentPhrases, accentPhrases3, (mora, otherMora) -> mora.vowelLength != otherMora.vowelLength)); - List accentPhrases4 = synthesizer.replaceMoraData(accentPhrases, model.metas[1].styles[0].id); - assertTrue(checkAllMoras(accentPhrases, accentPhrases4, - (mora, otherMora) -> mora.pitch != otherMora.pitch && mora.vowelLength != otherMora.vowelLength)); - + checkAllMoras( + accentPhrases, accentPhrases2, (mora, otherMora) -> mora.pitch != otherMora.pitch)); + List accentPhrases3 = + synthesizer.replacePhonemeLength(accentPhrases, model.metas[1].styles[0].id); + assertTrue( + checkAllMoras( + accentPhrases, + accentPhrases3, + (mora, otherMora) -> mora.vowelLength != otherMora.vowelLength)); + List accentPhrases4 = + synthesizer.replaceMoraData(accentPhrases, model.metas[1].styles[0].id); + assertTrue( + checkAllMoras( + accentPhrases, + accentPhrases4, + (mora, otherMora) -> + mora.pitch != otherMora.pitch && mora.vowelLength != otherMora.vowelLength)); } @Test @@ -84,6 +100,7 @@ void checkTts() { OpenJtalk openJtalk = loadOpenJtalk(); Synthesizer synthesizer = Synthesizer.builder(openJtalk).build(); synthesizer.loadVoiceModel(model); - synthesizer.tts("こんにちは", model.metas[0].styles[0].id, EnumSet.noneOf(Synthesizer.TtsOption.class)); + synthesizer.tts( + "こんにちは", model.metas[0].styles[0].id, EnumSet.noneOf(Synthesizer.TtsOption.class)); } } 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 3a1db9a92..40e770494 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 @@ -13,7 +13,6 @@ VoiceModel loadModel() { } catch (Exception e) { throw new RuntimeException(e); } - } OpenJtalk loadOpenJtalk() { diff --git a/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/UserDictTest.java b/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/UserDictTest.java index 597ef89b6..7ed51276a 100644 --- a/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/UserDictTest.java +++ b/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/UserDictTest.java @@ -5,11 +5,9 @@ import java.nio.file.Files; import java.nio.file.Path; import java.util.EnumSet; - import org.junit.jupiter.api.Test; -class UserDictTest - extends TestUtils { +class UserDictTest extends TestUtils { // 辞書ロードのテスト。 // 辞書ロード前後でkanaが異なることを確認する @@ -20,23 +18,24 @@ void checkLoad() { Synthesizer synthesizer = Synthesizer.builder(openJtalk).build(); UserDict userDict = new UserDict(); synthesizer.loadVoiceModel(model); - AudioQuery query1 = synthesizer.audioQuery("this_word_should_not_exist_in_default_dictionary", - model.metas[0].styles[0].id, - EnumSet.noneOf(Synthesizer.AudioQueryOption.class)); - userDict.addWord( - new UserDict.Word("this_word_should_not_exist_in_default_dictionary", "テスト")); + AudioQuery query1 = + synthesizer.audioQuery( + "this_word_should_not_exist_in_default_dictionary", + model.metas[0].styles[0].id, + EnumSet.noneOf(Synthesizer.AudioQueryOption.class)); + userDict.addWord(new UserDict.Word("this_word_should_not_exist_in_default_dictionary", "テスト")); openJtalk.useUserDict(userDict); - AudioQuery query2 = synthesizer.audioQuery("this_word_should_not_exist_in_default_dictionary", - model.metas[0].styles[0].id, - EnumSet.noneOf(Synthesizer.AudioQueryOption.class)); + AudioQuery query2 = + synthesizer.audioQuery( + "this_word_should_not_exist_in_default_dictionary", + model.metas[0].styles[0].id, + EnumSet.noneOf(Synthesizer.AudioQueryOption.class)); assertTrue(query1.kana != query2.kana); - } // 辞書操作のテスト。 @Test - void checkManipulation() - throws Exception { + void checkManipulation() throws Exception { UserDict userDict = new UserDict(); // 単語追加 String uuid = userDict.addWord(new UserDict.Word("hoge", "ホゲ")); @@ -67,6 +66,5 @@ void checkManipulation() } finally { Files.deleteIfExists(path); } - } } From 480ea7dfadd4f776db78f4bbed7d6bbb1261c3b0 Mon Sep 17 00:00:00 2001 From: sevenc-nanashi Date: Sun, 13 Aug 2023 08:44:21 +0900 Subject: [PATCH 58/99] =?UTF-8?q?Fix:=20apply=E3=82=92=E5=89=8A=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crates/voicevox_core_java_api/lib/build.gradle | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/voicevox_core_java_api/lib/build.gradle b/crates/voicevox_core_java_api/lib/build.gradle index 3fa69dc98..faeffd6fe 100644 --- a/crates/voicevox_core_java_api/lib/build.gradle +++ b/crates/voicevox_core_java_api/lib/build.gradle @@ -54,7 +54,6 @@ tasks.named('test') { compileJava.options.encoding = 'UTF-8' compileTestJava.options.encoding = 'UTF-8' -apply plugin: "com.diffplug.spotless" spotless { java { googleJavaFormat() From 9e268d0f15e54ab379068de12c10f70f4f28a1fc Mon Sep 17 00:00:00 2001 From: sevenc-nanashi Date: Sun, 13 Aug 2023 08:53:02 +0900 Subject: [PATCH 59/99] =?UTF-8?q?Change:=20workflow=E3=81=AEJava=E3=82=921?= =?UTF-8?q?1=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 15283a9f3..daf9d7bf4 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -297,7 +297,7 @@ jobs: - name: Set up Java uses: actions/setup-java@v2 with: - java-version: "8" + java-version: "11" distribution: "adopt" - name: Build run: | From d1c3f968b58a079beb3e2c1ea78c2e3577f1a25e Mon Sep 17 00:00:00 2001 From: Nanashi Date: Sun, 13 Aug 2023 12:03:01 +0900 Subject: [PATCH 60/99] =?UTF-8?q?Change:=20API=E3=83=89=E3=82=AD=E3=83=A5?= =?UTF-8?q?=E3=83=A1=E3=83=B3=E3=83=88=E7=94=9F=E6=88=90=E3=81=AEJava?= =?UTF-8?q?=E3=81=AE=E3=83=90=E3=83=BC=E3=82=B8=E3=83=A7=E3=83=B3=E3=82=92?= =?UTF-8?q?=E5=A4=89=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/generate_document.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/generate_document.yml b/.github/workflows/generate_document.yml index def11b9b6..178400cff 100644 --- a/.github/workflows/generate_document.yml +++ b/.github/workflows/generate_document.yml @@ -23,7 +23,7 @@ jobs: - name: Setup Java uses: actions/setup-java@v2 with: - java-version: "8" + java-version: "11" distribution: "adopt" - name: Install cargo-binstall uses: taiki-e/install-action@cargo-binstall From 9a8129edfb2f886b9bd9cb57a8fdedd4a0bd0a9d Mon Sep 17 00:00:00 2001 From: Nanashi Date: Sun, 13 Aug 2023 12:03:36 +0900 Subject: [PATCH 61/99] =?UTF-8?q?Fix:=20JDK=E3=81=AE=E3=83=90=E3=83=BC?= =?UTF-8?q?=E3=82=B8=E3=83=A7=E3=83=B3=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crates/voicevox_core_java_api/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/voicevox_core_java_api/README.md b/crates/voicevox_core_java_api/README.md index 66b40dc62..4d649b182 100644 --- a/crates/voicevox_core_java_api/README.md +++ b/crates/voicevox_core_java_api/README.md @@ -7,7 +7,7 @@ VOICEVOX CORE の Java バインディング。 以下の環境が必要です: - Rustup -- JDK 8 +- JDK 11 ## ファイル構成 From b091e6ae68e05677a3a89d835a07352642d9df9e Mon Sep 17 00:00:00 2001 From: Nanashi Date: Sun, 13 Aug 2023 12:07:30 +0900 Subject: [PATCH 62/99] =?UTF-8?q?Fix:=20

=E3=82=92=E5=89=8A=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/jp/Hiroshiba/VoicevoxCore/AudioQuery.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/AudioQuery.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/AudioQuery.java index fa03be9d3..6d2a585c6 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/AudioQuery.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/AudioQuery.java @@ -6,7 +6,7 @@ import java.util.List; import javax.annotation.Nonnull; -/** AudioQuery (音声合成用のクエリ)。 */ +/** AudioQuery(音声合成用のクエリ)。 */ public class AudioQuery { /** アクセント句の配列。 */ @SerializedName("accent_phrases") @@ -57,7 +57,7 @@ public class AudioQuery { /** * [読み取り専用] AquesTalk風記法。 * - *

{@link Synthesizer#audioQuery} が返すもののみ String となる。入力としてのAudioQueryでは無視される。 + * {@link Synthesizer#audioQuery} が返すもののみ String となる。入力としてのAudioQueryでは無視される。 */ @SerializedName("kana") @Expose From e766bd612fa15bf167104d7b4004c648f7e78f1b Mon Sep 17 00:00:00 2001 From: Nanashi Date: Sun, 13 Aug 2023 12:08:33 +0900 Subject: [PATCH 63/99] =?UTF-8?q?Revert:=20p=E3=82=92=E5=BE=A9=E6=B4=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lib/src/main/java/jp/Hiroshiba/VoicevoxCore/AudioQuery.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/AudioQuery.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/AudioQuery.java index 6d2a585c6..21c97a4db 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/AudioQuery.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/AudioQuery.java @@ -57,7 +57,7 @@ public class AudioQuery { /** * [読み取り専用] AquesTalk風記法。 * - * {@link Synthesizer#audioQuery} が返すもののみ String となる。入力としてのAudioQueryでは無視される。 + *

{@link Synthesizer#audioQuery} が返すもののみ String となる。入力としてのAudioQueryでは無視される。 */ @SerializedName("kana") @Expose From 6d1e51707bd8b3e5c44406e933a8abf75e4846c4 Mon Sep 17 00:00:00 2001 From: Nanashi Date: Sun, 13 Aug 2023 14:51:32 +0900 Subject: [PATCH 64/99] =?UTF-8?q?Code:=20shellcheck=E3=81=AE=E9=81=95?= =?UTF-8?q?=E5=8F=8D=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Ryo Yamashita --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index daf9d7bf4..fb720e2f3 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -355,6 +355,6 @@ jobs: exit 1 ;; esac - cp -v ../../target/debug/$DLL_NAME ./lib/src/main/resources/dll/$TARGET_NAME/$DLL_NAME + cp -v "../../target/debug/$DLL_NAME" "./lib/src/main/resources/dll/$TARGET_NAME/$DLL_NAME" echo "target = $TARGET_NAME, dll = $DLL_NAME" ./gradlew test --info From 225c8f9bf85f798d8c9f8f4f968c0b13b799b961 Mon Sep 17 00:00:00 2001 From: Nanashi Date: Sun, 13 Aug 2023 14:51:55 +0900 Subject: [PATCH 65/99] =?UTF-8?q?Revert:=20new=E3=82=92default=E3=81=AB?= =?UTF-8?q?=E6=88=BB=E3=81=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Ryo Yamashita --- crates/voicevox_core/src/status.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/voicevox_core/src/status.rs b/crates/voicevox_core/src/status.rs index 66c3f67f3..12f7e1bd6 100644 --- a/crates/voicevox_core/src/status.rs +++ b/crates/voicevox_core/src/status.rs @@ -76,7 +76,7 @@ impl Status { merged_metas: VoiceModelMeta::default(), light_session_options: SessionOptions::new(cpu_num_threads, false), heavy_session_options: SessionOptions::new(cpu_num_threads, use_gpu), - id_relations: BTreeMap::new(), + id_relations: BTreeMap::default(), } } From f62adc142f55d6a487e67b17743179dd15ac6307 Mon Sep 17 00:00:00 2001 From: Nanashi Date: Sun, 13 Aug 2023 14:52:28 +0900 Subject: [PATCH 66/99] =?UTF-8?q?Change:=20realpath=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Ryo Yamashita --- crates/voicevox_core_java_api/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/voicevox_core_java_api/README.md b/crates/voicevox_core_java_api/README.md index 4d649b182..941d0deea 100644 --- a/crates/voicevox_core_java_api/README.md +++ b/crates/voicevox_core_java_api/README.md @@ -47,7 +47,7 @@ Java プロジェクトを動かすには、 ```console ❯ cargo build -❯ LD_LIBRARY_PATH=/home/user/voicevox_core/target/debug ./gradlew build +❯ LD_LIBRARY_PATH=$(realpath ../../target/debug) ./gradlew build # または ❯ cp ../../target/debug/libvoicevox_core_java_api.so lib/src/main/resources/dll/[target]/libvoicevox_core_java_api.so From 87a286dd91000b0e147c2c28e1456897eaed76e2 Mon Sep 17 00:00:00 2001 From: sevenc-nanashi Date: Tue, 15 Aug 2023 16:46:46 +0900 Subject: [PATCH 67/99] =?UTF-8?q?Change:=20=E9=A0=86=E7=95=AA=E3=82=92?= =?UTF-8?q?=E5=A4=89=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 509738aa8..53b9670a3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,8 +4,8 @@ members = [ "crates/test_util", "crates/voicevox_core", "crates/voicevox_core_c_api", - "crates/voicevox_core_python_api", "crates/voicevox_core_java_api", + "crates/voicevox_core_python_api", "crates/xtask" ] From 5dbb30f0b20f0a67cea882a45e1a361398d3218b Mon Sep 17 00:00:00 2001 From: sevenc-nanashi Date: Tue, 15 Aug 2023 16:47:54 +0900 Subject: [PATCH 68/99] =?UTF-8?q?Change:=20$RUNNER=5FOS=E3=82=92=E4=BD=BF?= =?UTF-8?q?=E3=81=86=E7=94=A8=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index fb720e2f3..5841f0880 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -307,7 +307,7 @@ jobs: working-directory: crates/voicevox_core_java_api run: | ARCH="$(uname -m)" - case "${{ matrix.os }}" in + case "$RUNNER_OS" in windows-latest) DLL_NAME="voicevox_core_java_api.dll" case "$ARCH" in From 0cb2721751df693d959cbee408ddcaadc4b674c5 Mon Sep 17 00:00:00 2001 From: sevenc-nanashi Date: Tue, 15 Aug 2023 16:49:28 +0900 Subject: [PATCH 69/99] =?UTF-8?q?Fix:=20README=E3=81=AE=E8=A8=98=E8=BF=B0?= =?UTF-8?q?=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crates/voicevox_core_java_api/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/voicevox_core_java_api/README.md b/crates/voicevox_core_java_api/README.md index 941d0deea..c879ca1bb 100644 --- a/crates/voicevox_core_java_api/README.md +++ b/crates/voicevox_core_java_api/README.md @@ -23,7 +23,7 @@ VOICEVOX CORE の Java バインディング。 - Synthesizer.java - ... - resources: - - dll: # ライブラリ用のディレクトリ。詳細はDll.javaを参照。 + - dll: # ライブラリ用のディレクトリ。詳細は後述。 - windows-x64: - voicevox_core.dll - ... From e6facbcbcf35893c6507573f69f3186db3d92edc Mon Sep 17 00:00:00 2001 From: sevenc-nanashi Date: Tue, 15 Aug 2023 19:54:17 +0900 Subject: [PATCH 70/99] =?UTF-8?q?Fix:=20RUNNER=5FOS=E3=81=AE=E5=80=A4?= =?UTF-8?q?=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/test.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 5841f0880..0b20d68c6 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -308,7 +308,7 @@ jobs: run: | ARCH="$(uname -m)" case "$RUNNER_OS" in - windows-latest) + windows) DLL_NAME="voicevox_core_java_api.dll" case "$ARCH" in x86_64) @@ -320,7 +320,7 @@ jobs: ;; esac ;; - macos-latest) + macos) DLL_NAME="libvoicevox_core_java_api.dylib" case "$ARCH" in x86_64) @@ -335,7 +335,7 @@ jobs: ;; esac ;; - ubuntu-latest) + ubuntu) DLL_NAME="libvoicevox_core_java_api.so" case "$ARCH" in x86_64) From 8cad17a260d8cc2e80971c2746ddf9eeee1e2958 Mon Sep 17 00:00:00 2001 From: Nanashi Date: Tue, 15 Aug 2023 20:44:35 +0900 Subject: [PATCH 71/99] =?UTF-8?q?Fix:=20OS=E3=81=AE=E5=80=A4=E3=82=92?= =?UTF-8?q?=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/test.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 0b20d68c6..2fa732d60 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -308,7 +308,7 @@ jobs: run: | ARCH="$(uname -m)" case "$RUNNER_OS" in - windows) + Windows) DLL_NAME="voicevox_core_java_api.dll" case "$ARCH" in x86_64) @@ -320,7 +320,7 @@ jobs: ;; esac ;; - macos) + macOS) DLL_NAME="libvoicevox_core_java_api.dylib" case "$ARCH" in x86_64) @@ -335,7 +335,7 @@ jobs: ;; esac ;; - ubuntu) + Linux) DLL_NAME="libvoicevox_core_java_api.so" case "$ARCH" in x86_64) @@ -351,7 +351,7 @@ jobs: esac ;; *) - echo "Unsupported OS: ${{ matrix.os }}" + echo "Unsupported OS: $RUNNER_OS" exit 1 ;; esac From c6c56c333b037cb567c2acc70ca7459a53d6b614 Mon Sep 17 00:00:00 2001 From: Nanashi Date: Wed, 16 Aug 2023 18:58:50 +0900 Subject: [PATCH 72/99] =?UTF-8?q?Change:=20AudioQuery#kana=E3=82=92Nullabl?= =?UTF-8?q?e=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Ryo Yamashita --- .../src/main/java/jp/Hiroshiba/VoicevoxCore/AudioQuery.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/AudioQuery.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/AudioQuery.java index 21c97a4db..b46dc88a3 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/AudioQuery.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/AudioQuery.java @@ -61,7 +61,7 @@ public class AudioQuery { */ @SerializedName("kana") @Expose - @Nonnull + @Nullable public final String kana; public AudioQuery() { @@ -73,6 +73,6 @@ public AudioQuery() { this.prePhonemeLength = 0.1; this.postPhonemeLength = 0.1; this.outputSamplingRate = 24000; - this.kana = ""; + this.kana = null; } } From 17e1a8bad02124b0ab858f76f7f08a6af369b74a Mon Sep 17 00:00:00 2001 From: sevenc-nanashi Date: Wed, 16 Aug 2023 19:04:15 +0900 Subject: [PATCH 73/99] =?UTF-8?q?Delete:=20=E4=B8=8D=E8=A6=81=E3=81=AAget-?= =?UTF-8?q?>drop=E3=82=92=E5=89=8A=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: qryxip --- .../src/main/java/jp/Hiroshiba/VoicevoxCore/AudioQuery.java | 1 + crates/voicevox_core_java_api/src/open_jtalk.rs | 4 ---- crates/voicevox_core_java_api/src/synthesizer.rs | 5 ----- crates/voicevox_core_java_api/src/user_dict.rs | 3 --- 4 files changed, 1 insertion(+), 12 deletions(-) diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/AudioQuery.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/AudioQuery.java index b46dc88a3..d10d49fc5 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/AudioQuery.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/AudioQuery.java @@ -5,6 +5,7 @@ import java.util.ArrayList; import java.util.List; import javax.annotation.Nonnull; +import javax.annotation.Nullable; /** AudioQuery(音声合成用のクエリ)。 */ public class AudioQuery { diff --git a/crates/voicevox_core_java_api/src/open_jtalk.rs b/crates/voicevox_core_java_api/src/open_jtalk.rs index 4a65f882d..614ecef2c 100644 --- a/crates/voicevox_core_java_api/src/open_jtalk.rs +++ b/crates/voicevox_core_java_api/src/open_jtalk.rs @@ -67,10 +67,6 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_OpenJtalk_rsDrop<'local>( this: JObject<'local>, ) { throw_if_err(env, (), |env| { - let internal = unsafe { - env.get_rust_field::<_, _, Arc>(&this, "internal") - }?; - drop(internal); unsafe { env.take_rust_field(&this, "internal") }?; Ok(()) }) diff --git a/crates/voicevox_core_java_api/src/synthesizer.rs b/crates/voicevox_core_java_api/src/synthesizer.rs index 06e15fa29..23a430e63 100644 --- a/crates/voicevox_core_java_api/src/synthesizer.rs +++ b/crates/voicevox_core_java_api/src/synthesizer.rs @@ -387,11 +387,6 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsDrop<'local> this: JObject<'local>, ) { throw_if_err(env, (), |env| { - let internal = unsafe { - env.get_rust_field::<_, _, Arc>>(&this, "internal")? - .clone() - }; - drop(internal); unsafe { env.take_rust_field(&this, "internal") }?; Ok(()) }) diff --git a/crates/voicevox_core_java_api/src/user_dict.rs b/crates/voicevox_core_java_api/src/user_dict.rs index 012db3e2f..7d896005c 100644 --- a/crates/voicevox_core_java_api/src/user_dict.rs +++ b/crates/voicevox_core_java_api/src/user_dict.rs @@ -209,9 +209,6 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsDrop<'local>( this: JObject<'local>, ) { throw_if_err(env, (), |env| { - let internal = - unsafe { env.get_rust_field::<_, _, voicevox_core::VoiceModel>(&this, "internal") }?; - drop(internal); unsafe { env.take_rust_field(&this, "internal") }?; Ok(()) }) From 7f6dc518e2ea0056d896be0376eda2e817b81a1d Mon Sep 17 00:00:00 2001 From: sevenc-nanashi Date: Wed, 16 Aug 2023 19:09:48 +0900 Subject: [PATCH 74/99] Change: internal -> handle Co-Authored-By: qryxip --- .../jp/Hiroshiba/VoicevoxCore/OpenJtalk.java | 2 +- .../Hiroshiba/VoicevoxCore/Synthesizer.java | 2 +- .../jp/Hiroshiba/VoicevoxCore/UserDict.java | 2 +- .../jp/Hiroshiba/VoicevoxCore/VoiceModel.java | 2 +- .../voicevox_core_java_api/src/open_jtalk.rs | 10 +++---- .../voicevox_core_java_api/src/synthesizer.rs | 28 +++++++++---------- .../voicevox_core_java_api/src/user_dict.rs | 20 ++++++------- .../voicevox_core_java_api/src/voice_model.rs | 11 +++----- 8 files changed, 37 insertions(+), 40 deletions(-) diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/OpenJtalk.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/OpenJtalk.java index e17edf0ed..2b12baea7 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/OpenJtalk.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/OpenJtalk.java @@ -2,7 +2,7 @@ /** テキスト解析器としてのOpen JTalk。 */ public class OpenJtalk extends Dll { - long internal; + private long handle; /** * Open JTalkの辞書ディレクトリ。 diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Synthesizer.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Synthesizer.java index d1ff972dc..cbacdcd06 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Synthesizer.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Synthesizer.java @@ -13,7 +13,7 @@ * @see Synthesizer#builder */ public class Synthesizer extends Dll { - long internal; + private long handle; private Synthesizer(OpenJtalk openJtalk, Builder builder) { rsNewWithInitialize(openJtalk, builder); diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/UserDict.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/UserDict.java index 32015d3fa..ca3d5a631 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/UserDict.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/UserDict.java @@ -11,7 +11,7 @@ /** ユーザー辞書。 */ public class UserDict extends Dll { - long internal; + private long handle; /** ユーザー辞書を作成する。 */ public UserDict() { diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/VoiceModel.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/VoiceModel.java index 739f15c85..76196d3e4 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/VoiceModel.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/VoiceModel.java @@ -7,7 +7,7 @@ /** 音声モデル。 */ public class VoiceModel extends Dll { - long internal; + private long handle; /** ID。 */ @Nonnull public final String id; diff --git a/crates/voicevox_core_java_api/src/open_jtalk.rs b/crates/voicevox_core_java_api/src/open_jtalk.rs index 614ecef2c..04f589684 100644 --- a/crates/voicevox_core_java_api/src/open_jtalk.rs +++ b/crates/voicevox_core_java_api/src/open_jtalk.rs @@ -13,7 +13,7 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_OpenJtalk_rsNewWithoutDic< throw_if_err(env, (), |env| { let internal = voicevox_core::OpenJtalk::new_without_dic(); - unsafe { env.set_rust_field(&this, "internal", Arc::new(internal)) }?; + unsafe { env.set_rust_field(&this, "handle", Arc::new(internal)) }?; Ok(()) }) } @@ -29,7 +29,7 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_OpenJtalk_rsNewWithInitial let open_jtalk_dict_dir = open_jtalk_dict_dir.to_str()?; let internal = voicevox_core::OpenJtalk::new_with_initialize(open_jtalk_dict_dir)?; - unsafe { env.set_rust_field(&this, "internal", Arc::new(internal)) }?; + unsafe { env.set_rust_field(&this, "handle", Arc::new(internal)) }?; Ok(()) }) @@ -43,12 +43,12 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_OpenJtalk_rsUseUserDict<'l ) { throw_if_err(env, (), |env| { let internal = unsafe { - env.get_rust_field::<_, _, Arc>(&this, "internal")? + env.get_rust_field::<_, _, Arc>(&this, "handle")? .clone() }; let user_dict = unsafe { - env.get_rust_field::<_, _, Arc>>(&user_dict, "internal")? + env.get_rust_field::<_, _, Arc>>(&user_dict, "handle")? .clone() }; @@ -67,7 +67,7 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_OpenJtalk_rsDrop<'local>( this: JObject<'local>, ) { throw_if_err(env, (), |env| { - unsafe { env.take_rust_field(&this, "internal") }?; + unsafe { env.take_rust_field(&this, "handle") }?; Ok(()) }) } diff --git a/crates/voicevox_core_java_api/src/synthesizer.rs b/crates/voicevox_core_java_api/src/synthesizer.rs index 23a430e63..9cd0366b9 100644 --- a/crates/voicevox_core_java_api/src/synthesizer.rs +++ b/crates/voicevox_core_java_api/src/synthesizer.rs @@ -54,14 +54,14 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsNewWithIniti } let open_jtalk = unsafe { - env.get_rust_field::<_, _, Arc>(&open_jtalk, "internal")? + env.get_rust_field::<_, _, Arc>(&open_jtalk, "handle")? .clone() }; let internal = RUNTIME.block_on(voicevox_core::Synthesizer::new_with_initialize( open_jtalk, Box::leak(Box::new(options)), ))?; - unsafe { env.set_rust_field(&this, "internal", Arc::new(Mutex::new(internal)))? }; + unsafe { env.set_rust_field(&this, "handle", Arc::new(Mutex::new(internal)))? }; Ok(()) }) } @@ -74,11 +74,11 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsLoadVoiceMod ) { throw_if_err(env, (), |env| { let model = unsafe { - env.get_rust_field::<_, _, Arc>(&model, "internal")? + env.get_rust_field::<_, _, Arc>(&model, "handle")? .clone() }; let internal = unsafe { - env.get_rust_field::<_, _, Arc>>(&this, "internal")? + env.get_rust_field::<_, _, Arc>>(&this, "handle")? .clone() }; { @@ -99,7 +99,7 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsUnloadVoiceM let model_id: String = env.get_string(&model_id)?.into(); let internal = unsafe { - env.get_rust_field::<_, _, Arc>>(&this, "internal")? + env.get_rust_field::<_, _, Arc>>(&this, "handle")? .clone() }; @@ -123,7 +123,7 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsIsLoadedVoic let model_id: String = env.get_string(&model_id)?.into(); let internal = unsafe { - env.get_rust_field::<_, _, Arc>>(&this, "internal")? + env.get_rust_field::<_, _, Arc>>(&this, "handle")? .clone() }; @@ -149,7 +149,7 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsAudioQuery<' let style_id = style_id as u32; let internal = unsafe { - env.get_rust_field::<_, _, Arc>>(&this, "internal")? + env.get_rust_field::<_, _, Arc>>(&this, "handle")? .clone() }; @@ -187,7 +187,7 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsAccentPhrase let style_id = style_id as u32; let internal = unsafe { - env.get_rust_field::<_, _, Arc>>(&this, "internal")? + env.get_rust_field::<_, _, Arc>>(&this, "handle")? .clone() }; @@ -226,7 +226,7 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsReplaceMoraD let style_id = style_id as u32; let internal = unsafe { - env.get_rust_field::<_, _, Arc>>(&this, "internal")? + env.get_rust_field::<_, _, Arc>>(&this, "handle")? .clone() }; @@ -257,7 +257,7 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsReplacePhone let style_id = style_id as u32; let internal = unsafe { - env.get_rust_field::<_, _, Arc>>(&this, "internal")? + env.get_rust_field::<_, _, Arc>>(&this, "handle")? .clone() }; @@ -289,7 +289,7 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsReplaceMoraP let style_id = style_id as u32; let internal = unsafe { - env.get_rust_field::<_, _, Arc>>(&this, "internal")? + env.get_rust_field::<_, _, Arc>>(&this, "handle")? .clone() }; @@ -320,7 +320,7 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsSynthesis<'l let style_id = style_id as u32; let internal = unsafe { - env.get_rust_field::<_, _, Arc>>(&this, "internal")? + env.get_rust_field::<_, _, Arc>>(&this, "handle")? .clone() }; @@ -357,7 +357,7 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsTts<'local>( let style_id = style_id as u32; let internal = unsafe { - env.get_rust_field::<_, _, Arc>>(&this, "internal")? + env.get_rust_field::<_, _, Arc>>(&this, "handle")? .clone() }; @@ -387,7 +387,7 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsDrop<'local> this: JObject<'local>, ) { throw_if_err(env, (), |env| { - unsafe { env.take_rust_field(&this, "internal") }?; + unsafe { env.take_rust_field(&this, "handle") }?; Ok(()) }) } diff --git a/crates/voicevox_core_java_api/src/user_dict.rs b/crates/voicevox_core_java_api/src/user_dict.rs index 7d896005c..0f496bad4 100644 --- a/crates/voicevox_core_java_api/src/user_dict.rs +++ b/crates/voicevox_core_java_api/src/user_dict.rs @@ -16,7 +16,7 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsNew<'local>( throw_if_err(env, (), |env| { let internal = voicevox_core::UserDict::new(); - unsafe { env.set_rust_field(&this, "internal", Arc::new(Mutex::new(internal))) }?; + unsafe { env.set_rust_field(&this, "handle", Arc::new(Mutex::new(internal))) }?; Ok(()) }) @@ -30,7 +30,7 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsAddWord<'local> ) -> jobject { throw_if_err(env, std::ptr::null_mut(), |env| { let internal = unsafe { - env.get_rust_field::<_, _, Arc>>(&this, "internal")? + env.get_rust_field::<_, _, Arc>>(&this, "handle")? .clone() }; @@ -60,7 +60,7 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsUpdateWord<'loc ) { throw_if_err(env, (), |env| { let internal = unsafe { - env.get_rust_field::<_, _, Arc>>(&this, "internal")? + env.get_rust_field::<_, _, Arc>>(&this, "handle")? .clone() }; @@ -88,7 +88,7 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsRemoveWord<'loc ) { throw_if_err(env, (), |env| { let internal = unsafe { - env.get_rust_field::<_, _, Arc>>(&this, "internal")? + env.get_rust_field::<_, _, Arc>>(&this, "handle")? .clone() }; @@ -112,13 +112,13 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsImportDict<'loc ) { throw_if_err(env, (), |env| { let internal = unsafe { - env.get_rust_field::<_, _, Arc>>(&this, "internal")? + env.get_rust_field::<_, _, Arc>>(&this, "handle")? .clone() }; let other_dict = unsafe { env.get_rust_field::<_, _, Arc>>( &other_dict, - "internal", + "handle", )? .clone() }; @@ -141,7 +141,7 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsLoad<'local>( ) { throw_if_err(env, (), |env| { let internal = unsafe { - env.get_rust_field::<_, _, Arc>>(&this, "internal")? + env.get_rust_field::<_, _, Arc>>(&this, "handle")? .clone() }; @@ -165,7 +165,7 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsSave<'local>( ) { throw_if_err(env, (), |env| { let internal = unsafe { - env.get_rust_field::<_, _, Arc>>(&this, "internal")? + env.get_rust_field::<_, _, Arc>>(&this, "handle")? .clone() }; @@ -188,7 +188,7 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsGetWords<'local ) -> jobject { throw_if_err(env, std::ptr::null_mut(), |env| { let internal = unsafe { - env.get_rust_field::<_, _, Arc>>(&this, "internal")? + env.get_rust_field::<_, _, Arc>>(&this, "handle")? .clone() }; @@ -209,7 +209,7 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsDrop<'local>( this: JObject<'local>, ) { throw_if_err(env, (), |env| { - unsafe { env.take_rust_field(&this, "internal") }?; + unsafe { env.take_rust_field(&this, "handle") }?; Ok(()) }) } diff --git a/crates/voicevox_core_java_api/src/voice_model.rs b/crates/voicevox_core_java_api/src/voice_model.rs index b09c17e2a..4f75b08fe 100644 --- a/crates/voicevox_core_java_api/src/voice_model.rs +++ b/crates/voicevox_core_java_api/src/voice_model.rs @@ -19,7 +19,7 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_VoiceModel_rsFromPath<'loc let internal = RUNTIME.block_on(voicevox_core::VoiceModel::from_path(model_path))?; - unsafe { env.set_rust_field(&this, "internal", Arc::new(internal)) }?; + unsafe { env.set_rust_field(&this, "handle", Arc::new(internal)) }?; Ok(()) }) @@ -32,7 +32,7 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_VoiceModel_rsGetId<'local> ) -> jobject { throw_if_err(env, std::ptr::null_mut(), |env| { let internal = unsafe { - env.get_rust_field::<_, _, Arc>(&this, "internal")? + env.get_rust_field::<_, _, Arc>(&this, "handle")? .clone() }; @@ -51,7 +51,7 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_VoiceModel_rsGetMetasJson< ) -> jobject { throw_if_err(env, std::ptr::null_mut(), |env| { let internal = unsafe { - env.get_rust_field::<_, _, Arc>(&this, "internal")? + env.get_rust_field::<_, _, Arc>(&this, "handle")? .clone() }; @@ -67,10 +67,7 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_VoiceModel_rsDrop<'local>( this: JObject<'local>, ) { throw_if_err(env, (), |env| { - let internal = - unsafe { env.get_rust_field::<_, _, voicevox_core::VoiceModel>(&this, "internal") }?; - drop(internal); - unsafe { env.take_rust_field(&this, "internal") }?; + unsafe { env.take_rust_field(&this, "handle") }?; Ok(()) }) } From 28ca04063be96f2147276ad429f409e05167c46d Mon Sep 17 00:00:00 2001 From: Nanashi Date: Wed, 16 Aug 2023 19:13:27 +0900 Subject: [PATCH 75/99] Change: 999.999.999 -> 0.0.0 Co-authored-by: Ryo Yamashita --- crates/voicevox_core_java_api/lib/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/voicevox_core_java_api/lib/build.gradle b/crates/voicevox_core_java_api/lib/build.gradle index faeffd6fe..c0104b7c5 100644 --- a/crates/voicevox_core_java_api/lib/build.gradle +++ b/crates/voicevox_core_java_api/lib/build.gradle @@ -11,7 +11,7 @@ plugins { id "com.diffplug.spotless" version "6.20.0" } -version = '999.999.999' +version = '0.0.0' repositories { // Use Maven Central for resolving dependencies. From 57bc4198b531a8cdfafaa5a8f3d6a2705266607b Mon Sep 17 00:00:00 2001 From: sevenc-nanashi Date: Wed, 16 Aug 2023 19:09:48 +0900 Subject: [PATCH 76/99] Change: internal -> handle Co-Authored-By: qryxip --- .../jp/Hiroshiba/VoicevoxCore/OpenJtalk.java | 2 +- .../Hiroshiba/VoicevoxCore/Synthesizer.java | 2 +- .../jp/Hiroshiba/VoicevoxCore/UserDict.java | 2 +- .../jp/Hiroshiba/VoicevoxCore/VoiceModel.java | 2 +- .../voicevox_core_java_api/src/open_jtalk.rs | 10 +++---- .../voicevox_core_java_api/src/synthesizer.rs | 28 +++++++++---------- .../voicevox_core_java_api/src/user_dict.rs | 20 ++++++------- .../voicevox_core_java_api/src/voice_model.rs | 11 +++----- 8 files changed, 37 insertions(+), 40 deletions(-) diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/OpenJtalk.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/OpenJtalk.java index e17edf0ed..2b12baea7 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/OpenJtalk.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/OpenJtalk.java @@ -2,7 +2,7 @@ /** テキスト解析器としてのOpen JTalk。 */ public class OpenJtalk extends Dll { - long internal; + private long handle; /** * Open JTalkの辞書ディレクトリ。 diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Synthesizer.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Synthesizer.java index d1ff972dc..cbacdcd06 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Synthesizer.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Synthesizer.java @@ -13,7 +13,7 @@ * @see Synthesizer#builder */ public class Synthesizer extends Dll { - long internal; + private long handle; private Synthesizer(OpenJtalk openJtalk, Builder builder) { rsNewWithInitialize(openJtalk, builder); diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/UserDict.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/UserDict.java index 32015d3fa..ca3d5a631 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/UserDict.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/UserDict.java @@ -11,7 +11,7 @@ /** ユーザー辞書。 */ public class UserDict extends Dll { - long internal; + private long handle; /** ユーザー辞書を作成する。 */ public UserDict() { diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/VoiceModel.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/VoiceModel.java index 739f15c85..76196d3e4 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/VoiceModel.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/VoiceModel.java @@ -7,7 +7,7 @@ /** 音声モデル。 */ public class VoiceModel extends Dll { - long internal; + private long handle; /** ID。 */ @Nonnull public final String id; diff --git a/crates/voicevox_core_java_api/src/open_jtalk.rs b/crates/voicevox_core_java_api/src/open_jtalk.rs index 614ecef2c..04f589684 100644 --- a/crates/voicevox_core_java_api/src/open_jtalk.rs +++ b/crates/voicevox_core_java_api/src/open_jtalk.rs @@ -13,7 +13,7 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_OpenJtalk_rsNewWithoutDic< throw_if_err(env, (), |env| { let internal = voicevox_core::OpenJtalk::new_without_dic(); - unsafe { env.set_rust_field(&this, "internal", Arc::new(internal)) }?; + unsafe { env.set_rust_field(&this, "handle", Arc::new(internal)) }?; Ok(()) }) } @@ -29,7 +29,7 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_OpenJtalk_rsNewWithInitial let open_jtalk_dict_dir = open_jtalk_dict_dir.to_str()?; let internal = voicevox_core::OpenJtalk::new_with_initialize(open_jtalk_dict_dir)?; - unsafe { env.set_rust_field(&this, "internal", Arc::new(internal)) }?; + unsafe { env.set_rust_field(&this, "handle", Arc::new(internal)) }?; Ok(()) }) @@ -43,12 +43,12 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_OpenJtalk_rsUseUserDict<'l ) { throw_if_err(env, (), |env| { let internal = unsafe { - env.get_rust_field::<_, _, Arc>(&this, "internal")? + env.get_rust_field::<_, _, Arc>(&this, "handle")? .clone() }; let user_dict = unsafe { - env.get_rust_field::<_, _, Arc>>(&user_dict, "internal")? + env.get_rust_field::<_, _, Arc>>(&user_dict, "handle")? .clone() }; @@ -67,7 +67,7 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_OpenJtalk_rsDrop<'local>( this: JObject<'local>, ) { throw_if_err(env, (), |env| { - unsafe { env.take_rust_field(&this, "internal") }?; + unsafe { env.take_rust_field(&this, "handle") }?; Ok(()) }) } diff --git a/crates/voicevox_core_java_api/src/synthesizer.rs b/crates/voicevox_core_java_api/src/synthesizer.rs index 23a430e63..9cd0366b9 100644 --- a/crates/voicevox_core_java_api/src/synthesizer.rs +++ b/crates/voicevox_core_java_api/src/synthesizer.rs @@ -54,14 +54,14 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsNewWithIniti } let open_jtalk = unsafe { - env.get_rust_field::<_, _, Arc>(&open_jtalk, "internal")? + env.get_rust_field::<_, _, Arc>(&open_jtalk, "handle")? .clone() }; let internal = RUNTIME.block_on(voicevox_core::Synthesizer::new_with_initialize( open_jtalk, Box::leak(Box::new(options)), ))?; - unsafe { env.set_rust_field(&this, "internal", Arc::new(Mutex::new(internal)))? }; + unsafe { env.set_rust_field(&this, "handle", Arc::new(Mutex::new(internal)))? }; Ok(()) }) } @@ -74,11 +74,11 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsLoadVoiceMod ) { throw_if_err(env, (), |env| { let model = unsafe { - env.get_rust_field::<_, _, Arc>(&model, "internal")? + env.get_rust_field::<_, _, Arc>(&model, "handle")? .clone() }; let internal = unsafe { - env.get_rust_field::<_, _, Arc>>(&this, "internal")? + env.get_rust_field::<_, _, Arc>>(&this, "handle")? .clone() }; { @@ -99,7 +99,7 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsUnloadVoiceM let model_id: String = env.get_string(&model_id)?.into(); let internal = unsafe { - env.get_rust_field::<_, _, Arc>>(&this, "internal")? + env.get_rust_field::<_, _, Arc>>(&this, "handle")? .clone() }; @@ -123,7 +123,7 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsIsLoadedVoic let model_id: String = env.get_string(&model_id)?.into(); let internal = unsafe { - env.get_rust_field::<_, _, Arc>>(&this, "internal")? + env.get_rust_field::<_, _, Arc>>(&this, "handle")? .clone() }; @@ -149,7 +149,7 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsAudioQuery<' let style_id = style_id as u32; let internal = unsafe { - env.get_rust_field::<_, _, Arc>>(&this, "internal")? + env.get_rust_field::<_, _, Arc>>(&this, "handle")? .clone() }; @@ -187,7 +187,7 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsAccentPhrase let style_id = style_id as u32; let internal = unsafe { - env.get_rust_field::<_, _, Arc>>(&this, "internal")? + env.get_rust_field::<_, _, Arc>>(&this, "handle")? .clone() }; @@ -226,7 +226,7 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsReplaceMoraD let style_id = style_id as u32; let internal = unsafe { - env.get_rust_field::<_, _, Arc>>(&this, "internal")? + env.get_rust_field::<_, _, Arc>>(&this, "handle")? .clone() }; @@ -257,7 +257,7 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsReplacePhone let style_id = style_id as u32; let internal = unsafe { - env.get_rust_field::<_, _, Arc>>(&this, "internal")? + env.get_rust_field::<_, _, Arc>>(&this, "handle")? .clone() }; @@ -289,7 +289,7 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsReplaceMoraP let style_id = style_id as u32; let internal = unsafe { - env.get_rust_field::<_, _, Arc>>(&this, "internal")? + env.get_rust_field::<_, _, Arc>>(&this, "handle")? .clone() }; @@ -320,7 +320,7 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsSynthesis<'l let style_id = style_id as u32; let internal = unsafe { - env.get_rust_field::<_, _, Arc>>(&this, "internal")? + env.get_rust_field::<_, _, Arc>>(&this, "handle")? .clone() }; @@ -357,7 +357,7 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsTts<'local>( let style_id = style_id as u32; let internal = unsafe { - env.get_rust_field::<_, _, Arc>>(&this, "internal")? + env.get_rust_field::<_, _, Arc>>(&this, "handle")? .clone() }; @@ -387,7 +387,7 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsDrop<'local> this: JObject<'local>, ) { throw_if_err(env, (), |env| { - unsafe { env.take_rust_field(&this, "internal") }?; + unsafe { env.take_rust_field(&this, "handle") }?; Ok(()) }) } diff --git a/crates/voicevox_core_java_api/src/user_dict.rs b/crates/voicevox_core_java_api/src/user_dict.rs index 7d896005c..0f496bad4 100644 --- a/crates/voicevox_core_java_api/src/user_dict.rs +++ b/crates/voicevox_core_java_api/src/user_dict.rs @@ -16,7 +16,7 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsNew<'local>( throw_if_err(env, (), |env| { let internal = voicevox_core::UserDict::new(); - unsafe { env.set_rust_field(&this, "internal", Arc::new(Mutex::new(internal))) }?; + unsafe { env.set_rust_field(&this, "handle", Arc::new(Mutex::new(internal))) }?; Ok(()) }) @@ -30,7 +30,7 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsAddWord<'local> ) -> jobject { throw_if_err(env, std::ptr::null_mut(), |env| { let internal = unsafe { - env.get_rust_field::<_, _, Arc>>(&this, "internal")? + env.get_rust_field::<_, _, Arc>>(&this, "handle")? .clone() }; @@ -60,7 +60,7 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsUpdateWord<'loc ) { throw_if_err(env, (), |env| { let internal = unsafe { - env.get_rust_field::<_, _, Arc>>(&this, "internal")? + env.get_rust_field::<_, _, Arc>>(&this, "handle")? .clone() }; @@ -88,7 +88,7 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsRemoveWord<'loc ) { throw_if_err(env, (), |env| { let internal = unsafe { - env.get_rust_field::<_, _, Arc>>(&this, "internal")? + env.get_rust_field::<_, _, Arc>>(&this, "handle")? .clone() }; @@ -112,13 +112,13 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsImportDict<'loc ) { throw_if_err(env, (), |env| { let internal = unsafe { - env.get_rust_field::<_, _, Arc>>(&this, "internal")? + env.get_rust_field::<_, _, Arc>>(&this, "handle")? .clone() }; let other_dict = unsafe { env.get_rust_field::<_, _, Arc>>( &other_dict, - "internal", + "handle", )? .clone() }; @@ -141,7 +141,7 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsLoad<'local>( ) { throw_if_err(env, (), |env| { let internal = unsafe { - env.get_rust_field::<_, _, Arc>>(&this, "internal")? + env.get_rust_field::<_, _, Arc>>(&this, "handle")? .clone() }; @@ -165,7 +165,7 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsSave<'local>( ) { throw_if_err(env, (), |env| { let internal = unsafe { - env.get_rust_field::<_, _, Arc>>(&this, "internal")? + env.get_rust_field::<_, _, Arc>>(&this, "handle")? .clone() }; @@ -188,7 +188,7 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsGetWords<'local ) -> jobject { throw_if_err(env, std::ptr::null_mut(), |env| { let internal = unsafe { - env.get_rust_field::<_, _, Arc>>(&this, "internal")? + env.get_rust_field::<_, _, Arc>>(&this, "handle")? .clone() }; @@ -209,7 +209,7 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsDrop<'local>( this: JObject<'local>, ) { throw_if_err(env, (), |env| { - unsafe { env.take_rust_field(&this, "internal") }?; + unsafe { env.take_rust_field(&this, "handle") }?; Ok(()) }) } diff --git a/crates/voicevox_core_java_api/src/voice_model.rs b/crates/voicevox_core_java_api/src/voice_model.rs index b09c17e2a..4f75b08fe 100644 --- a/crates/voicevox_core_java_api/src/voice_model.rs +++ b/crates/voicevox_core_java_api/src/voice_model.rs @@ -19,7 +19,7 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_VoiceModel_rsFromPath<'loc let internal = RUNTIME.block_on(voicevox_core::VoiceModel::from_path(model_path))?; - unsafe { env.set_rust_field(&this, "internal", Arc::new(internal)) }?; + unsafe { env.set_rust_field(&this, "handle", Arc::new(internal)) }?; Ok(()) }) @@ -32,7 +32,7 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_VoiceModel_rsGetId<'local> ) -> jobject { throw_if_err(env, std::ptr::null_mut(), |env| { let internal = unsafe { - env.get_rust_field::<_, _, Arc>(&this, "internal")? + env.get_rust_field::<_, _, Arc>(&this, "handle")? .clone() }; @@ -51,7 +51,7 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_VoiceModel_rsGetMetasJson< ) -> jobject { throw_if_err(env, std::ptr::null_mut(), |env| { let internal = unsafe { - env.get_rust_field::<_, _, Arc>(&this, "internal")? + env.get_rust_field::<_, _, Arc>(&this, "handle")? .clone() }; @@ -67,10 +67,7 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_VoiceModel_rsDrop<'local>( this: JObject<'local>, ) { throw_if_err(env, (), |env| { - let internal = - unsafe { env.get_rust_field::<_, _, voicevox_core::VoiceModel>(&this, "internal") }?; - drop(internal); - unsafe { env.take_rust_field(&this, "internal") }?; + unsafe { env.take_rust_field(&this, "handle") }?; Ok(()) }) } From 922e8d6358f26dd418ed73ff357a1ada894e23a7 Mon Sep 17 00:00:00 2001 From: sevenc-nanashi Date: Wed, 16 Aug 2023 19:21:59 +0900 Subject: [PATCH 77/99] Change: getWords -> toHashMap Co-Authored-By: qryxip --- .../jp/Hiroshiba/VoicevoxCore/UserDict.java | 2 +- .../Hiroshiba/VoicevoxCore/UserDictTest.java | 10 ++++---- crates/voicevox_core_java_api/src/lib.rs | 5 ---- .../voicevox_core_java_api/src/open_jtalk.rs | 8 +++---- .../voicevox_core_java_api/src/synthesizer.rs | 24 +++++++++---------- .../voicevox_core_java_api/src/user_dict.rs | 22 ++++++++--------- .../voicevox_core_java_api/src/voice_model.rs | 8 +++---- 7 files changed, 37 insertions(+), 42 deletions(-) diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/UserDict.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/UserDict.java index ca3d5a631..19e1f80a7 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/UserDict.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/UserDict.java @@ -87,7 +87,7 @@ public void save(String path) { * @return ユーザー辞書の単語。 */ @Nonnull - public HashMap getWords() { + public HashMap toHashMap() { String json = rsGetWords(); Gson gson = new Gson(); @SuppressWarnings("unchecked") diff --git a/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/UserDictTest.java b/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/UserDictTest.java index 7ed51276a..ab5d80726 100644 --- a/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/UserDictTest.java +++ b/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/UserDictTest.java @@ -39,22 +39,22 @@ void checkManipulation() throws Exception { UserDict userDict = new UserDict(); // 単語追加 String uuid = userDict.addWord(new UserDict.Word("hoge", "ホゲ")); - assertTrue(userDict.getWords().get(uuid) != null); + assertTrue(userDict.toHashMap().get(uuid) != null); // 単語更新 userDict.updateWord(uuid, new UserDict.Word("hoge", "ホゲホゲ")); - assertTrue(userDict.getWords().get(uuid).pronunciation.equals("ホゲホゲ")); + assertTrue(userDict.toHashMap().get(uuid).pronunciation.equals("ホゲホゲ")); // 単語削除 userDict.removeWord(uuid); - assertTrue(userDict.getWords().get(uuid) == null); + assertTrue(userDict.toHashMap().get(uuid) == null); // 辞書のインポート userDict.addWord(new UserDict.Word("hoge", "ホゲ")); UserDict userDict2 = new UserDict(); userDict2.addWord(new UserDict.Word("fuga", "フガ")); userDict.importDict(userDict2); - assertTrue(userDict.getWords().size() == 2); + assertTrue(userDict.toHashMap().size() == 2); // 辞書の保存/読み込み Path path = Files.createTempFile("voicevox_user_dict", ".json"); @@ -62,7 +62,7 @@ void checkManipulation() throws Exception { UserDict userDict3 = new UserDict(); userDict.save(path.toString()); userDict3.load(path.toString()); - assertTrue(userDict3.getWords().size() == 2); + assertTrue(userDict3.toHashMap().size() == 2); } finally { Files.deleteIfExists(path); } diff --git a/crates/voicevox_core_java_api/src/lib.rs b/crates/voicevox_core_java_api/src/lib.rs index 07a74673c..4ea35c0b2 100644 --- a/crates/voicevox_core_java_api/src/lib.rs +++ b/crates/voicevox_core_java_api/src/lib.rs @@ -3,8 +3,3 @@ mod open_jtalk; mod synthesizer; mod user_dict; mod voice_model; - -pub use crate::open_jtalk::*; -pub use crate::synthesizer::*; -pub use crate::user_dict::*; -pub use crate::voice_model::*; diff --git a/crates/voicevox_core_java_api/src/open_jtalk.rs b/crates/voicevox_core_java_api/src/open_jtalk.rs index 04f589684..128f053fb 100644 --- a/crates/voicevox_core_java_api/src/open_jtalk.rs +++ b/crates/voicevox_core_java_api/src/open_jtalk.rs @@ -6,7 +6,7 @@ use jni::{ JNIEnv, }; #[no_mangle] -pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_OpenJtalk_rsNewWithoutDic<'local>( +extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_OpenJtalk_rsNewWithoutDic<'local>( env: JNIEnv<'local>, this: JObject<'local>, ) { @@ -19,7 +19,7 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_OpenJtalk_rsNewWithoutDic< } #[no_mangle] -pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_OpenJtalk_rsNewWithInitialize<'local>( +extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_OpenJtalk_rsNewWithInitialize<'local>( env: JNIEnv<'local>, this: JObject<'local>, open_jtalk_dict_dir: JString<'local>, @@ -36,7 +36,7 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_OpenJtalk_rsNewWithInitial } #[no_mangle] -pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_OpenJtalk_rsUseUserDict<'local>( +extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_OpenJtalk_rsUseUserDict<'local>( env: JNIEnv<'local>, this: JObject<'local>, user_dict: JObject<'local>, @@ -62,7 +62,7 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_OpenJtalk_rsUseUserDict<'l } #[no_mangle] -pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_OpenJtalk_rsDrop<'local>( +extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_OpenJtalk_rsDrop<'local>( env: JNIEnv<'local>, this: JObject<'local>, ) { diff --git a/crates/voicevox_core_java_api/src/synthesizer.rs b/crates/voicevox_core_java_api/src/synthesizer.rs index 9cd0366b9..fed53992f 100644 --- a/crates/voicevox_core_java_api/src/synthesizer.rs +++ b/crates/voicevox_core_java_api/src/synthesizer.rs @@ -12,7 +12,7 @@ use jni::{ use std::sync::{Arc, Mutex}; #[no_mangle] -pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsNewWithInitialize<'local>( +extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsNewWithInitialize<'local>( env: JNIEnv<'local>, this: JObject<'local>, open_jtalk: JObject<'local>, @@ -67,7 +67,7 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsNewWithIniti } #[no_mangle] -pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsLoadVoiceModel<'local>( +extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsLoadVoiceModel<'local>( env: JNIEnv<'local>, this: JObject<'local>, model: JObject<'local>, @@ -90,7 +90,7 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsLoadVoiceMod } #[no_mangle] -pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsUnloadVoiceModel<'local>( +extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsUnloadVoiceModel<'local>( env: JNIEnv<'local>, this: JObject<'local>, model_id: JString<'local>, @@ -114,7 +114,7 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsUnloadVoiceM } #[no_mangle] -pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsIsLoadedVoiceModel<'local>( +extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsIsLoadedVoiceModel<'local>( env: JNIEnv<'local>, this: JObject<'local>, model_id: JString<'local>, @@ -137,7 +137,7 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsIsLoadedVoic } #[no_mangle] -pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsAudioQuery<'local>( +extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsAudioQuery<'local>( env: JNIEnv<'local>, this: JObject<'local>, text: JString<'local>, @@ -175,7 +175,7 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsAudioQuery<' } #[no_mangle] -pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsAccentPhrases<'local>( +extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsAccentPhrases<'local>( env: JNIEnv<'local>, this: JObject<'local>, text: JString<'local>, @@ -213,7 +213,7 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsAccentPhrase } #[no_mangle] -pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsReplaceMoraData<'local>( +extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsReplaceMoraData<'local>( env: JNIEnv<'local>, this: JObject<'local>, accent_phrases_json: JString<'local>, @@ -244,7 +244,7 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsReplaceMoraD } #[no_mangle] -pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsReplacePhonemeLength<'local>( +extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsReplacePhonemeLength<'local>( env: JNIEnv<'local>, this: JObject<'local>, accent_phrases_json: JString<'local>, @@ -276,7 +276,7 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsReplacePhone } #[no_mangle] -pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsReplaceMoraPitch<'local>( +extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsReplaceMoraPitch<'local>( env: JNIEnv<'local>, this: JObject<'local>, accent_phrases_json: JString<'local>, @@ -307,7 +307,7 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsReplaceMoraP } #[no_mangle] -pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsSynthesis<'local>( +extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsSynthesis<'local>( env: JNIEnv<'local>, this: JObject<'local>, query_json: JString<'local>, @@ -344,7 +344,7 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsSynthesis<'l } #[no_mangle] -pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsTts<'local>( +extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsTts<'local>( env: JNIEnv<'local>, this: JObject<'local>, query_json: JString<'local>, @@ -382,7 +382,7 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsTts<'local>( } #[no_mangle] -pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsDrop<'local>( +extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsDrop<'local>( env: JNIEnv<'local>, this: JObject<'local>, ) { diff --git a/crates/voicevox_core_java_api/src/user_dict.rs b/crates/voicevox_core_java_api/src/user_dict.rs index 0f496bad4..384626de4 100644 --- a/crates/voicevox_core_java_api/src/user_dict.rs +++ b/crates/voicevox_core_java_api/src/user_dict.rs @@ -9,7 +9,7 @@ use jni::{ }; #[no_mangle] -pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsNew<'local>( +extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsNew<'local>( env: JNIEnv<'local>, this: JObject<'local>, ) { @@ -23,7 +23,7 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsNew<'local>( } #[no_mangle] -pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsAddWord<'local>( +extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsAddWord<'local>( env: JNIEnv<'local>, this: JObject<'local>, word_json: JString<'local>, @@ -52,7 +52,7 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsAddWord<'local> } #[no_mangle] -pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsUpdateWord<'local>( +extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsUpdateWord<'local>( env: JNIEnv<'local>, this: JObject<'local>, uuid: JString<'local>, @@ -81,7 +81,7 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsUpdateWord<'loc } #[no_mangle] -pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsRemoveWord<'local>( +extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsRemoveWord<'local>( env: JNIEnv<'local>, this: JObject<'local>, uuid: JString<'local>, @@ -105,7 +105,7 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsRemoveWord<'loc } #[no_mangle] -pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsImportDict<'local>( +extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsImportDict<'local>( env: JNIEnv<'local>, this: JObject<'local>, other_dict: JObject<'local>, @@ -134,7 +134,7 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsImportDict<'loc } #[no_mangle] -pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsLoad<'local>( +extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsLoad<'local>( env: JNIEnv<'local>, this: JObject<'local>, path: JString<'local>, @@ -158,7 +158,7 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsLoad<'local>( } #[no_mangle] -pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsSave<'local>( +extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsSave<'local>( env: JNIEnv<'local>, this: JObject<'local>, path: JString<'local>, @@ -182,7 +182,7 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsSave<'local>( } #[no_mangle] -pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsGetWords<'local>( +extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsGetWords<'local>( env: JNIEnv<'local>, this: JObject<'local>, ) -> jobject { @@ -204,7 +204,7 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsGetWords<'local } #[no_mangle] -pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsDrop<'local>( +extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsDrop<'local>( env: JNIEnv<'local>, this: JObject<'local>, ) { @@ -215,7 +215,7 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsDrop<'local>( } #[no_mangle] -pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsToZenkaku<'local>( +extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsToZenkaku<'local>( env: JNIEnv<'local>, _cls: JClass<'local>, text: JString<'local>, @@ -232,7 +232,7 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsToZenkaku<'loca } #[no_mangle] -pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsValidatePronunciation<'local>( +extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsValidatePronunciation<'local>( env: JNIEnv<'local>, _cls: JClass<'local>, text: JString<'local>, diff --git a/crates/voicevox_core_java_api/src/voice_model.rs b/crates/voicevox_core_java_api/src/voice_model.rs index 4f75b08fe..35630d16e 100644 --- a/crates/voicevox_core_java_api/src/voice_model.rs +++ b/crates/voicevox_core_java_api/src/voice_model.rs @@ -8,7 +8,7 @@ use jni::{ }; #[no_mangle] -pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_VoiceModel_rsFromPath<'local>( +extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_VoiceModel_rsFromPath<'local>( env: JNIEnv<'local>, this: JObject<'local>, model_path: JString<'local>, @@ -26,7 +26,7 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_VoiceModel_rsFromPath<'loc } #[no_mangle] -pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_VoiceModel_rsGetId<'local>( +extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_VoiceModel_rsGetId<'local>( env: JNIEnv<'local>, this: JObject<'local>, ) -> jobject { @@ -45,7 +45,7 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_VoiceModel_rsGetId<'local> } #[no_mangle] -pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_VoiceModel_rsGetMetasJson<'local>( +extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_VoiceModel_rsGetMetasJson<'local>( env: JNIEnv<'local>, this: JObject<'local>, ) -> jobject { @@ -62,7 +62,7 @@ pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_VoiceModel_rsGetMetasJson< } #[no_mangle] -pub extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_VoiceModel_rsDrop<'local>( +extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_VoiceModel_rsDrop<'local>( env: JNIEnv<'local>, this: JObject<'local>, ) { From 02b87c64198a170f3f84eb4c770cf94b571b0678 Mon Sep 17 00:00:00 2001 From: sevenc-nanashi Date: Wed, 16 Aug 2023 19:23:18 +0900 Subject: [PATCH 78/99] Change: as jboolean -> into() Co-Authored-By: qryxip --- crates/voicevox_core_java_api/src/synthesizer.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/voicevox_core_java_api/src/synthesizer.rs b/crates/voicevox_core_java_api/src/synthesizer.rs index fed53992f..c7ac9d533 100644 --- a/crates/voicevox_core_java_api/src/synthesizer.rs +++ b/crates/voicevox_core_java_api/src/synthesizer.rs @@ -133,7 +133,8 @@ extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsIsLoadedVoiceMod }; Ok(is_loaded) - }) as jboolean + }) + .into() } #[no_mangle] From 1d9b0a568d9ccd430d93ac817c24399ecbbfd015 Mon Sep 17 00:00:00 2001 From: sevenc-nanashi Date: Wed, 16 Aug 2023 19:32:10 +0900 Subject: [PATCH 79/99] =?UTF-8?q?Change:=20=E6=95=B4=E6=95=B0=E3=81=AE?= =?UTF-8?q?=E7=AF=84=E5=9B=B2=E3=81=AE=E3=83=81=E3=82=A7=E3=83=83=E3=82=AF?= =?UTF-8?q?=E3=82=92Java=E5=81=B4=E3=81=A7=E8=A1=8C=E3=81=86=E3=82=88?= =?UTF-8?q?=E3=81=86=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: qryxip --- .../Hiroshiba/VoicevoxCore/Synthesizer.java | 43 ++++++++++++++----- .../java/jp/Hiroshiba/VoicevoxCore/Utils.java | 15 +++++++ .../voicevox_core_java_api/src/synthesizer.rs | 8 +--- 3 files changed, 50 insertions(+), 16 deletions(-) create mode 100644 crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Utils.java diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Synthesizer.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Synthesizer.java index cbacdcd06..3510ec473 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Synthesizer.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Synthesizer.java @@ -50,13 +50,16 @@ public boolean isLoadedVoiceModel(String voiceModelId) { /** * {@link AudioQuery} を生成する。 * - * @param text テキスト。 + * @param text テキスト。 * @param styleId スタイルID。 * @param options {@link AudioQueryOption} のセット。 * @return 話者とテキストから生成された {@link AudioQuery}。 */ @Nonnull public AudioQuery audioQuery(String text, int styleId, EnumSet options) { + if (!Utils.isU32(styleId)) { + throw new IllegalArgumentException("styleId"); + } boolean kana = options.contains(AudioQueryOption.KANA); String queryJson = rsAudioQuery(text, styleId, kana); Gson gson = new Gson(); @@ -71,7 +74,7 @@ public AudioQuery audioQuery(String text, int styleId, EnumSet /** * {@link AccentPhrase} の配列を生成する。 * - * @param text テキスト。 + * @param text テキスト。 * @param styleId スタイルID。 * @param options {@link AudioQueryOption} のセット。 * @return 話者とテキストから生成された {@link AccentPhrase} の配列。 @@ -79,6 +82,9 @@ public AudioQuery audioQuery(String text, int styleId, EnumSet @Nonnull public List createAccentPhrases( String text, int styleId, EnumSet options) { + if (!Utils.isU32(styleId)) { + throw new IllegalArgumentException("styleId"); + } boolean kana = options.contains(AccentPhrasesOption.KANA); String accentPhrasesJson = rsAccentPhrases(text, styleId, kana); Gson gson = new Gson(); @@ -93,11 +99,14 @@ public List createAccentPhrases( * アクセント句の音高・音素長を変更する。 * * @param accentPhrases 変更元のアクセント句の配列。 - * @param styleId スタイルID。 + * @param styleId スタイルID。 * @return 変更後のアクセント句の配列。 */ @Nonnull public List replaceMoraData(List accentPhrases, int styleId) { + if (!Utils.isU32(styleId)) { + throw new IllegalArgumentException("styleId"); + } String accentPhrasesJson = new Gson().toJson(accentPhrases); String replacedAccentPhrasesJson = rsReplaceMoraData(accentPhrasesJson, styleId, false); return new ArrayList<>( @@ -108,11 +117,14 @@ public List replaceMoraData(List accentPhrases, int * アクセント句の音素長を変更する。 * * @param accentPhrases 変更元のアクセント句の配列。 - * @param styleId スタイルID。 + * @param styleId スタイルID。 * @return 変更後のアクセント句の配列。 */ @Nonnull public List replacePhonemeLength(List accentPhrases, int styleId) { + if (!Utils.isU32(styleId)) { + throw new IllegalArgumentException("styleId"); + } String accentPhrasesJson = new Gson().toJson(accentPhrases); String replacedAccentPhrasesJson = rsReplacePhonemeLength(accentPhrasesJson, styleId, false); return new ArrayList<>( @@ -123,11 +135,14 @@ public List replacePhonemeLength(List accentPhrases, * アクセント句の音高を変更する。 * * @param accentPhrases 変更元のアクセント句の配列。 - * @param styleId スタイルID。 + * @param styleId スタイルID。 * @return 変更後のアクセント句の配列。 */ @Nonnull public List replaceMoraPitch(List accentPhrases, int styleId) { + if (!Utils.isU32(styleId)) { + throw new IllegalArgumentException("styleId"); + } String accentPhrasesJson = new Gson().toJson(accentPhrases); String replacedAccentPhrasesJson = rsReplaceMoraPitch(accentPhrasesJson, styleId, false); return new ArrayList<>( @@ -138,14 +153,16 @@ public List replaceMoraPitch(List accentPhrases, int * {@link AudioQuery} から音声合成する。 * * @param audioQuery {@link AudioQuery}。 - * @param styleId スタイルID。 - * @param options {@link SynthesisOption} のセット。 + * @param styleId スタイルID。 + * @param options {@link SynthesisOption} のセット。 * @return WAVデータ。 */ @Nonnull public byte[] synthesis(AudioQuery audioQuery, int styleId, EnumSet options) { - boolean enableInterrogativeUpspeak = - options.contains(SynthesisOption.ENABLE_INTERROGATIVE_UPSPEAK); + if (!Utils.isU32(styleId)) { + throw new IllegalArgumentException("styleId"); + } + boolean enableInterrogativeUpspeak = options.contains(SynthesisOption.ENABLE_INTERROGATIVE_UPSPEAK); Gson gson = new Gson(); String queryJson = gson.toJson(audioQuery); return rsSynthesis(queryJson, styleId, enableInterrogativeUpspeak); @@ -154,13 +171,16 @@ public byte[] synthesis(AudioQuery audioQuery, int styleId, EnumSet options) { + if (!Utils.isU32(styleId)) { + throw new IllegalArgumentException("styleId"); + } boolean kana = options.contains(TtsOption.KANA); boolean enableInterrogativeUpspeak = options.contains(TtsOption.ENABLE_INTERROGATIVE_UPSPEAK); return rsTts(text, styleId, kana, enableInterrogativeUpspeak); @@ -248,6 +268,9 @@ public Builder accelerationMode(AccelerationMode accelerationMode) { * @return ビルダー。 */ public Builder cpuNumThreads(int cpuNumThreads) { + if (Utils.isU16(cpuNumThreads)) { + throw new IllegalArgumentException("cpuNumThreads"); + } this.cpuNumThreads = cpuNumThreads; return this; } diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Utils.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Utils.java new file mode 100644 index 000000000..3d46e97d0 --- /dev/null +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Utils.java @@ -0,0 +1,15 @@ +package jp.Hiroshiba.VoicevoxCore; + +class Utils { + static boolean isU8(int value) { + return value >= 0 && value <= 255; + } + + static boolean isU16(int value) { + return value >= 0 && value <= 65535; + } + + static boolean isU32(long value) { + return value >= 0 && value <= 4294967295L; + } +} diff --git a/crates/voicevox_core_java_api/src/synthesizer.rs b/crates/voicevox_core_java_api/src/synthesizer.rs index c7ac9d533..0ef0ff150 100644 --- a/crates/voicevox_core_java_api/src/synthesizer.rs +++ b/crates/voicevox_core_java_api/src/synthesizer.rs @@ -44,14 +44,10 @@ extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsNewWithInitializ }; } let cpu_num_threads = env.get_field(&builder, "cpuNumThreads", "I")?; - if let Ok(cpu_num_threads) = cpu_num_threads.i() { - options.cpu_num_threads = cpu_num_threads as u16; - } + options.cpu_num_threads = cpu_num_threads.i().expect("cpuNumThreads is not integer") as u16; let load_all_models = env.get_field(&builder, "loadAllModels", "Z")?; - if let Ok(load_all_models) = load_all_models.z() { - options.load_all_models = load_all_models; - } + options.load_all_models = load_all_models.z().expect("loadAllModels is not boolean"); let open_jtalk = unsafe { env.get_rust_field::<_, _, Arc>(&open_jtalk, "handle")? From 30d5c59f1211749ea10c1ee6e0f69f52a4cfa46e Mon Sep 17 00:00:00 2001 From: sevenc-nanashi Date: Wed, 16 Aug 2023 20:04:51 +0900 Subject: [PATCH 80/99] =?UTF-8?q?Change:=20unsafe=E3=82=92=E9=96=A2?= =?UTF-8?q?=E6=95=B0=E3=81=AB=E7=A7=BB=E5=8B=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: qryxip --- .../voicevox_core_java_api/src/open_jtalk.rs | 28 ++--- .../voicevox_core_java_api/src/synthesizer.rs | 116 ++++++++---------- .../voicevox_core_java_api/src/user_dict.rs | 81 ++++++------ .../voicevox_core_java_api/src/voice_model.rs | 26 ++-- 4 files changed, 114 insertions(+), 137 deletions(-) diff --git a/crates/voicevox_core_java_api/src/open_jtalk.rs b/crates/voicevox_core_java_api/src/open_jtalk.rs index 128f053fb..5b13fe406 100644 --- a/crates/voicevox_core_java_api/src/open_jtalk.rs +++ b/crates/voicevox_core_java_api/src/open_jtalk.rs @@ -6,20 +6,20 @@ use jni::{ JNIEnv, }; #[no_mangle] -extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_OpenJtalk_rsNewWithoutDic<'local>( +unsafe extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_OpenJtalk_rsNewWithoutDic<'local>( env: JNIEnv<'local>, this: JObject<'local>, ) { throw_if_err(env, (), |env| { let internal = voicevox_core::OpenJtalk::new_without_dic(); - unsafe { env.set_rust_field(&this, "handle", Arc::new(internal)) }?; + env.set_rust_field(&this, "handle", Arc::new(internal))?; Ok(()) }) } #[no_mangle] -extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_OpenJtalk_rsNewWithInitialize<'local>( +unsafe extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_OpenJtalk_rsNewWithInitialize<'local>( env: JNIEnv<'local>, this: JObject<'local>, open_jtalk_dict_dir: JString<'local>, @@ -29,28 +29,26 @@ extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_OpenJtalk_rsNewWithInitialize< let open_jtalk_dict_dir = open_jtalk_dict_dir.to_str()?; let internal = voicevox_core::OpenJtalk::new_with_initialize(open_jtalk_dict_dir)?; - unsafe { env.set_rust_field(&this, "handle", Arc::new(internal)) }?; + env.set_rust_field(&this, "handle", Arc::new(internal))?; Ok(()) }) } #[no_mangle] -extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_OpenJtalk_rsUseUserDict<'local>( +unsafe extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_OpenJtalk_rsUseUserDict<'local>( env: JNIEnv<'local>, this: JObject<'local>, user_dict: JObject<'local>, ) { throw_if_err(env, (), |env| { - let internal = unsafe { - env.get_rust_field::<_, _, Arc>(&this, "handle")? - .clone() - }; + let internal = env + .get_rust_field::<_, _, Arc>(&this, "handle")? + .clone(); - let user_dict = unsafe { - env.get_rust_field::<_, _, Arc>>(&user_dict, "handle")? - .clone() - }; + let user_dict = env + .get_rust_field::<_, _, Arc>>(&user_dict, "handle")? + .clone(); { let user_dict = user_dict.lock().unwrap(); @@ -62,12 +60,12 @@ extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_OpenJtalk_rsUseUserDict<'local } #[no_mangle] -extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_OpenJtalk_rsDrop<'local>( +unsafe extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_OpenJtalk_rsDrop<'local>( env: JNIEnv<'local>, this: JObject<'local>, ) { throw_if_err(env, (), |env| { - unsafe { env.take_rust_field(&this, "handle") }?; + env.take_rust_field(&this, "handle")?; Ok(()) }) } diff --git a/crates/voicevox_core_java_api/src/synthesizer.rs b/crates/voicevox_core_java_api/src/synthesizer.rs index 0ef0ff150..f1186cd35 100644 --- a/crates/voicevox_core_java_api/src/synthesizer.rs +++ b/crates/voicevox_core_java_api/src/synthesizer.rs @@ -12,7 +12,7 @@ use jni::{ use std::sync::{Arc, Mutex}; #[no_mangle] -extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsNewWithInitialize<'local>( +unsafe extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsNewWithInitialize<'local>( env: JNIEnv<'local>, this: JObject<'local>, open_jtalk: JObject<'local>, @@ -49,34 +49,31 @@ extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsNewWithInitializ let load_all_models = env.get_field(&builder, "loadAllModels", "Z")?; options.load_all_models = load_all_models.z().expect("loadAllModels is not boolean"); - let open_jtalk = unsafe { - env.get_rust_field::<_, _, Arc>(&open_jtalk, "handle")? - .clone() - }; + let open_jtalk = env + .get_rust_field::<_, _, Arc>(&open_jtalk, "handle")? + .clone(); let internal = RUNTIME.block_on(voicevox_core::Synthesizer::new_with_initialize( open_jtalk, Box::leak(Box::new(options)), ))?; - unsafe { env.set_rust_field(&this, "handle", Arc::new(Mutex::new(internal)))? }; + env.set_rust_field(&this, "handle", Arc::new(Mutex::new(internal)))?; Ok(()) }) } #[no_mangle] -extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsLoadVoiceModel<'local>( +unsafe extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsLoadVoiceModel<'local>( env: JNIEnv<'local>, this: JObject<'local>, model: JObject<'local>, ) { throw_if_err(env, (), |env| { - let model = unsafe { - env.get_rust_field::<_, _, Arc>(&model, "handle")? - .clone() - }; - let internal = unsafe { - env.get_rust_field::<_, _, Arc>>(&this, "handle")? - .clone() - }; + let model = env + .get_rust_field::<_, _, Arc>(&model, "handle")? + .clone(); + let internal = env + .get_rust_field::<_, _, Arc>>(&this, "handle")? + .clone(); { let mut internal = internal.lock().unwrap(); RUNTIME.block_on(internal.load_voice_model(&model))?; @@ -86,7 +83,7 @@ extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsLoadVoiceModel<' } #[no_mangle] -extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsUnloadVoiceModel<'local>( +unsafe extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsUnloadVoiceModel<'local>( env: JNIEnv<'local>, this: JObject<'local>, model_id: JString<'local>, @@ -94,10 +91,9 @@ extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsUnloadVoiceModel throw_if_err(env, (), |env| { let model_id: String = env.get_string(&model_id)?.into(); - let internal = unsafe { - env.get_rust_field::<_, _, Arc>>(&this, "handle")? - .clone() - }; + let internal = env + .get_rust_field::<_, _, Arc>>(&this, "handle")? + .clone(); { let mut internal = internal.lock().unwrap(); @@ -110,7 +106,9 @@ extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsUnloadVoiceModel } #[no_mangle] -extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsIsLoadedVoiceModel<'local>( +unsafe extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsIsLoadedVoiceModel< + 'local, +>( env: JNIEnv<'local>, this: JObject<'local>, model_id: JString<'local>, @@ -118,10 +116,9 @@ extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsIsLoadedVoiceMod throw_if_err(env, false, |env| { let model_id: String = env.get_string(&model_id)?.into(); - let internal = unsafe { - env.get_rust_field::<_, _, Arc>>(&this, "handle")? - .clone() - }; + let internal = env + .get_rust_field::<_, _, Arc>>(&this, "handle")? + .clone(); let is_loaded = { let internal = internal.lock().unwrap(); @@ -134,7 +131,7 @@ extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsIsLoadedVoiceMod } #[no_mangle] -extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsAudioQuery<'local>( +unsafe extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsAudioQuery<'local>( env: JNIEnv<'local>, this: JObject<'local>, text: JString<'local>, @@ -145,10 +142,9 @@ extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsAudioQuery<'loca let text: String = env.get_string(&text)?.into(); let style_id = style_id as u32; - let internal = unsafe { - env.get_rust_field::<_, _, Arc>>(&this, "handle")? - .clone() - }; + let internal = env + .get_rust_field::<_, _, Arc>>(&this, "handle")? + .clone(); let audio_query = { let internal = internal.lock().unwrap(); @@ -172,7 +168,7 @@ extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsAudioQuery<'loca } #[no_mangle] -extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsAccentPhrases<'local>( +unsafe extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsAccentPhrases<'local>( env: JNIEnv<'local>, this: JObject<'local>, text: JString<'local>, @@ -183,10 +179,9 @@ extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsAccentPhrases<'l let text: String = env.get_string(&text)?.into(); let style_id = style_id as u32; - let internal = unsafe { - env.get_rust_field::<_, _, Arc>>(&this, "handle")? - .clone() - }; + let internal = env + .get_rust_field::<_, _, Arc>>(&this, "handle")? + .clone(); let accent_phrases = { let internal = internal.lock().unwrap(); @@ -210,7 +205,7 @@ extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsAccentPhrases<'l } #[no_mangle] -extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsReplaceMoraData<'local>( +unsafe extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsReplaceMoraData<'local>( env: JNIEnv<'local>, this: JObject<'local>, accent_phrases_json: JString<'local>, @@ -222,10 +217,9 @@ extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsReplaceMoraData< serde_json::from_str(&accent_phrases_json)?; let style_id = style_id as u32; - let internal = unsafe { - env.get_rust_field::<_, _, Arc>>(&this, "handle")? - .clone() - }; + let internal = env + .get_rust_field::<_, _, Arc>>(&this, "handle")? + .clone(); let replaced_accent_phrases = { let internal = internal.lock().unwrap(); @@ -241,7 +235,9 @@ extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsReplaceMoraData< } #[no_mangle] -extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsReplacePhonemeLength<'local>( +unsafe extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsReplacePhonemeLength< + 'local, +>( env: JNIEnv<'local>, this: JObject<'local>, accent_phrases_json: JString<'local>, @@ -253,10 +249,9 @@ extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsReplacePhonemeLe serde_json::from_str(&accent_phrases_json)?; let style_id = style_id as u32; - let internal = unsafe { - env.get_rust_field::<_, _, Arc>>(&this, "handle")? - .clone() - }; + let internal = env + .get_rust_field::<_, _, Arc>>(&this, "handle")? + .clone(); let replaced_accent_phrases = { let internal = internal.lock().unwrap(); @@ -273,7 +268,7 @@ extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsReplacePhonemeLe } #[no_mangle] -extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsReplaceMoraPitch<'local>( +unsafe extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsReplaceMoraPitch<'local>( env: JNIEnv<'local>, this: JObject<'local>, accent_phrases_json: JString<'local>, @@ -285,10 +280,9 @@ extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsReplaceMoraPitch serde_json::from_str(&accent_phrases_json)?; let style_id = style_id as u32; - let internal = unsafe { - env.get_rust_field::<_, _, Arc>>(&this, "handle")? - .clone() - }; + let internal = env + .get_rust_field::<_, _, Arc>>(&this, "handle")? + .clone(); let replaced_accent_phrases = { let internal = internal.lock().unwrap(); @@ -304,7 +298,7 @@ extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsReplaceMoraPitch } #[no_mangle] -extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsSynthesis<'local>( +unsafe extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsSynthesis<'local>( env: JNIEnv<'local>, this: JObject<'local>, query_json: JString<'local>, @@ -316,10 +310,9 @@ extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsSynthesis<'local let audio_query: voicevox_core::AudioQueryModel = serde_json::from_str(&audio_query)?; let style_id = style_id as u32; - let internal = unsafe { - env.get_rust_field::<_, _, Arc>>(&this, "handle")? - .clone() - }; + let internal = env + .get_rust_field::<_, _, Arc>>(&this, "handle")? + .clone(); let wave = { let internal = internal.lock().unwrap(); @@ -341,7 +334,7 @@ extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsSynthesis<'local } #[no_mangle] -extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsTts<'local>( +unsafe extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsTts<'local>( env: JNIEnv<'local>, this: JObject<'local>, query_json: JString<'local>, @@ -353,10 +346,9 @@ extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsTts<'local>( let text: String = env.get_string(&query_json)?.into(); let style_id = style_id as u32; - let internal = unsafe { - env.get_rust_field::<_, _, Arc>>(&this, "handle")? - .clone() - }; + let internal = env + .get_rust_field::<_, _, Arc>>(&this, "handle")? + .clone(); let wave = { let internal = internal.lock().unwrap(); @@ -379,12 +371,12 @@ extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsTts<'local>( } #[no_mangle] -extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsDrop<'local>( +unsafe extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsDrop<'local>( env: JNIEnv<'local>, this: JObject<'local>, ) { throw_if_err(env, (), |env| { - unsafe { env.take_rust_field(&this, "handle") }?; + env.take_rust_field(&this, "handle")?; Ok(()) }) } diff --git a/crates/voicevox_core_java_api/src/user_dict.rs b/crates/voicevox_core_java_api/src/user_dict.rs index 384626de4..cc403e408 100644 --- a/crates/voicevox_core_java_api/src/user_dict.rs +++ b/crates/voicevox_core_java_api/src/user_dict.rs @@ -9,30 +9,29 @@ use jni::{ }; #[no_mangle] -extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsNew<'local>( +unsafe extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsNew<'local>( env: JNIEnv<'local>, this: JObject<'local>, ) { throw_if_err(env, (), |env| { let internal = voicevox_core::UserDict::new(); - unsafe { env.set_rust_field(&this, "handle", Arc::new(Mutex::new(internal))) }?; + env.set_rust_field(&this, "handle", Arc::new(Mutex::new(internal)))?; Ok(()) }) } #[no_mangle] -extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsAddWord<'local>( +unsafe extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsAddWord<'local>( env: JNIEnv<'local>, this: JObject<'local>, word_json: JString<'local>, ) -> jobject { throw_if_err(env, std::ptr::null_mut(), |env| { - let internal = unsafe { - env.get_rust_field::<_, _, Arc>>(&this, "handle")? - .clone() - }; + let internal = env + .get_rust_field::<_, _, Arc>>(&this, "handle")? + .clone(); let word_json = env.get_string(&word_json)?; let word_json = word_json.to_str()?; @@ -52,17 +51,16 @@ extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsAddWord<'local>( } #[no_mangle] -extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsUpdateWord<'local>( +unsafe extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsUpdateWord<'local>( env: JNIEnv<'local>, this: JObject<'local>, uuid: JString<'local>, word_json: JString<'local>, ) { throw_if_err(env, (), |env| { - let internal = unsafe { - env.get_rust_field::<_, _, Arc>>(&this, "handle")? - .clone() - }; + let internal = env + .get_rust_field::<_, _, Arc>>(&this, "handle")? + .clone(); let uuid = env.get_string(&uuid)?; let uuid = uuid.to_str()?.parse()?; @@ -81,16 +79,15 @@ extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsUpdateWord<'local>( } #[no_mangle] -extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsRemoveWord<'local>( +unsafe extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsRemoveWord<'local>( env: JNIEnv<'local>, this: JObject<'local>, uuid: JString<'local>, ) { throw_if_err(env, (), |env| { - let internal = unsafe { - env.get_rust_field::<_, _, Arc>>(&this, "handle")? - .clone() - }; + let internal = env + .get_rust_field::<_, _, Arc>>(&this, "handle")? + .clone(); let uuid = env.get_string(&uuid)?; let uuid = uuid.to_str()?.parse()?; @@ -105,23 +102,18 @@ extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsRemoveWord<'local>( } #[no_mangle] -extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsImportDict<'local>( +unsafe extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsImportDict<'local>( env: JNIEnv<'local>, this: JObject<'local>, other_dict: JObject<'local>, ) { throw_if_err(env, (), |env| { - let internal = unsafe { - env.get_rust_field::<_, _, Arc>>(&this, "handle")? - .clone() - }; - let other_dict = unsafe { - env.get_rust_field::<_, _, Arc>>( - &other_dict, - "handle", - )? - .clone() - }; + let internal = env + .get_rust_field::<_, _, Arc>>(&this, "handle")? + .clone(); + let other_dict = env + .get_rust_field::<_, _, Arc>>(&other_dict, "handle")? + .clone(); { let mut internal = internal.lock().unwrap(); @@ -134,16 +126,15 @@ extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsImportDict<'local>( } #[no_mangle] -extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsLoad<'local>( +unsafe extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsLoad<'local>( env: JNIEnv<'local>, this: JObject<'local>, path: JString<'local>, ) { throw_if_err(env, (), |env| { - let internal = unsafe { - env.get_rust_field::<_, _, Arc>>(&this, "handle")? - .clone() - }; + let internal = env + .get_rust_field::<_, _, Arc>>(&this, "handle")? + .clone(); let path = env.get_string(&path)?; let path = path.to_str()?; @@ -158,16 +149,15 @@ extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsLoad<'local>( } #[no_mangle] -extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsSave<'local>( +unsafe extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsSave<'local>( env: JNIEnv<'local>, this: JObject<'local>, path: JString<'local>, ) { throw_if_err(env, (), |env| { - let internal = unsafe { - env.get_rust_field::<_, _, Arc>>(&this, "handle")? - .clone() - }; + let internal = env + .get_rust_field::<_, _, Arc>>(&this, "handle")? + .clone(); let path = env.get_string(&path)?; let path = path.to_str()?; @@ -182,15 +172,14 @@ extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsSave<'local>( } #[no_mangle] -extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsGetWords<'local>( +unsafe extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsGetWords<'local>( env: JNIEnv<'local>, this: JObject<'local>, ) -> jobject { throw_if_err(env, std::ptr::null_mut(), |env| { - let internal = unsafe { - env.get_rust_field::<_, _, Arc>>(&this, "handle")? - .clone() - }; + let internal = env + .get_rust_field::<_, _, Arc>>(&this, "handle")? + .clone(); let words = { let internal = internal.lock().unwrap(); @@ -204,12 +193,12 @@ extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsGetWords<'local>( } #[no_mangle] -extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsDrop<'local>( +unsafe extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsDrop<'local>( env: JNIEnv<'local>, this: JObject<'local>, ) { throw_if_err(env, (), |env| { - unsafe { env.take_rust_field(&this, "handle") }?; + env.take_rust_field(&this, "handle")?; Ok(()) }) } diff --git a/crates/voicevox_core_java_api/src/voice_model.rs b/crates/voicevox_core_java_api/src/voice_model.rs index 35630d16e..03e9d916e 100644 --- a/crates/voicevox_core_java_api/src/voice_model.rs +++ b/crates/voicevox_core_java_api/src/voice_model.rs @@ -8,7 +8,7 @@ use jni::{ }; #[no_mangle] -extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_VoiceModel_rsFromPath<'local>( +unsafe extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_VoiceModel_rsFromPath<'local>( env: JNIEnv<'local>, this: JObject<'local>, model_path: JString<'local>, @@ -19,22 +19,21 @@ extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_VoiceModel_rsFromPath<'local>( let internal = RUNTIME.block_on(voicevox_core::VoiceModel::from_path(model_path))?; - unsafe { env.set_rust_field(&this, "handle", Arc::new(internal)) }?; + env.set_rust_field(&this, "handle", Arc::new(internal))?; Ok(()) }) } #[no_mangle] -extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_VoiceModel_rsGetId<'local>( +unsafe extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_VoiceModel_rsGetId<'local>( env: JNIEnv<'local>, this: JObject<'local>, ) -> jobject { throw_if_err(env, std::ptr::null_mut(), |env| { - let internal = unsafe { - env.get_rust_field::<_, _, Arc>(&this, "handle")? - .clone() - }; + let internal = env + .get_rust_field::<_, _, Arc>(&this, "handle")? + .clone(); let id = internal.id().raw_voice_model_id(); @@ -45,15 +44,14 @@ extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_VoiceModel_rsGetId<'local>( } #[no_mangle] -extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_VoiceModel_rsGetMetasJson<'local>( +unsafe extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_VoiceModel_rsGetMetasJson<'local>( env: JNIEnv<'local>, this: JObject<'local>, ) -> jobject { throw_if_err(env, std::ptr::null_mut(), |env| { - let internal = unsafe { - env.get_rust_field::<_, _, Arc>(&this, "handle")? - .clone() - }; + let internal = env + .get_rust_field::<_, _, Arc>(&this, "handle")? + .clone(); let metas = internal.metas(); let metas_json = serde_json::to_string(&metas)?; @@ -62,12 +60,12 @@ extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_VoiceModel_rsGetMetasJson<'loc } #[no_mangle] -extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_VoiceModel_rsDrop<'local>( +unsafe extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_VoiceModel_rsDrop<'local>( env: JNIEnv<'local>, this: JObject<'local>, ) { throw_if_err(env, (), |env| { - unsafe { env.take_rust_field(&this, "handle") }?; + env.take_rust_field(&this, "handle")?; Ok(()) }) } From 86e6a8b105047887db52d96117061a2d20a87b26 Mon Sep 17 00:00:00 2001 From: sevenc-nanashi Date: Wed, 16 Aug 2023 20:11:54 +0900 Subject: [PATCH 81/99] =?UTF-8?q?Change:=20target=E5=91=A8=E3=82=8A?= =?UTF-8?q?=E3=82=92=E5=A4=89=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/test.yml | 49 +------------------ .../java/jp/Hiroshiba/VoicevoxCore/Dll.java | 2 +- .../dll/{mac-arm64 => macos-arm64}/.gitkeep | 0 .../dll/{mac-x64 => macos-x64}/.gitkeep | 0 4 files changed, 2 insertions(+), 49 deletions(-) rename crates/voicevox_core_java_api/lib/src/main/resources/dll/{mac-arm64 => macos-arm64}/.gitkeep (100%) rename crates/voicevox_core_java_api/lib/src/main/resources/dll/{mac-x64 => macos-x64}/.gitkeep (100%) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 2fa732d60..3285272a7 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -307,54 +307,7 @@ jobs: working-directory: crates/voicevox_core_java_api run: | ARCH="$(uname -m)" - case "$RUNNER_OS" in - Windows) - DLL_NAME="voicevox_core_java_api.dll" - case "$ARCH" in - x86_64) - TARGET_NAME="windows-x64" - ;; - *) - echo "Unsupported architecture: $ARCH" - exit 1 - ;; - esac - ;; - macOS) - DLL_NAME="libvoicevox_core_java_api.dylib" - case "$ARCH" in - x86_64) - TARGET_NAME="mac-x64" - ;; - arm64) - TARGET_NAME="mac-arm64" - ;; - *) - echo "Unsupported architecture: $ARCH" - exit 1 - ;; - esac - ;; - Linux) - DLL_NAME="libvoicevox_core_java_api.so" - case "$ARCH" in - x86_64) - TARGET_NAME="linux-x64" - ;; - aarch64) - TARGET_NAME="linux-arm64" - ;; - *) - echo "Unsupported architecture: $ARCH" - exit 1 - ;; - esac - ;; - *) - echo "Unsupported OS: $RUNNER_OS" - exit 1 - ;; - esac + TARGET_NAME="${RUNNER_OS,,}-${RUNNER_ARCH,,}" cp -v "../../target/debug/$DLL_NAME" "./lib/src/main/resources/dll/$TARGET_NAME/$DLL_NAME" echo "target = $TARGET_NAME, dll = $DLL_NAME" ./gradlew test --info 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 b7c88ebde..ab000efc9 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 @@ -21,7 +21,7 @@ abstract class Dll { osName = "windows"; dllName = "voicevox_core_java_api.dll"; } else if (rawOsName.startsWith("Mac")) { - osName = "mac"; + osName = "macos"; dllName = "libvoicevox_core_java_api.dylib"; } else if (rawOsName.startsWith("Linux")) { osName = "linux"; diff --git a/crates/voicevox_core_java_api/lib/src/main/resources/dll/mac-arm64/.gitkeep b/crates/voicevox_core_java_api/lib/src/main/resources/dll/macos-arm64/.gitkeep similarity index 100% rename from crates/voicevox_core_java_api/lib/src/main/resources/dll/mac-arm64/.gitkeep rename to crates/voicevox_core_java_api/lib/src/main/resources/dll/macos-arm64/.gitkeep diff --git a/crates/voicevox_core_java_api/lib/src/main/resources/dll/mac-x64/.gitkeep b/crates/voicevox_core_java_api/lib/src/main/resources/dll/macos-x64/.gitkeep similarity index 100% rename from crates/voicevox_core_java_api/lib/src/main/resources/dll/mac-x64/.gitkeep rename to crates/voicevox_core_java_api/lib/src/main/resources/dll/macos-x64/.gitkeep From cf82621eaaa4c9db58310503ea601823bc04efaa Mon Sep 17 00:00:00 2001 From: sevenc-nanashi Date: Wed, 16 Aug 2023 20:13:35 +0900 Subject: [PATCH 82/99] =?UTF-8?q?Change:=20Java=2011=E3=81=AB=E5=A4=89?= =?UTF-8?q?=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crates/voicevox_core_java_api/lib/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/voicevox_core_java_api/lib/build.gradle b/crates/voicevox_core_java_api/lib/build.gradle index c0104b7c5..3e87cceff 100644 --- a/crates/voicevox_core_java_api/lib/build.gradle +++ b/crates/voicevox_core_java_api/lib/build.gradle @@ -42,7 +42,7 @@ dependencies { // Apply a specific Java toolchain to ease working on different environments. java { toolchain { - languageVersion = JavaLanguageVersion.of(8) + languageVersion = JavaLanguageVersion.of(11) } } From 9877a6e19c13aec6e60f9e32585ddf6fe9ac8c7a Mon Sep 17 00:00:00 2001 From: sevenc-nanashi Date: Wed, 16 Aug 2023 20:14:17 +0900 Subject: [PATCH 83/99] =?UTF-8?q?Delete:=20ARCH=E3=82=92=E5=89=8A=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/test.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 3285272a7..a38236511 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -306,7 +306,6 @@ jobs: - name: 必要なDLLをコピーしてテストを実行 working-directory: crates/voicevox_core_java_api run: | - ARCH="$(uname -m)" TARGET_NAME="${RUNNER_OS,,}-${RUNNER_ARCH,,}" cp -v "../../target/debug/$DLL_NAME" "./lib/src/main/resources/dll/$TARGET_NAME/$DLL_NAME" echo "target = $TARGET_NAME, dll = $DLL_NAME" From f26ea638d3d307db3e3cc8fafd1ae275ca26b62e Mon Sep 17 00:00:00 2001 From: sevenc-nanashi Date: Wed, 16 Aug 2023 20:38:21 +0900 Subject: [PATCH 84/99] =?UTF-8?q?Fix:=20dll=E3=82=B3=E3=83=94=E3=83=BC?= =?UTF-8?q?=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/test.yml | 15 +++++++++++++++ .../Hiroshiba/VoicevoxCore/Synthesizer.java | 19 ++++++++++--------- 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index a38236511..7c6c799a3 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -306,6 +306,21 @@ jobs: - name: 必要なDLLをコピーしてテストを実行 working-directory: crates/voicevox_core_java_api run: | + case "$RUNNER_OS" in + Windows) + DLL_NAME="voicevox_core_java_api.dll" + ;; + macOS) + DLL_NAME="libvoicevox_core_java_api.dylib" + ;; + Linux) + DLL_NAME="libvoicevox_core_java_api.so" + ;; + *) + echo "Unsupported OS: $RUNNER_OS" + exit 1 + ;; + esac TARGET_NAME="${RUNNER_OS,,}-${RUNNER_ARCH,,}" cp -v "../../target/debug/$DLL_NAME" "./lib/src/main/resources/dll/$TARGET_NAME/$DLL_NAME" echo "target = $TARGET_NAME, dll = $DLL_NAME" diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Synthesizer.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Synthesizer.java index 3510ec473..51c983f21 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Synthesizer.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Synthesizer.java @@ -50,7 +50,7 @@ public boolean isLoadedVoiceModel(String voiceModelId) { /** * {@link AudioQuery} を生成する。 * - * @param text テキスト。 + * @param text テキスト。 * @param styleId スタイルID。 * @param options {@link AudioQueryOption} のセット。 * @return 話者とテキストから生成された {@link AudioQuery}。 @@ -74,7 +74,7 @@ public AudioQuery audioQuery(String text, int styleId, EnumSet /** * {@link AccentPhrase} の配列を生成する。 * - * @param text テキスト。 + * @param text テキスト。 * @param styleId スタイルID。 * @param options {@link AudioQueryOption} のセット。 * @return 話者とテキストから生成された {@link AccentPhrase} の配列。 @@ -99,7 +99,7 @@ public List createAccentPhrases( * アクセント句の音高・音素長を変更する。 * * @param accentPhrases 変更元のアクセント句の配列。 - * @param styleId スタイルID。 + * @param styleId スタイルID。 * @return 変更後のアクセント句の配列。 */ @Nonnull @@ -117,7 +117,7 @@ public List replaceMoraData(List accentPhrases, int * アクセント句の音素長を変更する。 * * @param accentPhrases 変更元のアクセント句の配列。 - * @param styleId スタイルID。 + * @param styleId スタイルID。 * @return 変更後のアクセント句の配列。 */ @Nonnull @@ -135,7 +135,7 @@ public List replacePhonemeLength(List accentPhrases, * アクセント句の音高を変更する。 * * @param accentPhrases 変更元のアクセント句の配列。 - * @param styleId スタイルID。 + * @param styleId スタイルID。 * @return 変更後のアクセント句の配列。 */ @Nonnull @@ -153,8 +153,8 @@ public List replaceMoraPitch(List accentPhrases, int * {@link AudioQuery} から音声合成する。 * * @param audioQuery {@link AudioQuery}。 - * @param styleId スタイルID。 - * @param options {@link SynthesisOption} のセット。 + * @param styleId スタイルID。 + * @param options {@link SynthesisOption} のセット。 * @return WAVデータ。 */ @Nonnull @@ -162,7 +162,8 @@ public byte[] synthesis(AudioQuery audioQuery, int styleId, EnumSet Date: Wed, 16 Aug 2023 22:24:21 +0900 Subject: [PATCH 85/99] =?UTF-8?q?Change:=20Builder=E3=83=91=E3=82=BF?= =?UTF-8?q?=E3=83=BC=E3=83=B3=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Hiroshiba/VoicevoxCore/Synthesizer.java | 272 +++++++++++++----- .../VoicevoxCore/SynthesizerTest.java | 18 +- .../Hiroshiba/VoicevoxCore/UserDictTest.java | 18 +- 3 files changed, 215 insertions(+), 93 deletions(-) diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Synthesizer.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Synthesizer.java index 51c983f21..349bc30ac 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Synthesizer.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Synthesizer.java @@ -3,7 +3,6 @@ import com.google.gson.Gson; import java.util.ArrayList; import java.util.Arrays; -import java.util.EnumSet; import java.util.List; import javax.annotation.Nonnull; @@ -48,51 +47,27 @@ public boolean isLoadedVoiceModel(String voiceModelId) { } /** - * {@link AudioQuery} を生成する。 + * {@link AudioQuery} を生成するためのオブジェクトを生成する。 * * @param text テキスト。 * @param styleId スタイルID。 - * @param options {@link AudioQueryOption} のセット。 - * @return 話者とテキストから生成された {@link AudioQuery}。 + * @return {@link CreateAudioQueryConfigurator}。 */ @Nonnull - public AudioQuery audioQuery(String text, int styleId, EnumSet options) { - if (!Utils.isU32(styleId)) { - throw new IllegalArgumentException("styleId"); - } - boolean kana = options.contains(AudioQueryOption.KANA); - String queryJson = rsAudioQuery(text, styleId, kana); - Gson gson = new Gson(); - - AudioQuery audioQuery = gson.fromJson(queryJson, AudioQuery.class); - if (audioQuery == null) { - throw new NullPointerException("audio_query"); - } - return audioQuery; + public CreateAudioQueryConfigurator createAudioQuery(String text, int styleId) { + return new CreateAudioQueryConfigurator(this, text, styleId); } /** - * {@link AccentPhrase} の配列を生成する。 + * {@link AccentPhrase} のリストを生成するためのオブジェクトを生成する。 * * @param text テキスト。 * @param styleId スタイルID。 - * @param options {@link AudioQueryOption} のセット。 - * @return 話者とテキストから生成された {@link AccentPhrase} の配列。 + * @return {@link CreateAccentPhrasesConfigurator}。 */ @Nonnull - public List createAccentPhrases( - String text, int styleId, EnumSet options) { - if (!Utils.isU32(styleId)) { - throw new IllegalArgumentException("styleId"); - } - boolean kana = options.contains(AccentPhrasesOption.KANA); - String accentPhrasesJson = rsAccentPhrases(text, styleId, kana); - Gson gson = new Gson(); - AccentPhrase[] rawAccentPhrases = gson.fromJson(accentPhrasesJson, AccentPhrase[].class); - if (rawAccentPhrases == null) { - throw new NullPointerException("accent_phrases"); - } - return new ArrayList<>(Arrays.asList(rawAccentPhrases)); + public CreateAccentPhrasesConfigurator createAccentPhrases(String text, int styleId) { + return new CreateAccentPhrasesConfigurator(this, text, styleId); } /** @@ -150,41 +125,27 @@ public List replaceMoraPitch(List accentPhrases, int } /** - * {@link AudioQuery} から音声合成する。 + * {@link AudioQuery} から音声合成するためのオブジェクトを生成する。 * * @param audioQuery {@link AudioQuery}。 * @param styleId スタイルID。 - * @param options {@link SynthesisOption} のセット。 - * @return WAVデータ。 + * @return {@link SynthesisConfigurator}。 */ @Nonnull - public byte[] synthesis(AudioQuery audioQuery, int styleId, EnumSet options) { - if (!Utils.isU32(styleId)) { - throw new IllegalArgumentException("styleId"); - } - boolean enableInterrogativeUpspeak = - options.contains(SynthesisOption.ENABLE_INTERROGATIVE_UPSPEAK); - Gson gson = new Gson(); - String queryJson = gson.toJson(audioQuery); - return rsSynthesis(queryJson, styleId, enableInterrogativeUpspeak); + public SynthesisConfigurator synthesis(AudioQuery audioQuery, int styleId) { + return new SynthesisConfigurator(this, audioQuery, styleId); } /** - * テキスト音声合成を実行する。 + * テキスト音声合成を実行するためのオブジェクトを生成する。 * * @param text テキスト。 * @param styleId スタイルID。 - * @param options {@link TtsOption} のセット。 - * @return WAVデータ。 + * @return {@link TtsConfigurator}。 */ @Nonnull - public byte[] tts(String text, int styleId, EnumSet options) { - if (!Utils.isU32(styleId)) { - throw new IllegalArgumentException("styleId"); - } - boolean kana = options.contains(TtsOption.KANA); - boolean enableInterrogativeUpspeak = options.contains(TtsOption.ENABLE_INTERROGATIVE_UPSPEAK); - return rsTts(text, styleId, kana, enableInterrogativeUpspeak); + public TtsConfigurator tts(String text, int styleId) { + return new TtsConfigurator(this, text, styleId); } /** 音声シンセサイザを破棄する。 */ @@ -309,28 +270,199 @@ public static enum AccelerationMode { } /** {@link Synthesizer#audioQuery} のオプション。 */ - public static enum AudioQueryOption { - /** 入力テキストをAquesTalk風記法として解釈するかどうか。 */ - KANA, + public class CreateAudioQueryConfigurator { + private Synthesizer synthesizer; + private String text; + private int styleId; + private boolean kana; + + private CreateAudioQueryConfigurator(Synthesizer synthesizer, String text, int styleId) { + if (!Utils.isU32(styleId)) { + throw new IllegalArgumentException("styleId"); + } + this.synthesizer = synthesizer; + this.text = text; + this.styleId = styleId; + this.kana = false; + } + + /** + * 入力テキストをAquesTalk風記法として解釈するかどうか。 + * + * @param kana 入力テキストをAquesTalk風記法として解釈するかどうか。 + * @return {@link CreateAudioQueryConfigurator}。 + */ + @Nonnull + public CreateAudioQueryConfigurator kana(boolean kana) { + this.kana = kana; + return this; + } + + /** + * {@link AudioQuery} を生成する。 + * + * @return {@link AudioQuery}。 + */ + @Nonnull + public AudioQuery execute() { + if (!Utils.isU32(styleId)) { + throw new IllegalArgumentException("styleId"); + } + String queryJson = synthesizer.rsAudioQuery(this.text, this.styleId, this.kana); + Gson gson = new Gson(); + + AudioQuery audioQuery = gson.fromJson(queryJson, AudioQuery.class); + if (audioQuery == null) { + throw new NullPointerException("audio_query"); + } + return audioQuery; + } } /** {@link Synthesizer#createAccentPhrases} のオプション。 */ - public static enum AccentPhrasesOption { - /** 入力テキストをAquesTalk風記法として解釈するかどうか。 */ - KANA, + public class CreateAccentPhrasesConfigurator { + private Synthesizer synthesizer; + private String text; + private int styleId; + private boolean kana; + + private CreateAccentPhrasesConfigurator(Synthesizer synthesizer, String text, int styleId) { + if (!Utils.isU32(styleId)) { + throw new IllegalArgumentException("styleId"); + } + this.synthesizer = synthesizer; + this.text = text; + this.styleId = styleId; + this.kana = false; + } + + /** + * 入力テキストをAquesTalk風記法として解釈するかどうか。 + * + * @param kana 入力テキストをAquesTalk風記法として解釈するかどうか。 + * @return {@link CreateAudioQueryConfigurator}。 + */ + @Nonnull + public CreateAccentPhrasesConfigurator kana(boolean kana) { + this.kana = kana; + return this; + } + + /** + * {@link AccentPhrase} のリストを取得する。 + * + * @return {@link AccentPhrase} のリスト。 + */ + @Nonnull + public List execute() { + String accentPhrasesJson = synthesizer.rsAccentPhrases(this.text, this.styleId, this.kana); + Gson gson = new Gson(); + AccentPhrase[] rawAccentPhrases = gson.fromJson(accentPhrasesJson, AccentPhrase[].class); + if (rawAccentPhrases == null) { + throw new NullPointerException("accent_phrases"); + } + return new ArrayList(Arrays.asList(rawAccentPhrases)); + } } - /** {@link Synthesizer#synthesis} のオプション。 */ - public static enum SynthesisOption { - /** 疑問文の調整を有効にするかどうか。 */ - ENABLE_INTERROGATIVE_UPSPEAK + /** {@link Synthesizer#synthesize} のオプション。 */ + public class SynthesisConfigurator { + private Synthesizer synthesizer; + private AudioQuery audioQuery; + private int styleId; + private boolean interrogativeUpspeak; + + private SynthesisConfigurator(Synthesizer synthesizer, AudioQuery audioQuery, int styleId) { + if (!Utils.isU32(styleId)) { + throw new IllegalArgumentException("styleId"); + } + this.synthesizer = synthesizer; + this.audioQuery = audioQuery; + this.styleId = styleId; + this.interrogativeUpspeak = false; + } + + /** + * 疑問文の調整を有効にするかどうか。 + * + * @param interrogativeUpspeak 疑問文の調整を有効にするかどうか。 + * @return {@link SynthesisConfigurator}。 + */ + @Nonnull + public SynthesisConfigurator interrogativeUpspeak(boolean interrogativeUpspeak) { + this.interrogativeUpspeak = interrogativeUpspeak; + return this; + } + + /** + * {@link AudioQuery} から音声合成する。 + * + * @return 音声データ。 + */ + @Nonnull + public byte[] execute() { + if (!Utils.isU32(styleId)) { + throw new IllegalArgumentException("styleId"); + } + Gson gson = new Gson(); + String queryJson = gson.toJson(this.audioQuery); + return synthesizer.rsSynthesis(queryJson, this.styleId, this.interrogativeUpspeak); + } } /** {@link Synthesizer#tts} のオプション。 */ - public static enum TtsOption { - /** 入力テキストをAquesTalk風記法として解釈するかどうか。 */ - KANA, - /** 疑問文の調整を有効にするかどうか。 */ - ENABLE_INTERROGATIVE_UPSPEAK + public class TtsConfigurator { + private Synthesizer synthesizer; + private String text; + private int styleId; + private boolean kana; + private boolean interrogativeUpspeak; + + private TtsConfigurator(Synthesizer synthesizer, String text, int styleId) { + if (!Utils.isU32(styleId)) { + throw new IllegalArgumentException("styleId"); + } + this.synthesizer = synthesizer; + this.text = text; + this.styleId = styleId; + this.kana = false; + } + + /** + * 入力テキストをAquesTalk風記法として解釈するかどうか。 + * + * @param kana 入力テキストをAquesTalk風記法として解釈するかどうか。 + * @return {@link CreateAudioQueryConfigurator}。 + */ + @Nonnull + public TtsConfigurator kana(boolean kana) { + this.kana = kana; + return this; + } + + /** + * 疑問文の調整を有効にするかどうか。 + * + * @param interrogativeUpspeak 疑問文の調整を有効にするかどうか。 + * @return {@link SynthesisConfigurator}。 + */ + @Nonnull + public TtsConfigurator interrogativeUpspeak(boolean interrogativeUpspeak) { + this.interrogativeUpspeak = interrogativeUpspeak; + return this; + } + + /** + * {@link AudioQuery} から音声合成する。 + * + * @return 音声データ。 + */ + @Nonnull + public byte[] execute() { + if (!Utils.isU32(styleId)) { + throw new IllegalArgumentException("styleId"); + } + return synthesizer.rsTts(this.text, this.styleId, this.kana, this.interrogativeUpspeak); + } } } 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 89f53c658..a48132336 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 @@ -7,7 +7,6 @@ import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; -import java.util.EnumSet; import java.util.List; import org.junit.jupiter.api.Test; @@ -51,14 +50,9 @@ void checkAudioQuery() { OpenJtalk openJtalk = loadOpenJtalk(); Synthesizer synthesizer = Synthesizer.builder(openJtalk).build(); synthesizer.loadVoiceModel(model); - AudioQuery query = - synthesizer.audioQuery( - "こんにちは", - model.metas[0].styles[0].id, - EnumSet.noneOf(Synthesizer.AudioQueryOption.class)); + AudioQuery query = synthesizer.createAudioQuery("こんにちは", model.metas[0].styles[0].id).execute(); - synthesizer.synthesis( - query, model.metas[0].styles[0].id, EnumSet.noneOf(Synthesizer.SynthesisOption.class)); + synthesizer.synthesis(query, model.metas[0].styles[0].id).execute(); } @Test @@ -68,10 +62,7 @@ void checkAccentPhrases() { Synthesizer synthesizer = Synthesizer.builder(openJtalk).build(); synthesizer.loadVoiceModel(model); List accentPhrases = - synthesizer.createAccentPhrases( - "こんにちは", - model.metas[0].styles[0].id, - EnumSet.noneOf(Synthesizer.AccentPhrasesOption.class)); + synthesizer.createAccentPhrases("こんにちは", model.metas[0].styles[0].id).execute(); List accentPhrases2 = synthesizer.replaceMoraPitch(accentPhrases, model.metas[1].styles[0].id); assertTrue( @@ -100,7 +91,6 @@ void checkTts() { OpenJtalk openJtalk = loadOpenJtalk(); Synthesizer synthesizer = Synthesizer.builder(openJtalk).build(); synthesizer.loadVoiceModel(model); - synthesizer.tts( - "こんにちは", model.metas[0].styles[0].id, EnumSet.noneOf(Synthesizer.TtsOption.class)); + synthesizer.tts("こんにちは", model.metas[0].styles[0].id).execute(); } } diff --git a/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/UserDictTest.java b/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/UserDictTest.java index ab5d80726..f92b74207 100644 --- a/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/UserDictTest.java +++ b/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/UserDictTest.java @@ -4,7 +4,6 @@ import java.nio.file.Files; import java.nio.file.Path; -import java.util.EnumSet; import org.junit.jupiter.api.Test; class UserDictTest extends TestUtils { @@ -19,17 +18,18 @@ void checkLoad() { UserDict userDict = new UserDict(); synthesizer.loadVoiceModel(model); AudioQuery query1 = - synthesizer.audioQuery( - "this_word_should_not_exist_in_default_dictionary", - model.metas[0].styles[0].id, - EnumSet.noneOf(Synthesizer.AudioQueryOption.class)); + synthesizer + .createAudioQuery( + "this_word_should_not_exist_in_default_dictionary", model.metas[0].styles[0].id) + .execute(); + userDict.addWord(new UserDict.Word("this_word_should_not_exist_in_default_dictionary", "テスト")); openJtalk.useUserDict(userDict); AudioQuery query2 = - synthesizer.audioQuery( - "this_word_should_not_exist_in_default_dictionary", - model.metas[0].styles[0].id, - EnumSet.noneOf(Synthesizer.AudioQueryOption.class)); + synthesizer + .createAudioQuery( + "this_word_should_not_exist_in_default_dictionary", model.metas[0].styles[0].id) + .execute(); assertTrue(query1.kana != query2.kana); } From d8a9ed214aea2da39e3aea38c6ef1f3db1337f33 Mon Sep 17 00:00:00 2001 From: sevenc-nanashi Date: Wed, 16 Aug 2023 22:32:07 +0900 Subject: [PATCH 86/99] Change: finalize -> Cleaner --- .../java/jp/Hiroshiba/VoicevoxCore/OpenJtalk.java | 11 +++++------ .../java/jp/Hiroshiba/VoicevoxCore/Synthesizer.java | 9 +++------ .../main/java/jp/Hiroshiba/VoicevoxCore/UserDict.java | 10 ++++------ .../java/jp/Hiroshiba/VoicevoxCore/VoiceModel.java | 8 +++----- 4 files changed, 15 insertions(+), 23 deletions(-) diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/OpenJtalk.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/OpenJtalk.java index 2b12baea7..51b0c95c1 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/OpenJtalk.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/OpenJtalk.java @@ -1,8 +1,11 @@ package jp.Hiroshiba.VoicevoxCore; +import java.lang.ref.Cleaner; + /** テキスト解析器としてのOpen JTalk。 */ public class OpenJtalk extends Dll { private long handle; + private static final Cleaner cleaner = Cleaner.create(); /** * Open JTalkの辞書ディレクトリ。 @@ -11,6 +14,8 @@ public class OpenJtalk extends Dll { */ public OpenJtalk(String openJtalkDictDir) { rsNewWithInitialize(openJtalkDictDir); + + cleaner.register(this, () -> rsDrop()); } /** @@ -24,12 +29,6 @@ public void useUserDict(UserDict userDict) { rsUseUserDict(userDict); } - /** Open JTalkを廃棄する。 */ - @Override - protected void finalize() { - rsDrop(); - } - private native void rsNewWithoutDic(); private native void rsNewWithInitialize(String openJtalkDictDir); diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Synthesizer.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Synthesizer.java index 349bc30ac..75c28bca5 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Synthesizer.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Synthesizer.java @@ -1,6 +1,7 @@ package jp.Hiroshiba.VoicevoxCore; import com.google.gson.Gson; +import java.lang.ref.Cleaner; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -13,9 +14,11 @@ */ public class Synthesizer extends Dll { private long handle; + private static final Cleaner cleaner = Cleaner.create(); private Synthesizer(OpenJtalk openJtalk, Builder builder) { rsNewWithInitialize(openJtalk, builder); + cleaner.register(this, () -> rsDrop()); } /** @@ -148,12 +151,6 @@ public TtsConfigurator tts(String text, int styleId) { return new TtsConfigurator(this, text, styleId); } - /** 音声シンセサイザを破棄する。 */ - @Override - protected void finalize() { - rsDrop(); - } - private native void rsNewWithInitialize(OpenJtalk openJtalk, Builder builder); private native void rsLoadVoiceModel(VoiceModel voiceModel); diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/UserDict.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/UserDict.java index 19e1f80a7..0574c39f8 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/UserDict.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/UserDict.java @@ -6,16 +6,20 @@ import com.google.gson.internal.LinkedTreeMap; import jakarta.validation.constraints.Max; import jakarta.validation.constraints.Min; +import java.lang.ref.Cleaner; import java.util.HashMap; import javax.annotation.Nonnull; /** ユーザー辞書。 */ public class UserDict extends Dll { private long handle; + private static final Cleaner cleaner = Cleaner.create(); /** ユーザー辞書を作成する。 */ public UserDict() { rsNew(); + + cleaner.register(this, () -> rsDrop()); } /** @@ -108,12 +112,6 @@ public HashMap toHashMap() { return words; } - /** ユーザー辞書を破棄する。 */ - @Override - protected void finalize() { - rsDrop(); - } - private native void rsNew(); @Nonnull diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/VoiceModel.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/VoiceModel.java index 76196d3e4..52d07a0bc 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/VoiceModel.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/VoiceModel.java @@ -3,11 +3,13 @@ import com.google.gson.Gson; import com.google.gson.annotations.Expose; import com.google.gson.annotations.SerializedName; +import java.lang.ref.Cleaner; import javax.annotation.Nonnull; /** 音声モデル。 */ public class VoiceModel extends Dll { private long handle; + private static final Cleaner cleaner = Cleaner.create(); /** ID。 */ @Nonnull public final String id; @@ -25,12 +27,8 @@ public VoiceModel(String modelPath) { throw new RuntimeException("Failed to parse metasJson"); } metas = rawMetas; - } - /** 音声モデルを廃棄する。 */ - @Override - protected void finalize() { - rsDrop(); + cleaner.register(this, () -> rsDrop()); } private native void rsFromPath(String modelPath); From 16ac034b5aee86e6a30b11349c83646b2c6d0206 Mon Sep 17 00:00:00 2001 From: sevenc-nanashi Date: Wed, 16 Aug 2023 22:33:18 +0900 Subject: [PATCH 87/99] Change: VAR,, -> tr --- .github/workflows/test.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 7c6c799a3..677b9ec4d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -306,6 +306,10 @@ jobs: - name: 必要なDLLをコピーしてテストを実行 working-directory: crates/voicevox_core_java_api run: | + + OS=$(tr '[:upper:]' '[:lower:]' <<<"$RUNNER_OS") + ARCH=$(tr '[:upper:]' '[:lower:]' <<<"$RUNNER_ARCH") + case "$RUNNER_OS" in Windows) DLL_NAME="voicevox_core_java_api.dll" @@ -321,7 +325,7 @@ jobs: exit 1 ;; esac - TARGET_NAME="${RUNNER_OS,,}-${RUNNER_ARCH,,}" + TARGET_NAME="$OS-$ARCH" cp -v "../../target/debug/$DLL_NAME" "./lib/src/main/resources/dll/$TARGET_NAME/$DLL_NAME" echo "target = $TARGET_NAME, dll = $DLL_NAME" ./gradlew test --info From 78bc92cb762b3ba8c98055269c3bbaa9b1eeb8ba Mon Sep 17 00:00:00 2001 From: sevenc-nanashi Date: Wed, 16 Aug 2023 23:04:48 +0900 Subject: [PATCH 88/99] =?UTF-8?q?Fix:=20javadoc=E3=81=8C=E7=94=9F=E6=88=90?= =?UTF-8?q?=E3=81=A7=E3=81=8D=E3=81=AA=E3=81=84=E3=81=AE=E3=82=92=E4=BF=AE?= =?UTF-8?q?=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/jp/Hiroshiba/VoicevoxCore/AudioQuery.java | 2 +- .../java/jp/Hiroshiba/VoicevoxCore/Synthesizer.java | 12 ++++++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/AudioQuery.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/AudioQuery.java index d10d49fc5..3f122d84b 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/AudioQuery.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/AudioQuery.java @@ -58,7 +58,7 @@ public class AudioQuery { /** * [読み取り専用] AquesTalk風記法。 * - *

{@link Synthesizer#audioQuery} が返すもののみ String となる。入力としてのAudioQueryでは無視される。 + *

{@link Synthesizer#createAudioQuery} が返すもののみ String となる。入力としてのAudioQueryでは無視される。 */ @SerializedName("kana") @Expose diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Synthesizer.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Synthesizer.java index 75c28bca5..d2cb381ba 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Synthesizer.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Synthesizer.java @@ -55,6 +55,8 @@ public boolean isLoadedVoiceModel(String voiceModelId) { * @param text テキスト。 * @param styleId スタイルID。 * @return {@link CreateAudioQueryConfigurator}。 + * + * @see CreateAudioQueryConfigurator#execute */ @Nonnull public CreateAudioQueryConfigurator createAudioQuery(String text, int styleId) { @@ -67,6 +69,8 @@ public CreateAudioQueryConfigurator createAudioQuery(String text, int styleId) { * @param text テキスト。 * @param styleId スタイルID。 * @return {@link CreateAccentPhrasesConfigurator}。 + * + * @see CreateAccentPhrasesConfigurator#execute */ @Nonnull public CreateAccentPhrasesConfigurator createAccentPhrases(String text, int styleId) { @@ -133,6 +137,8 @@ public List replaceMoraPitch(List accentPhrases, int * @param audioQuery {@link AudioQuery}。 * @param styleId スタイルID。 * @return {@link SynthesisConfigurator}。 + * + * @see SynthesisConfigurator#execute */ @Nonnull public SynthesisConfigurator synthesis(AudioQuery audioQuery, int styleId) { @@ -145,6 +151,8 @@ public SynthesisConfigurator synthesis(AudioQuery audioQuery, int styleId) { * @param text テキスト。 * @param styleId スタイルID。 * @return {@link TtsConfigurator}。 + * + * @see TtsConfigurator#execute */ @Nonnull public TtsConfigurator tts(String text, int styleId) { @@ -266,7 +274,7 @@ public static enum AccelerationMode { GPU, } - /** {@link Synthesizer#audioQuery} のオプション。 */ + /** {@link Synthesizer#createAudioQuery} のオプション。 */ public class CreateAudioQueryConfigurator { private Synthesizer synthesizer; private String text; @@ -362,7 +370,7 @@ public List execute() { } } - /** {@link Synthesizer#synthesize} のオプション。 */ + /** {@link Synthesizer#synthesis} のオプション。 */ public class SynthesisConfigurator { private Synthesizer synthesizer; private AudioQuery audioQuery; From 5890f6129714f49bf6570d55a3e699b0e6d066e4 Mon Sep 17 00:00:00 2001 From: Nanashi Date: Thu, 17 Aug 2023 08:13:06 +0900 Subject: [PATCH 89/99] =?UTF-8?q?Delete:=20=E4=B8=8D=E8=A6=81=E3=81=AA?= =?UTF-8?q?=E6=8C=87=E5=AE=9A=E3=82=92=E5=89=8A=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Ryo Yamashita --- crates/voicevox_core_java_api/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/voicevox_core_java_api/Cargo.toml b/crates/voicevox_core_java_api/Cargo.toml index 25683377e..b854016c1 100644 --- a/crates/voicevox_core_java_api/Cargo.toml +++ b/crates/voicevox_core_java_api/Cargo.toml @@ -16,7 +16,7 @@ jni = "0.21.1" once_cell.workspace = true serde_json.workspace = true tokio.workspace = true -tracing = { workspace = true, features = ["log"] } +tracing.workspace = true tracing-subscriber.workspace = true voicevox_core.workspace = true From e75a0fa8065dd09becd2b623d25a20ce4c5dc2a6 Mon Sep 17 00:00:00 2001 From: Nanashi Date: Thu, 17 Aug 2023 08:13:26 +0900 Subject: [PATCH 90/99] =?UTF-8?q?Delete:=20=E4=B8=8D=E8=A6=81=E3=81=AA?= =?UTF-8?q?=E4=BE=9D=E5=AD=98=E3=82=92=E5=89=8A=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Ryo Yamashita --- crates/voicevox_core_java_api/Cargo.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/voicevox_core_java_api/Cargo.toml b/crates/voicevox_core_java_api/Cargo.toml index b854016c1..7a8583245 100644 --- a/crates/voicevox_core_java_api/Cargo.toml +++ b/crates/voicevox_core_java_api/Cargo.toml @@ -11,7 +11,6 @@ crate-type = ["cdylib"] android_logger = "0.13.1" anyhow.workspace = true chrono = "0.4.26" -easy-ext.workspace = true jni = "0.21.1" once_cell.workspace = true serde_json.workspace = true From 8def7017a01580a78bb1fa45d72c1bc2d373b05c Mon Sep 17 00:00:00 2001 From: sevenc-nanashi Date: Thu, 17 Aug 2023 09:37:50 +0900 Subject: [PATCH 91/99] Change: jp.Hiroshiba.VoicevoxCore -> jp.hiroshiba.voicevoxcore Co-Authored-By: qryxip --- Cargo.lock | 1 - .../voicevoxcore}/AccentPhrase.java | 2 +- .../voicevoxcore}/AudioQuery.java | 2 +- .../voicevoxcore}/Dll.java | 2 +- .../voicevoxcore}/Mora.java | 2 +- .../voicevoxcore}/OpenJtalk.java | 2 +- .../voicevoxcore}/Synthesizer.java | 2 +- .../voicevoxcore}/UserDict.java | 5 ++-- .../voicevoxcore}/Utils.java | 2 +- .../voicevoxcore}/VoiceModel.java | 2 +- .../voicevoxcore}/VoicevoxException.java | 2 +- .../voicevoxcore}/MetaTest.java | 2 +- .../voicevoxcore}/SynthesizerTest.java | 2 +- .../voicevoxcore}/TestUtils.java | 2 +- .../voicevoxcore}/UserDictTest.java | 2 +- crates/voicevox_core_java_api/settings.gradle | 2 +- crates/voicevox_core_java_api/src/common.rs | 4 ++-- .../voicevox_core_java_api/src/open_jtalk.rs | 8 +++---- .../voicevox_core_java_api/src/synthesizer.rs | 24 +++++++++---------- .../voicevox_core_java_api/src/user_dict.rs | 22 ++++++++--------- .../voicevox_core_java_api/src/voice_model.rs | 8 +++---- 21 files changed, 50 insertions(+), 50 deletions(-) rename crates/voicevox_core_java_api/lib/src/main/java/jp/{Hiroshiba/VoicevoxCore => hiroshiba/voicevoxcore}/AccentPhrase.java (96%) rename crates/voicevox_core_java_api/lib/src/main/java/jp/{Hiroshiba/VoicevoxCore => hiroshiba/voicevoxcore}/AudioQuery.java (98%) rename crates/voicevox_core_java_api/lib/src/main/java/jp/{Hiroshiba/VoicevoxCore => hiroshiba/voicevoxcore}/Dll.java (98%) rename crates/voicevox_core_java_api/lib/src/main/java/jp/{Hiroshiba/VoicevoxCore => hiroshiba/voicevoxcore}/Mora.java (96%) rename crates/voicevox_core_java_api/lib/src/main/java/jp/{Hiroshiba/VoicevoxCore => hiroshiba/voicevoxcore}/OpenJtalk.java (96%) rename crates/voicevox_core_java_api/lib/src/main/java/jp/{Hiroshiba/VoicevoxCore => hiroshiba/voicevoxcore}/Synthesizer.java (99%) rename crates/voicevox_core_java_api/lib/src/main/java/jp/{Hiroshiba/VoicevoxCore => hiroshiba/voicevoxcore}/UserDict.java (98%) rename crates/voicevox_core_java_api/lib/src/main/java/jp/{Hiroshiba/VoicevoxCore => hiroshiba/voicevoxcore}/Utils.java (88%) rename crates/voicevox_core_java_api/lib/src/main/java/jp/{Hiroshiba/VoicevoxCore => hiroshiba/voicevoxcore}/VoiceModel.java (98%) rename crates/voicevox_core_java_api/lib/src/main/java/jp/{Hiroshiba/VoicevoxCore => hiroshiba/voicevoxcore}/VoicevoxException.java (82%) rename crates/voicevox_core_java_api/lib/src/test/java/jp/{Hiroshiba/VoicevoxCore => hiroshiba/voicevoxcore}/MetaTest.java (93%) rename crates/voicevox_core_java_api/lib/src/test/java/jp/{Hiroshiba/VoicevoxCore => hiroshiba/voicevoxcore}/SynthesizerTest.java (98%) rename crates/voicevox_core_java_api/lib/src/test/java/jp/{Hiroshiba/VoicevoxCore => hiroshiba/voicevoxcore}/TestUtils.java (95%) rename crates/voicevox_core_java_api/lib/src/test/java/jp/{Hiroshiba/VoicevoxCore => hiroshiba/voicevoxcore}/UserDictTest.java (98%) diff --git a/Cargo.lock b/Cargo.lock index e8eebdfbc..14934abe1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4153,7 +4153,6 @@ dependencies = [ "android_logger", "anyhow", "chrono", - "easy-ext", "jni", "once_cell", "serde_json", diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/AccentPhrase.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/hiroshiba/voicevoxcore/AccentPhrase.java similarity index 96% rename from crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/AccentPhrase.java rename to crates/voicevox_core_java_api/lib/src/main/java/jp/hiroshiba/voicevoxcore/AccentPhrase.java index c5e87f04f..8c64c9d11 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/AccentPhrase.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/hiroshiba/voicevoxcore/AccentPhrase.java @@ -1,4 +1,4 @@ -package jp.Hiroshiba.VoicevoxCore; +package jp.hiroshiba.voicevoxcore; import com.google.gson.annotations.Expose; import com.google.gson.annotations.SerializedName; diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/AudioQuery.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/hiroshiba/voicevoxcore/AudioQuery.java similarity index 98% rename from crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/AudioQuery.java rename to crates/voicevox_core_java_api/lib/src/main/java/jp/hiroshiba/voicevoxcore/AudioQuery.java index 3f122d84b..4a23be3f7 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/AudioQuery.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/hiroshiba/voicevoxcore/AudioQuery.java @@ -1,4 +1,4 @@ -package jp.Hiroshiba.VoicevoxCore; +package jp.hiroshiba.voicevoxcore; import com.google.gson.annotations.Expose; import com.google.gson.annotations.SerializedName; 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 similarity index 98% rename from crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Dll.java rename to crates/voicevox_core_java_api/lib/src/main/java/jp/hiroshiba/voicevoxcore/Dll.java index ab000efc9..e4e674205 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,4 +1,4 @@ -package jp.Hiroshiba.VoicevoxCore; +package jp.hiroshiba.voicevoxcore; import ai.onnxruntime.OrtEnvironment; import java.io.InputStream; diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Mora.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/hiroshiba/voicevoxcore/Mora.java similarity index 96% rename from crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Mora.java rename to crates/voicevox_core_java_api/lib/src/main/java/jp/hiroshiba/voicevoxcore/Mora.java index 415843b20..61dbaf233 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Mora.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/hiroshiba/voicevoxcore/Mora.java @@ -1,4 +1,4 @@ -package jp.Hiroshiba.VoicevoxCore; +package jp.hiroshiba.voicevoxcore; import com.google.gson.annotations.Expose; import com.google.gson.annotations.SerializedName; diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/OpenJtalk.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/hiroshiba/voicevoxcore/OpenJtalk.java similarity index 96% rename from crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/OpenJtalk.java rename to crates/voicevox_core_java_api/lib/src/main/java/jp/hiroshiba/voicevoxcore/OpenJtalk.java index 51b0c95c1..3228b8d51 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/OpenJtalk.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/hiroshiba/voicevoxcore/OpenJtalk.java @@ -1,4 +1,4 @@ -package jp.Hiroshiba.VoicevoxCore; +package jp.hiroshiba.voicevoxcore; import java.lang.ref.Cleaner; diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Synthesizer.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/hiroshiba/voicevoxcore/Synthesizer.java similarity index 99% rename from crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Synthesizer.java rename to crates/voicevox_core_java_api/lib/src/main/java/jp/hiroshiba/voicevoxcore/Synthesizer.java index d2cb381ba..2e97cc59c 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Synthesizer.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/hiroshiba/voicevoxcore/Synthesizer.java @@ -1,4 +1,4 @@ -package jp.Hiroshiba.VoicevoxCore; +package jp.hiroshiba.voicevoxcore; import com.google.gson.Gson; import java.lang.ref.Cleaner; diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/UserDict.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/hiroshiba/voicevoxcore/UserDict.java similarity index 98% rename from crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/UserDict.java rename to crates/voicevox_core_java_api/lib/src/main/java/jp/hiroshiba/voicevoxcore/UserDict.java index 0574c39f8..e31d56338 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/UserDict.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/hiroshiba/voicevoxcore/UserDict.java @@ -1,4 +1,4 @@ -package jp.Hiroshiba.VoicevoxCore; +package jp.hiroshiba.voicevoxcore; import com.google.gson.Gson; import com.google.gson.annotations.Expose; @@ -6,6 +6,7 @@ import com.google.gson.internal.LinkedTreeMap; import jakarta.validation.constraints.Max; import jakarta.validation.constraints.Min; + import java.lang.ref.Cleaner; import java.util.HashMap; import javax.annotation.Nonnull; @@ -176,7 +177,7 @@ public static class Word { /** * UserDict.Wordを作成する。 * - * @param surface 言葉の表層形。 + * @param surface 言葉の表層形。 * @param pronunciation 言葉の発音。 * @throws IllegalArgumentException pronunciationが不正な場合。 */ diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Utils.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/hiroshiba/voicevoxcore/Utils.java similarity index 88% rename from crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Utils.java rename to crates/voicevox_core_java_api/lib/src/main/java/jp/hiroshiba/voicevoxcore/Utils.java index 3d46e97d0..19b154cbc 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/Utils.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/hiroshiba/voicevoxcore/Utils.java @@ -1,4 +1,4 @@ -package jp.Hiroshiba.VoicevoxCore; +package jp.hiroshiba.voicevoxcore; class Utils { static boolean isU8(int value) { diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/VoiceModel.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/hiroshiba/voicevoxcore/VoiceModel.java similarity index 98% rename from crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/VoiceModel.java rename to crates/voicevox_core_java_api/lib/src/main/java/jp/hiroshiba/voicevoxcore/VoiceModel.java index 52d07a0bc..6b157fdba 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/VoiceModel.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/hiroshiba/voicevoxcore/VoiceModel.java @@ -1,4 +1,4 @@ -package jp.Hiroshiba.VoicevoxCore; +package jp.hiroshiba.voicevoxcore; import com.google.gson.Gson; import com.google.gson.annotations.Expose; diff --git a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/VoicevoxException.java b/crates/voicevox_core_java_api/lib/src/main/java/jp/hiroshiba/voicevoxcore/VoicevoxException.java similarity index 82% rename from crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/VoicevoxException.java rename to crates/voicevox_core_java_api/lib/src/main/java/jp/hiroshiba/voicevoxcore/VoicevoxException.java index c2049a822..3bf6f53a4 100644 --- a/crates/voicevox_core_java_api/lib/src/main/java/jp/Hiroshiba/VoicevoxCore/VoicevoxException.java +++ b/crates/voicevox_core_java_api/lib/src/main/java/jp/hiroshiba/voicevoxcore/VoicevoxException.java @@ -1,4 +1,4 @@ -package jp.Hiroshiba.VoicevoxCore; +package jp.hiroshiba.voicevoxcore; /** VOICEVOX COREのエラー。 */ public class VoicevoxException extends RuntimeException { diff --git a/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/MetaTest.java b/crates/voicevox_core_java_api/lib/src/test/java/jp/hiroshiba/voicevoxcore/MetaTest.java similarity index 93% rename from crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/MetaTest.java rename to crates/voicevox_core_java_api/lib/src/test/java/jp/hiroshiba/voicevoxcore/MetaTest.java index 0bd8716c9..741f84e79 100644 --- a/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/MetaTest.java +++ b/crates/voicevox_core_java_api/lib/src/test/java/jp/hiroshiba/voicevoxcore/MetaTest.java @@ -1,7 +1,7 @@ /* * This Java source file was generated by the Gradle 'init' task. */ -package jp.Hiroshiba.VoicevoxCore; +package jp.hiroshiba.voicevoxcore; import static org.junit.jupiter.api.Assertions.assertNotNull; 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 similarity index 98% rename from crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/SynthesizerTest.java rename to crates/voicevox_core_java_api/lib/src/test/java/jp/hiroshiba/voicevoxcore/SynthesizerTest.java index a48132336..fe9b8220b 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 @@ -2,7 +2,7 @@ * 音声合成のテスト。 * ttsaudioQuery -> synthesisの順に実行する。 */ -package jp.Hiroshiba.VoicevoxCore; +package jp.hiroshiba.voicevoxcore; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; 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 similarity index 95% rename from crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/TestUtils.java rename to crates/voicevox_core_java_api/lib/src/test/java/jp/hiroshiba/voicevoxcore/TestUtils.java index 40e770494..670eddbdb 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 @@ -1,4 +1,4 @@ -package jp.Hiroshiba.VoicevoxCore; +package jp.hiroshiba.voicevoxcore; import java.io.File; diff --git a/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/UserDictTest.java b/crates/voicevox_core_java_api/lib/src/test/java/jp/hiroshiba/voicevoxcore/UserDictTest.java similarity index 98% rename from crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/UserDictTest.java rename to crates/voicevox_core_java_api/lib/src/test/java/jp/hiroshiba/voicevoxcore/UserDictTest.java index f92b74207..a7847efba 100644 --- a/crates/voicevox_core_java_api/lib/src/test/java/jp/Hiroshiba/VoicevoxCore/UserDictTest.java +++ b/crates/voicevox_core_java_api/lib/src/test/java/jp/hiroshiba/voicevoxcore/UserDictTest.java @@ -1,4 +1,4 @@ -package jp.Hiroshiba.VoicevoxCore; +package jp.hiroshiba.voicevoxcore; import static org.junit.jupiter.api.Assertions.assertTrue; diff --git a/crates/voicevox_core_java_api/settings.gradle b/crates/voicevox_core_java_api/settings.gradle index b8e6bb336..e2e5f2305 100644 --- a/crates/voicevox_core_java_api/settings.gradle +++ b/crates/voicevox_core_java_api/settings.gradle @@ -10,5 +10,5 @@ plugins { id 'org.gradle.toolchains.foojay-resolver-convention' version '0.4.0' } -rootProject.name = 'jp.Hiroshiba.VoicevoxCore' +rootProject.name = 'jp.hiroshiba.voicevoxcore' include('lib') diff --git a/crates/voicevox_core_java_api/src/common.rs b/crates/voicevox_core_java_api/src/common.rs index 9515e1de6..abf3cd54b 100644 --- a/crates/voicevox_core_java_api/src/common.rs +++ b/crates/voicevox_core_java_api/src/common.rs @@ -61,13 +61,13 @@ pub static RUNTIME: Lazy = Lazy::new(|| { #[macro_export] macro_rules! object { ($name: literal) => { - concat!("jp/Hiroshiba/VoicevoxCore/", $name) + concat!("jp/hiroshiba/voicevoxcore/", $name) }; } #[macro_export] macro_rules! object_type { ($name: literal) => { - concat!("Ljp/Hiroshiba/VoicevoxCore/", $name, ";") + concat!("Ljp/hiroshiba/voicevoxcore/", $name, ";") }; } #[macro_export] diff --git a/crates/voicevox_core_java_api/src/open_jtalk.rs b/crates/voicevox_core_java_api/src/open_jtalk.rs index 5b13fe406..98feaacb0 100644 --- a/crates/voicevox_core_java_api/src/open_jtalk.rs +++ b/crates/voicevox_core_java_api/src/open_jtalk.rs @@ -6,7 +6,7 @@ use jni::{ JNIEnv, }; #[no_mangle] -unsafe extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_OpenJtalk_rsNewWithoutDic<'local>( +unsafe extern "system" fn Java_jp_hiroshiba_voicevoxcore_OpenJtalk_rsNewWithoutDic<'local>( env: JNIEnv<'local>, this: JObject<'local>, ) { @@ -19,7 +19,7 @@ unsafe extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_OpenJtalk_rsNewWithoutD } #[no_mangle] -unsafe extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_OpenJtalk_rsNewWithInitialize<'local>( +unsafe extern "system" fn Java_jp_hiroshiba_voicevoxcore_OpenJtalk_rsNewWithInitialize<'local>( env: JNIEnv<'local>, this: JObject<'local>, open_jtalk_dict_dir: JString<'local>, @@ -36,7 +36,7 @@ unsafe extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_OpenJtalk_rsNewWithInit } #[no_mangle] -unsafe extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_OpenJtalk_rsUseUserDict<'local>( +unsafe extern "system" fn Java_jp_hiroshiba_voicevoxcore_OpenJtalk_rsUseUserDict<'local>( env: JNIEnv<'local>, this: JObject<'local>, user_dict: JObject<'local>, @@ -60,7 +60,7 @@ unsafe extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_OpenJtalk_rsUseUserDict } #[no_mangle] -unsafe extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_OpenJtalk_rsDrop<'local>( +unsafe extern "system" fn Java_jp_hiroshiba_voicevoxcore_OpenJtalk_rsDrop<'local>( env: JNIEnv<'local>, this: JObject<'local>, ) { diff --git a/crates/voicevox_core_java_api/src/synthesizer.rs b/crates/voicevox_core_java_api/src/synthesizer.rs index f1186cd35..27fa75022 100644 --- a/crates/voicevox_core_java_api/src/synthesizer.rs +++ b/crates/voicevox_core_java_api/src/synthesizer.rs @@ -12,7 +12,7 @@ use jni::{ use std::sync::{Arc, Mutex}; #[no_mangle] -unsafe extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsNewWithInitialize<'local>( +unsafe extern "system" fn Java_jp_hiroshiba_voicevoxcore_Synthesizer_rsNewWithInitialize<'local>( env: JNIEnv<'local>, this: JObject<'local>, open_jtalk: JObject<'local>, @@ -62,7 +62,7 @@ unsafe extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsNewWithIn } #[no_mangle] -unsafe extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsLoadVoiceModel<'local>( +unsafe extern "system" fn Java_jp_hiroshiba_voicevoxcore_Synthesizer_rsLoadVoiceModel<'local>( env: JNIEnv<'local>, this: JObject<'local>, model: JObject<'local>, @@ -83,7 +83,7 @@ unsafe extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsLoadVoice } #[no_mangle] -unsafe extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsUnloadVoiceModel<'local>( +unsafe extern "system" fn Java_jp_hiroshiba_voicevoxcore_Synthesizer_rsUnloadVoiceModel<'local>( env: JNIEnv<'local>, this: JObject<'local>, model_id: JString<'local>, @@ -106,7 +106,7 @@ unsafe extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsUnloadVoi } #[no_mangle] -unsafe extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsIsLoadedVoiceModel< +unsafe extern "system" fn Java_jp_hiroshiba_voicevoxcore_Synthesizer_rsIsLoadedVoiceModel< 'local, >( env: JNIEnv<'local>, @@ -131,7 +131,7 @@ unsafe extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsIsLoadedV } #[no_mangle] -unsafe extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsAudioQuery<'local>( +unsafe extern "system" fn Java_jp_hiroshiba_voicevoxcore_Synthesizer_rsAudioQuery<'local>( env: JNIEnv<'local>, this: JObject<'local>, text: JString<'local>, @@ -168,7 +168,7 @@ unsafe extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsAudioQuer } #[no_mangle] -unsafe extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsAccentPhrases<'local>( +unsafe extern "system" fn Java_jp_hiroshiba_voicevoxcore_Synthesizer_rsAccentPhrases<'local>( env: JNIEnv<'local>, this: JObject<'local>, text: JString<'local>, @@ -205,7 +205,7 @@ unsafe extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsAccentPhr } #[no_mangle] -unsafe extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsReplaceMoraData<'local>( +unsafe extern "system" fn Java_jp_hiroshiba_voicevoxcore_Synthesizer_rsReplaceMoraData<'local>( env: JNIEnv<'local>, this: JObject<'local>, accent_phrases_json: JString<'local>, @@ -235,7 +235,7 @@ unsafe extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsReplaceMo } #[no_mangle] -unsafe extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsReplacePhonemeLength< +unsafe extern "system" fn Java_jp_hiroshiba_voicevoxcore_Synthesizer_rsReplacePhonemeLength< 'local, >( env: JNIEnv<'local>, @@ -268,7 +268,7 @@ unsafe extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsReplacePh } #[no_mangle] -unsafe extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsReplaceMoraPitch<'local>( +unsafe extern "system" fn Java_jp_hiroshiba_voicevoxcore_Synthesizer_rsReplaceMoraPitch<'local>( env: JNIEnv<'local>, this: JObject<'local>, accent_phrases_json: JString<'local>, @@ -298,7 +298,7 @@ unsafe extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsReplaceMo } #[no_mangle] -unsafe extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsSynthesis<'local>( +unsafe extern "system" fn Java_jp_hiroshiba_voicevoxcore_Synthesizer_rsSynthesis<'local>( env: JNIEnv<'local>, this: JObject<'local>, query_json: JString<'local>, @@ -334,7 +334,7 @@ unsafe extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsSynthesis } #[no_mangle] -unsafe extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsTts<'local>( +unsafe extern "system" fn Java_jp_hiroshiba_voicevoxcore_Synthesizer_rsTts<'local>( env: JNIEnv<'local>, this: JObject<'local>, query_json: JString<'local>, @@ -371,7 +371,7 @@ unsafe extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsTts<'loca } #[no_mangle] -unsafe extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_Synthesizer_rsDrop<'local>( +unsafe extern "system" fn Java_jp_hiroshiba_voicevoxcore_Synthesizer_rsDrop<'local>( env: JNIEnv<'local>, this: JObject<'local>, ) { diff --git a/crates/voicevox_core_java_api/src/user_dict.rs b/crates/voicevox_core_java_api/src/user_dict.rs index cc403e408..a89c11d8e 100644 --- a/crates/voicevox_core_java_api/src/user_dict.rs +++ b/crates/voicevox_core_java_api/src/user_dict.rs @@ -9,7 +9,7 @@ use jni::{ }; #[no_mangle] -unsafe extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsNew<'local>( +unsafe extern "system" fn Java_jp_hiroshiba_voicevoxcore_UserDict_rsNew<'local>( env: JNIEnv<'local>, this: JObject<'local>, ) { @@ -23,7 +23,7 @@ unsafe extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsNew<'local>( } #[no_mangle] -unsafe extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsAddWord<'local>( +unsafe extern "system" fn Java_jp_hiroshiba_voicevoxcore_UserDict_rsAddWord<'local>( env: JNIEnv<'local>, this: JObject<'local>, word_json: JString<'local>, @@ -51,7 +51,7 @@ unsafe extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsAddWord<'loc } #[no_mangle] -unsafe extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsUpdateWord<'local>( +unsafe extern "system" fn Java_jp_hiroshiba_voicevoxcore_UserDict_rsUpdateWord<'local>( env: JNIEnv<'local>, this: JObject<'local>, uuid: JString<'local>, @@ -79,7 +79,7 @@ unsafe extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsUpdateWord<' } #[no_mangle] -unsafe extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsRemoveWord<'local>( +unsafe extern "system" fn Java_jp_hiroshiba_voicevoxcore_UserDict_rsRemoveWord<'local>( env: JNIEnv<'local>, this: JObject<'local>, uuid: JString<'local>, @@ -102,7 +102,7 @@ unsafe extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsRemoveWord<' } #[no_mangle] -unsafe extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsImportDict<'local>( +unsafe extern "system" fn Java_jp_hiroshiba_voicevoxcore_UserDict_rsImportDict<'local>( env: JNIEnv<'local>, this: JObject<'local>, other_dict: JObject<'local>, @@ -126,7 +126,7 @@ unsafe extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsImportDict<' } #[no_mangle] -unsafe extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsLoad<'local>( +unsafe extern "system" fn Java_jp_hiroshiba_voicevoxcore_UserDict_rsLoad<'local>( env: JNIEnv<'local>, this: JObject<'local>, path: JString<'local>, @@ -149,7 +149,7 @@ unsafe extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsLoad<'local> } #[no_mangle] -unsafe extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsSave<'local>( +unsafe extern "system" fn Java_jp_hiroshiba_voicevoxcore_UserDict_rsSave<'local>( env: JNIEnv<'local>, this: JObject<'local>, path: JString<'local>, @@ -172,7 +172,7 @@ unsafe extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsSave<'local> } #[no_mangle] -unsafe extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsGetWords<'local>( +unsafe extern "system" fn Java_jp_hiroshiba_voicevoxcore_UserDict_rsGetWords<'local>( env: JNIEnv<'local>, this: JObject<'local>, ) -> jobject { @@ -193,7 +193,7 @@ unsafe extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsGetWords<'lo } #[no_mangle] -unsafe extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsDrop<'local>( +unsafe extern "system" fn Java_jp_hiroshiba_voicevoxcore_UserDict_rsDrop<'local>( env: JNIEnv<'local>, this: JObject<'local>, ) { @@ -204,7 +204,7 @@ unsafe extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsDrop<'local> } #[no_mangle] -extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsToZenkaku<'local>( +extern "system" fn Java_jp_hiroshiba_voicevoxcore_UserDict_rsToZenkaku<'local>( env: JNIEnv<'local>, _cls: JClass<'local>, text: JString<'local>, @@ -221,7 +221,7 @@ extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsToZenkaku<'local>( } #[no_mangle] -extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_UserDict_rsValidatePronunciation<'local>( +extern "system" fn Java_jp_hiroshiba_voicevoxcore_UserDict_rsValidatePronunciation<'local>( env: JNIEnv<'local>, _cls: JClass<'local>, text: JString<'local>, diff --git a/crates/voicevox_core_java_api/src/voice_model.rs b/crates/voicevox_core_java_api/src/voice_model.rs index 03e9d916e..33ae01288 100644 --- a/crates/voicevox_core_java_api/src/voice_model.rs +++ b/crates/voicevox_core_java_api/src/voice_model.rs @@ -8,7 +8,7 @@ use jni::{ }; #[no_mangle] -unsafe extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_VoiceModel_rsFromPath<'local>( +unsafe extern "system" fn Java_jp_hiroshiba_voicevoxcore_VoiceModel_rsFromPath<'local>( env: JNIEnv<'local>, this: JObject<'local>, model_path: JString<'local>, @@ -26,7 +26,7 @@ unsafe extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_VoiceModel_rsFromPath<' } #[no_mangle] -unsafe extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_VoiceModel_rsGetId<'local>( +unsafe extern "system" fn Java_jp_hiroshiba_voicevoxcore_VoiceModel_rsGetId<'local>( env: JNIEnv<'local>, this: JObject<'local>, ) -> jobject { @@ -44,7 +44,7 @@ unsafe extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_VoiceModel_rsGetId<'loc } #[no_mangle] -unsafe extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_VoiceModel_rsGetMetasJson<'local>( +unsafe extern "system" fn Java_jp_hiroshiba_voicevoxcore_VoiceModel_rsGetMetasJson<'local>( env: JNIEnv<'local>, this: JObject<'local>, ) -> jobject { @@ -60,7 +60,7 @@ unsafe extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_VoiceModel_rsGetMetasJs } #[no_mangle] -unsafe extern "system" fn Java_jp_Hiroshiba_VoicevoxCore_VoiceModel_rsDrop<'local>( +unsafe extern "system" fn Java_jp_hiroshiba_voicevoxcore_VoiceModel_rsDrop<'local>( env: JNIEnv<'local>, this: JObject<'local>, ) { From 7ea44fbb7a2b1c7c4dfc293ee7adc5d48693aa0f Mon Sep 17 00:00:00 2001 From: sevenc-nanashi Date: Fri, 18 Aug 2023 10:55:53 +0900 Subject: [PATCH 92/99] =?UTF-8?q?Delete:=20mut=E3=82=92=E5=89=8A=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crates/voicevox_core_java_api/src/synthesizer.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/voicevox_core_java_api/src/synthesizer.rs b/crates/voicevox_core_java_api/src/synthesizer.rs index 27fa75022..de038c70c 100644 --- a/crates/voicevox_core_java_api/src/synthesizer.rs +++ b/crates/voicevox_core_java_api/src/synthesizer.rs @@ -75,7 +75,7 @@ unsafe extern "system" fn Java_jp_hiroshiba_voicevoxcore_Synthesizer_rsLoadVoice .get_rust_field::<_, _, Arc>>(&this, "handle")? .clone(); { - let mut internal = internal.lock().unwrap(); + let internal = internal.lock().unwrap(); RUNTIME.block_on(internal.load_voice_model(&model))?; } Ok(()) @@ -96,7 +96,7 @@ unsafe extern "system" fn Java_jp_hiroshiba_voicevoxcore_Synthesizer_rsUnloadVoi .clone(); { - let mut internal = internal.lock().unwrap(); + let internal = internal.lock().unwrap(); internal.unload_voice_model(&voicevox_core::VoiceModelId::new(model_id))?; } From e4d2dd63abe1a742317095a946b718bbc371326f Mon Sep 17 00:00:00 2001 From: sevenc-nanashi Date: Tue, 29 Aug 2023 19:40:19 +0900 Subject: [PATCH 93/99] =?UTF-8?q?Change:=20gradle=E3=82=92generated?= =?UTF-8?q?=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crates/voicevox_core_java_api/.gitattributes | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/voicevox_core_java_api/.gitattributes b/crates/voicevox_core_java_api/.gitattributes index 79f5b948c..b77518dbb 100644 --- a/crates/voicevox_core_java_api/.gitattributes +++ b/crates/voicevox_core_java_api/.gitattributes @@ -2,10 +2,11 @@ # https://help.github.com/articles/dealing-with-line-endings/ # # Linux start script should use lf -/gradlew text eol=lf linguist-vendored linguist-generated +./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 linguist-vendored linguist-generated From 44c9c91230d0bf879bbf7d497d01593974d5d003 Mon Sep 17 00:00:00 2001 From: sevenc-nanashi Date: Tue, 29 Aug 2023 19:40:54 +0900 Subject: [PATCH 94/99] =?UTF-8?q?Fix:=20=E5=B0=8F=E6=96=87=E5=AD=97?= =?UTF-8?q?=E5=8C=96=E3=81=AB=E8=BF=BD=E5=BE=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crates/voicevox_core_java_api/src/common.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/voicevox_core_java_api/src/common.rs b/crates/voicevox_core_java_api/src/common.rs index abf3cd54b..d7aeb720b 100644 --- a/crates/voicevox_core_java_api/src/common.rs +++ b/crates/voicevox_core_java_api/src/common.rs @@ -96,7 +96,7 @@ where // となり、デバッグが困難になるため、そのままにしておく。 if !env.exception_check().unwrap_or(false) { env.throw_new( - "jp/Hiroshiba/VoicevoxCore/VoicevoxException", + "jp/hiroshiba/voicevoxcore/VoicevoxException", error.to_string(), ) .unwrap_or_else(|_| panic!("Failed to throw exception, original error: {}", error)); From e149843606474b67166876e6b0978b2ff06e1696 Mon Sep 17 00:00:00 2001 From: sevenc-nanashi Date: Tue, 29 Aug 2023 19:46:19 +0900 Subject: [PATCH 95/99] =?UTF-8?q?Change:=20README=E3=81=AE=E7=B4=B0?= =?UTF-8?q?=E3=81=8B=E3=81=84=E9=83=A8=E5=88=86=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Hiroshiba --- crates/voicevox_core_java_api/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/voicevox_core_java_api/README.md b/crates/voicevox_core_java_api/README.md index c879ca1bb..4f23cb55f 100644 --- a/crates/voicevox_core_java_api/README.md +++ b/crates/voicevox_core_java_api/README.md @@ -19,7 +19,7 @@ VOICEVOX CORE の Java バインディング。 - src: - main: - java: - - jp/Hiroshiba/VoicevoxCore: # Javaのソースコード。 + - jp/hiroshiba/voicevoxcore: # Javaのソースコード。 - Synthesizer.java - ... - resources: @@ -41,7 +41,7 @@ VOICEVOX CORE の Java バインディング。 Java プロジェクトを動かすには、 - `LD_LIBRARY_PATH`などの環境変数に `[プロジェクトルート]/target/debug`(または`/release`) を追加するか、 -- `lib/src/main/resources/dll/[target]/libvoicevox_core_java_api.so` を作成する +- `lib/src/main/resources/dll/[target]/libvoicevox_core_java_api.so` を作成する(`libvoicevox_core_java_api.so`はプラットフォームによって異なります、詳細は後述)。 必要があります。 @@ -90,7 +90,7 @@ DLL の名前は、 - Windows:voicevox_core_java_api.dll - Linux:libvoicevox_core_java_api.so -- MacOS:libvoicevox_core_java_api.dylib +- macOS:libvoicevox_core_java_api.dylib になります。 見付からなかった場合は、`System.loadLibrary` で読み込みます。これはデバッグ用です。 From cbba795936c3302ca509eb9fb1d9f84ed4a19dac Mon Sep 17 00:00:00 2001 From: sevenc-nanashi Date: Tue, 29 Aug 2023 19:54:34 +0900 Subject: [PATCH 96/99] =?UTF-8?q?Delete:=20=E7=A9=BA=E3=83=87=E3=82=A3?= =?UTF-8?q?=E3=83=AC=E3=82=AF=E3=83=88=E3=83=AA=E3=82=92=E5=89=8A=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/test.yml | 2 +- crates/voicevox_core_java_api/README.md | 4 ++-- .../lib/src/main/resources/dll/README.md | 9 +++++++++ .../lib/src/main/resources/dll/linux-arm64/.gitkeep | 0 .../lib/src/main/resources/dll/linux-x64/.gitkeep | 0 .../lib/src/main/resources/dll/macos-arm64/.gitkeep | 0 .../lib/src/main/resources/dll/macos-x64/.gitkeep | 0 .../lib/src/main/resources/dll/windows-x64/.gitkeep | 0 .../lib/src/main/resources/dll/windows-x86/.gitkeep | 0 9 files changed, 12 insertions(+), 3 deletions(-) create mode 100644 crates/voicevox_core_java_api/lib/src/main/resources/dll/README.md delete mode 100644 crates/voicevox_core_java_api/lib/src/main/resources/dll/linux-arm64/.gitkeep delete mode 100644 crates/voicevox_core_java_api/lib/src/main/resources/dll/linux-x64/.gitkeep delete mode 100644 crates/voicevox_core_java_api/lib/src/main/resources/dll/macos-arm64/.gitkeep delete mode 100644 crates/voicevox_core_java_api/lib/src/main/resources/dll/macos-x64/.gitkeep delete mode 100644 crates/voicevox_core_java_api/lib/src/main/resources/dll/windows-x64/.gitkeep delete mode 100644 crates/voicevox_core_java_api/lib/src/main/resources/dll/windows-x86/.gitkeep diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 1aa7b072f..4adb3b9bf 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -308,7 +308,6 @@ jobs: - name: 必要なDLLをコピーしてテストを実行 working-directory: crates/voicevox_core_java_api run: | - OS=$(tr '[:upper:]' '[:lower:]' <<<"$RUNNER_OS") ARCH=$(tr '[:upper:]' '[:lower:]' <<<"$RUNNER_ARCH") @@ -328,6 +327,7 @@ jobs: ;; esac TARGET_NAME="$OS-$ARCH" + mkdir -p "./lib/src/main/resources/dll/$TARGET_NAME" cp -v "../../target/debug/$DLL_NAME" "./lib/src/main/resources/dll/$TARGET_NAME/$DLL_NAME" echo "target = $TARGET_NAME, dll = $DLL_NAME" ./gradlew test --info diff --git a/crates/voicevox_core_java_api/README.md b/crates/voicevox_core_java_api/README.md index 4f23cb55f..d1bc31938 100644 --- a/crates/voicevox_core_java_api/README.md +++ b/crates/voicevox_core_java_api/README.md @@ -56,8 +56,8 @@ Java プロジェクトを動かすには、 ## ビルド(リリース) -`cargo build --release` でRust側を、`./gradlew build` でJava側をビルドできます。 -パッケージ化する時はlib/src/main/resources/dll内にdllをコピーしてください。 +`cargo build --release` で Rust 側を、`./gradlew build` で Java 側をビルドできます。 +パッケージ化する時は lib/src/main/resources/dll 内に dll をコピーしてください。 ```console ❯ cargo build --release diff --git a/crates/voicevox_core_java_api/lib/src/main/resources/dll/README.md b/crates/voicevox_core_java_api/lib/src/main/resources/dll/README.md new file mode 100644 index 000000000..1975c39b6 --- /dev/null +++ b/crates/voicevox_core_java_api/lib/src/main/resources/dll/README.md @@ -0,0 +1,9 @@ +このディレクトリに JNI 用に読み込まれる DLL を配置します。 +ディレクトリ名は以下のうちのいずれかになります。 + +- `windows-x64` +- `windows-x86` +- `linux-x64` +- `linux-arm64` +- `macos-x64` +- `macos-arm64` diff --git a/crates/voicevox_core_java_api/lib/src/main/resources/dll/linux-arm64/.gitkeep b/crates/voicevox_core_java_api/lib/src/main/resources/dll/linux-arm64/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/crates/voicevox_core_java_api/lib/src/main/resources/dll/linux-x64/.gitkeep b/crates/voicevox_core_java_api/lib/src/main/resources/dll/linux-x64/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/crates/voicevox_core_java_api/lib/src/main/resources/dll/macos-arm64/.gitkeep b/crates/voicevox_core_java_api/lib/src/main/resources/dll/macos-arm64/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/crates/voicevox_core_java_api/lib/src/main/resources/dll/macos-x64/.gitkeep b/crates/voicevox_core_java_api/lib/src/main/resources/dll/macos-x64/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/crates/voicevox_core_java_api/lib/src/main/resources/dll/windows-x64/.gitkeep b/crates/voicevox_core_java_api/lib/src/main/resources/dll/windows-x64/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/crates/voicevox_core_java_api/lib/src/main/resources/dll/windows-x86/.gitkeep b/crates/voicevox_core_java_api/lib/src/main/resources/dll/windows-x86/.gitkeep deleted file mode 100644 index e69de29bb..000000000 From f54bc1f90e7e61ec3c1587875fa8130d6ad021fb Mon Sep 17 00:00:00 2001 From: sevenc-nanashi Date: Tue, 29 Aug 2023 19:55:12 +0900 Subject: [PATCH 97/99] =?UTF-8?q?Change:=20()=E3=82=92=E4=BD=BF=E3=81=86?= =?UTF-8?q?=E3=82=88=E3=81=86=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Hiroshiba --- .github/workflows/generate_document.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/generate_document.yml b/.github/workflows/generate_document.yml index 178400cff..bdf71905a 100644 --- a/.github/workflows/generate_document.yml +++ b/.github/workflows/generate_document.yml @@ -49,9 +49,7 @@ jobs: run: sphinx-build docs/apis/python_api public/apis/python_api - name: Generate Javadoc run: | - cd crates/voicevox_core_java_api - ./gradlew javadoc - cd ../.. + (cd crates/voicevox_core_java_api && ./gradlew javadoc) mkdir -p public/apis/java_api cp -r crates/voicevox_core_java_api/lib/build/docs/javadoc/* public/apis/java_api - name: Uplaod api document From d779a04b5cffa868537107d8b0d514ebad49e1ee Mon Sep 17 00:00:00 2001 From: sevenc-nanashi Date: Tue, 29 Aug 2023 20:16:23 +0900 Subject: [PATCH 98/99] =?UTF-8?q?Change:=20gradle-wrapper.jar=E3=82=92gene?= =?UTF-8?q?rated=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crates/voicevox_core_java_api/.gitattributes | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/voicevox_core_java_api/.gitattributes b/crates/voicevox_core_java_api/.gitattributes index b77518dbb..493fdc40f 100644 --- a/crates/voicevox_core_java_api/.gitattributes +++ b/crates/voicevox_core_java_api/.gitattributes @@ -9,4 +9,4 @@ ./gradlew linguist-vendored linguist-generated ./gradlew.bat linguist-vendored linguist-generated -./gradle linguist-vendored linguist-generated +./gradle/wrapper/gradle-wrapper.jar linguist-vendored linguist-generated From 456891e9f8ec21af594715d3c14f2235bcbc2e82 Mon Sep 17 00:00:00 2001 From: Hiroshiba Date: Thu, 31 Aug 2023 00:06:22 +0900 Subject: [PATCH 99/99] =?UTF-8?q?update-rust-branch=E3=81=AE=E6=A1=88?= =?UTF-8?q?=E5=86=85=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crates/voicevox_core_java_api/settings.gradle | 7 ------- 1 file changed, 7 deletions(-) diff --git a/crates/voicevox_core_java_api/settings.gradle b/crates/voicevox_core_java_api/settings.gradle index e2e5f2305..7d07347eb 100644 --- a/crates/voicevox_core_java_api/settings.gradle +++ b/crates/voicevox_core_java_api/settings.gradle @@ -1,10 +1,3 @@ -/* - * This file was generated by the Gradle 'init' task. - * - * The settings file is used to specify which projects to include in your build. - * For more detailed information on multi-project builds, please refer to https://docs.gradle.org/8.2.1/userguide/building_swift_projects.html in the Gradle documentation. - */ - plugins { // Apply the foojay-resolver plugin to allow automatic download of JDKs id 'org.gradle.toolchains.foojay-resolver-convention' version '0.4.0'