Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

C++音声合成ライブラリの追加 #87

Merged
merged 16 commits into from
Mar 10, 2022

Conversation

y-chan
Copy link
Member

@y-chan y-chan commented Mar 9, 2022

内容

今のところ動きませんとりあえず動くようになりました
wavの生成周りは多分うまくいっていますが、それを実際に実行(https://gist.github.com/y-chan/5d09177b3771bd17bfa946623b1fd905 )してみるとうまく行きません...(正しくないと思われるノイズ音声が再生されます)
https://gist.github.com/y-chan/5d09177b3771bd17bfa946623b1fd905 に実行のためのファイルと説明を置いておいたので、良ければ検証にご利用ください。

関連 Issue

ref #43

@Hiroshiba
Copy link
Member

プルリクエスト作成ありがとうございます!!!!!
いったんみんなで実際に動かそうとしてみたり、原因を探れると嬉しいですね!!!

@PickledChair
Copy link
Member

PickledChair commented Mar 9, 2022

Mac で検証してみました。ビルド・実行の過程で2点つまづいたところがあって、それを解消すると問題の「正しくないと思われるノイズ音声」が生成されました。

  • Mac でビルドしてみた時に jpcommon.hFILE が見つからないというエラーでビルドが通りませんでした。関連する以下の箇所(core/src/engine/openjtalk.h)で、 #include <cstdio> を一番先頭に持ってくるよう変更するとビルドが通るようになりました(ビルド手順のミスのせいでしたらすみません)。

https://github.com/y-chan/voicevox_core/blob/57c0902017ada63305a83b2a7baf85846cdc1010/core/src/engine/openjtalk.h#L1-L11

  • そのままでは main.cpp のビルド結果である a.out の実行でコアの初期化がうまくいきませんでした。ビルドされたコア(ビルド後に生成されるディレクトリ core/lib/ にある)と同じディレクトリに model/ ディレクトリ以下にあるファイルをコピーしてから実行するとうまくいきます。

@Hiroshiba
Copy link
Member

Windowsのcl.exeで試していたのですが、LoadLibraryが突破できませんでした。。
とりあえずビルドはできたので、そこまでのメモを残してみます。

FILEが見つからないエラー → @PickledChair さんの方法で解決

kana_parser.cppでstd::runtime_errorが無いエラー
↓をkana_parser.cppに追記

#include <algorithm>
#include <stdexcept>

LoadLibraryのエラー内容はGetLastError()で確認できるのですが、193でした。
32bitと64bitのDLLが混在しているとエラーが出る、的な記事が見つかるのでsが、根本的にどう解決すればいいかわからずに諦めました。

@takana-v
Copy link
Member

同じくcl.exeで試してみました。
@Hiroshiba さんの方法でビルドできました。また、metas.jsonと*.onnxが必要でした。

Pythonのctypesで実行してみましたが、ヘッダー以外空のwavファイルが出力されました。
複数回ヘッダーが出現している感じです。
「テスト」で生成し再生するとバチバチといった感じの音になりました。
文字数に応じて音声ファイルの長さが変化している感じでした。
(もしかしたらctypes実装にミスがあったのかもしれません)

ctypes実装
import argparse
import os
from ctypes import CDLL, POINTER, c_bool, c_char_p, c_int, c_int64, c_char
from pathlib import Path

class CppEngine:
    def __init__(self, root_dir: Path, openjtalk_dir: Path):
        self.core = CDLL(str((root_dir/"core.dll").resolve(strict=True)))

        self.core.initialize.restype = c_bool
        self.core.initialize_openjtalk.argtypes = (c_char_p,)
        self.core.initialize_openjtalk.restype = c_bool
        self.core.tts.argtypes = (c_char_p, POINTER(c_int64), POINTER(c_int))
        self.core.tts.restype = POINTER(c_char)
        cwd = os.getcwd()
        os.chdir(root_dir)
        init_core = self.core.initialize(".", False, None)
        os.chdir(cwd)
        assert init_core
        init_ojt = self.core.initialize_openjtalk(c_char_p(str(openjtalk_dir).encode()))
        assert init_ojt
    
    def tts(self, text: str, speaker_id: int):
        binary_size = POINTER(c_int)(c_int(0))
        return self.core.tts(
            c_char_p(text.encode()),
            c_int64(speaker_id),
            binary_size
        ), binary_size


if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("--root_dir", type=Path)
    parser.add_argument("--openjtalk_dir", type=Path)
    parser.add_argument("--text", type=str)
    parser.add_argument("--speaker_id", type=int)
    args = parser.parse_args()
    engine = CppEngine(args.root_dir, args.openjtalk_dir)
    tts_ret, bin_size = engine.tts(args.text, args.speaker_id)
    data = b""
    for i in range(bin_size.contents.value):
        data += tts_ret[i]
    
    with open("test.wav", mode="wb") as f:
        f.write(data)

image

@y-chan
Copy link
Member Author

y-chan commented Mar 10, 2022

jpcommonのためのコードを入れておいたはずが、clang-formatで移動させられて機能していなかったようです。
それと、出力される波形がおかしいのは、入力されるデータがおかしいからではないかということで、phonemeのvectorを1次元に直し、アドレスを連続させるようにしたところ、生成されるwavが改善されました。

今のところ、エラーハンドリングやWindowsでの手元での動作確認が取れていない等まだ課題が残っているので、Draftは外さずに置いておきます。

Copy link
Contributor

@qwerty2501 qwerty2501 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

コード見てみましたが恐らく動かなくなっている原因となっているところがありました。
また随所にGCのある言語のようなノリで書かれてると思われるコードが散見されました。
C++でこれをやってしまうとメモリリークやアクセス領域違反があり大変危険な状態です。
まだあるかもしれません。

core/src/engine/synthesis_engine.cpp Show resolved Hide resolved
core/src/engine/openjtalk.h Outdated Show resolved Hide resolved
core/src/engine/acoustic_feature_extractor.h Show resolved Hide resolved
core/src/engine.cpp Outdated Show resolved Hide resolved
core/src/core.h Outdated Show resolved Hide resolved
core/src/engine/openjtalk.h Outdated Show resolved Hide resolved
@y-chan
Copy link
Member Author

y-chan commented Mar 10, 2022

GCのある言語のようなノリで書かれてると思われるコードが散見され

おっしゃる通りと思われます。
私自身C++でコードを沢山書いたことがある訳ではなく、全くの初心者であるため、常識がわかっておらず色んな間違いがあることは否定しません。
VOICEVOXのロードマップとして、とりあえず動かせるC++ライブラリを作ると言ったことがあったので、このPRではとりあえず私の持つ既存コード(https://github.com/y-chan/node-voicevox-engine )を、Coreと結合して動かすことを目的として書き直しました。
なので、動きはするが問題が異常な程にあるといった状況に思われます。

このPRがDraftなのは、エラーハンドリング周りが完全でないことだけでなく、そういった非常識で危険なコードを修正するためでもあります。
ご指摘頂いた点はなるべく解決するようにしたいと考えています。
また、suggestionなど送っていただければ、もっと色々議論ができるかなと思います。

追記: OpenJTalk周りのコードはpyopenjtalkのコードの流用であるため、特に深い意味はありません。とはいえ深い意味がないが使っているというのは危険なコードではあると思うので、正しいように直せたら良いなと思います。

@qwerty2501
Copy link
Contributor

@y-chan suggestionも考えたのですがちょっと広範になりそうなのでとりあえず今思ってることで良いので各コメントに対して返信していただけますか?
短くできそうなところは後でsuggestionします

@Hiroshiba
Copy link
Member

Hiroshiba commented Mar 10, 2022

@qwerty2501 さん
レビューありがとうございます!!非常に心強いです。

戦略ですが、一旦マージしてしまえば各々がプルリクエストを送ることができるので、マージを最優先に考えています。
メモリ的に危ない箇所はたしかにありそうですが、目についたものにFIXMEコメントを付けて頂いて、多少強引ですが一旦マージしたいです・・・!

@Hiroshiba
Copy link
Member

なので、指摘箇所のうちすぐ直せる部分は直していただきつつ、難しいところはFIXMEコメントを足した状態にできればdraftを外していただければ・・・!

@qwerty2501
Copy link
Contributor

コメントしましたがmergeのタイミングはお任せします

@Hiroshiba
Copy link
Member

個人的には @qwerty2501 さんにコメント頂いた2箇所を修正 or FIXMEコメント追加頂ければ一旦マージしたいですね・・・!!

@Segu-g
Copy link
Member

Segu-g commented Mar 10, 2022

多少強引ですが一旦マージしたいです・・・!

とりあえず別ブランチとしてマージするのがいいと思います!

@y-chan
Copy link
Member Author

y-chan commented Mar 10, 2022

とりあえず別ブランチとしてマージするのがいいと思います!

私もそう思いました!
exampleとかREADMEとかもまだ未整備で、テストも回ってないので、一旦別ブランチを用意して、ある程度まともになってからマージするのが良さそうだと思いました

@y-chan y-chan marked this pull request as ready for review March 10, 2022 10:55
@y-chan y-chan changed the base branch from main to cpp-library March 10, 2022 10:59
@y-chan
Copy link
Member Author

y-chan commented Mar 10, 2022

とりあえず現状指摘のあった

  • heapを使った方がいい(これであってるのかはわからない...)
  • namespaceを使った方がいい
  • prefixを付けた方がいい

と、その他のリファクタ(warningの解消やformat)を改善しました。
私たちにはwrite権限があるので、独断ではありますが、一旦cpp-libraryブランチを派生させ、PRをそちらに向けるように修正しました。

core/src/engine.cpp Outdated Show resolved Hide resolved
core/src/engine.cpp Outdated Show resolved Hide resolved
@qwerty2501
Copy link
Contributor

qwerty2501 commented Mar 10, 2022

コメントしましたがLGTMです。
コメント内容を取り込むかはおまかせします

y-chan and others added 2 commits March 10, 2022 20:40
Co-authored-by: qwerty2501 <939468+qwerty2501@users.noreply.github.com>
Co-authored-by: qwerty2501 <939468+qwerty2501@users.noreply.github.com>
core/src/engine.cpp Outdated Show resolved Hide resolved
y-chan and others added 2 commits March 10, 2022 20:47
Co-authored-by: takana-v <44311840+takana-v@users.noreply.github.com>
Copy link
Member

@Hiroshiba Hiroshiba left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!!!

コメント、僕もとても勉強になりました。
さすがに初手で完璧なのはなかなかなく、いろんな改善点があるのかもしれません。
どんどん良くしていければ嬉しいです、プルリクエストお待ちしています!!

@Hiroshiba Hiroshiba merged commit 5182f6d into VOICEVOX:cpp-library Mar 10, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants