VOICEVOX / voicevox_engine

無料で使える中品質なテキスト読み上げソフトウェア、VOICEVOXの音声合成エンジン
https://voicevox.hiroshiba.jp/
Other
1.32k stars 196 forks source link

音割れをさせずに音量を上げる方法を調査・実装する #135

Open Hiroshiba opened 3 years ago

Hiroshiba commented 3 years ago

内容

VOICEVOX ENGINEは音量パラメータがありますが、これは波形を単純に定数倍しているだけなので、音が割れます(-1~1の範囲外になる)。 おそらく世の中の音声ツールは、音が割れないように音量(音圧?)を上げられる仕組みになっているはずです。 このissueはその方法を調査して、(ライブラリの力などを借りつつ)実装することが目的です。

Pros 良くなる点

音割れせずに音量をあげられる

Cons 悪くなる点

仕様変更のアナウンスが必要

実現方法

pythonの音声系のライブラリlibrosaにヒントがあるかも。 あとはffmpegにもそういう機能があるかも。

その他

Yosshi999 commented 2 years ago

コンプレッサー(Wikipedia) について調べてみましたが"compressor"だとmp3圧縮などがヒットしてしまって検索が難しいですね https://librosa.org/doc/main/generated/librosa.mu_compress.html にコンプレッサーのようなものがありましたがこれが効くかどうかは分かりません ffmpegにはacompressorというフィルタがあるようです https://ffmpeg.org/ffmpeg-filters.html#acompressor

ただ、音声の圧縮の場合は上のwikipediaにあるようにどちらかというと歯擦音対策が主なのかもしれません

補足としてデフォルトの音声の大きさとしてLUFSという単位を使うのがいいらしいです https://en.wikipedia.org/wiki/Audio_normalization によれば、たいていのストリーミングサービスでは-14 LUFSになるように調整されているようです

Hiroshiba commented 2 years ago

なるほど、コンプレッサーを使えばいい・・・のでしょうか。 概念に馴染みがないためか、やりたいこと(音が割れないように音量を上げられる仕組み)ができるのかがちょっと判断つきませんでした・・・。

単位もありがとうございます。実は裏で、機械学習に用いる音声データの音量を揃えてみようとしているのですが、そこでLUFSの値が揃うようにしてみています。 (学習データが音割れすると悲しいのでちょっと小さめの-23LUFSにしてみています。)

tarepan commented 2 years ago

概要

本issueの希望動作は「clipを起こさずラウドネスを増加」.
対処法はダイナミックレンジ制御(コンプレッサー)、デモを添付.
実装は pyloudnorm + 何からのcompressor ?

分野背景

主観的な音の大きさをラウドネスといいます (≒音圧≠音量). LUFSはラウドネスの単位の1つです.
音声のラウドネスは波の最大振幅 (=音量) よりも平均振幅に依存します. 一瞬だけ0.99のピークがある音より、平均で0.7ある音を大きく感じる、というイメージです.
波形の定数倍(ゲイン方式)の問題点はダイナミックレンジの大きい信号がすぐに上限へ達してしまうことです. 高いピークがすぐに1.0になってしまい、ラウドネスを司る平均振幅は小さいままなので.

解決策

方針

高ダイナミックレンジが問題の根本にあるので、ダイナミックレンジ制御が解決手法になります.
イメージは「ピークがすぐ1に引っかかるなら、0.9超えた部分は1/2にしようぜ、そしたらもっとゲイン掛けられるじゃん」です.
音楽分野ではダイナミクス系・コンプレッサーリミッター・マキシマイザ等と呼ばれている手法です.

デモ

AudacityでのPoC/デモです.

中段はclipされ音割れしています.
下段は最大振幅がほぼ不変にもかかわらず、音割れせずに主観的な音の大きさが上がっています.
Audacityを入れている方であれば5分程度で検証可能かと思います.

実装

エディタ上のバーでラウドネスを指定、音割れさせずに指定ラウドネスまで増幅、が所望の動作かと思います.
「clip気にせず所望のラウドネスまでゲイン式の増幅」→「clip部を抑えるためにコンプレッサー掛ける」の2ステップ実装が私の第一感です.
前者はpyloudnormで可能です. 後者は有名なpython OSSがパッと思い浮かばないです.

まとめ

現動作: 音量パラメータで音量を定数倍、clipあり得る
希望動作: clipを起こさずラウドネスを増加
解決法: ゲインでラウドネス合わせたのち、コンプレッサーでclipを防止

Hiroshiba commented 2 years ago

おお、なるほどです!! とても良くわかりました。 とりあえず増幅→コンプレッサー、という流れでしょうか。

audacityもOSSなのでコードは持ってこれるかもしれませんが、さすがに大変そうな印象があります。 別にpythonだけで実装しなければならないこともないので、ffmpegなどの外部実行ファイルを同梱してしまっても良いかもです。

tarepan commented 2 years ago

memo for implementer

実装時hookポイント

https://github.com/VOICEVOX/voicevox_engine/blob/c935cf2585358bf7fc217389d63e5032885a516c/voicevox_engine/synthesis_engine/synthesis_engine.py#L463-L466

ラウドネス調整ライブラリ

pyloudnorm

speech = [...] # speech data
target_loudness = -10 # from editor

meter = pyln.Meter(rate)
source_loudness = meter.integrated_loudness(speech)
loudness_normalized_speech = pyln.normalize.loudness(speech, source_loudness, target_loudness)

コンプレッサーライブラリ

pedalboard
This has built-in Compressor.
But... this is licenced by GPL v3 (need discussion in #265).

Hiroshiba commented 2 years ago

いろいろ調べた感じ、コンプレッサーを導入すればOKみたいでした。 SoXという実行バイナリにもコンプレッサー機能がありました。

音量に関しては結構頻繁に課題の声が届いているので、優先度を上げたいと思います! https://twitter.com/KOUCAch/status/1589682431485153280 もしよければ、ぜひ・・・!

uboar commented 2 years ago

失礼します。Discordでコメントさせて頂いた者です。

といった内容をコメントさせて頂きました、が…

あの後色々調べた結果、PedalboardというPythonライブラリが非常に良さそうだと個人的に感じました。検討の余地があると思います。

リバーブ(コンプだと違いが分かりづらいので)を入れてSynthesisしてみました。ご参考までに。

# run.py
def synthesis
# --------------略----------------------------------
    effect_input = wave.astype('float32') #オーディオデータをf32に変換
    board = Pedalboard([Reverb(room_size=0.25)]) #リバーブエフェクターの作成
    effect_output = board(effect_input, query.outputSamplingRate) #エフェクトを掛ける
    with NamedTemporaryFile(delete=False) as f:
        soundfile.write(
            file=f, data=effect_output, samplerate=query.outputSamplingRate, format="WAV"
        )

https://user-images.githubusercontent.com/10250330/200873762-dcab229c-d697-4da8-8eee-ddde0fbc760d.mp4

sabonerune commented 2 years ago

GPLv3ライセンスみたいですね…

Hiroshiba commented 2 years ago

Pedalboard、すごく良さそうだけど・・・GPLなんですね・・・・・。 VOICEVOXはコアの音声合成のモデルがどうしても公開できず、そのためGPLを適用できない形態となっており。。

uboar commented 2 years ago

なるほど…GPLライセンスは使用できないのですね。失礼しました。もう少し情報収集してみます。

uboar commented 2 years ago

VST系はそもそも元のVST SDKがGPLなので厳しそうですね…(参考

追加でいくつか調べた物を挙げておきます。

ユーザーがパラメータを触る事を考えるとこの中ではffmpegのdynaudnormが良いと感じました。本格的なコンプレッサーはかなり調整が難しく、専門用語まみれなので…

おまけ

音を圧縮して音圧を稼ぐ事に対してやたらと色んな名前が付いていますが、目的に対して使い分けている場合が多いです(明確な定義が無いので必ずしもそうとは限りません。面倒くさい…)

qryxip commented 2 years ago

一応純Rustのライブラリも軽く調べてみましたが、こっちはあまり期待はできなさそうです。 (ライセンスはすべてMIT OR Apache-2.0です)

Hiroshiba commented 2 years ago

コメントありがとうございます!!とても参考になります・・・!!

ユーザーがパラメータを触る事を考えると

個人的にはできればユーザーが触らなくても、それっぽく音量がいい感じになるのが良いのかなと思っています。(大体のユーザーは方法がわからないので) コンプレッサーをかける(音量を均一化する)かどうかだけユーザー側で選べると良いのかなと思いました! その用途でもffmpegdynaudnorm便利そうですね!!これが良いのでは・・・?

ffmpegはmp3出力などにも利用できそうなので、導入しても良いのかなと思いました!

たしかffmpegは内部で使っているライブラリに応じて、GPL版とLGPL版があるはずです。 今回の用途だとLGPL版なら問題なく利用することができるはず・・・!

tarepan commented 8 months ago

@Hiroshiba

素朴な疑問(?)なのですが、「実際のところ、音割れ含め機能性になっている」という可能性はありますか?
音声合成エンジニアリングとしてはコンプレッサー実装が正しいのですが、「音割れ含む絶叫が面白い」というシチュエーションはYouTubeでよくある気がしまして(「絶叫するビーバー」的な)。

Hiroshiba commented 8 months ago

@tarepan たしかに可能性はあると思います!

実際にコンプレッサーをかけた爆音と、音割れしてる爆音を聴き比べて、差がありそうかどうかを検証してもいいかもですね・・・! ここに差があったら何かしらの策を考えても良いかもです。(コンプレッサーフラグをつけるとか、破壊的変更して別の編集ソフトでの編集をお願いするとか。)

個人的にはどちらかというと音割れしない方が需要が多そうなので、実装した場合少なくともデフォルトはコンプレッサーありにした方が良い気がしてます。

github-actions[bot] commented 2 months ago

本 Issue は直近 180 日間で活動がありません。今後の方針について VOICEVOX チームによる再検討がおこなわれる予定です。