Closed y-chan closed 2 months ago
まだ解決はしていませんが,エラーは再現できてこれがバグか否かまでは確認できたので現状報告です. 1.こちらはバグで修正可能と思われます. もともとの実装であるMATLAB版では再現しませんでしたので,C++へ移植した際に何らかの問題が生じているようです.
2,3への回答としてですが,暫定版としてcoarse_aperiodicityでNaNの部分を1.0に置き換えれば,MATLAB版に近い挙動になりそうです.
なんとなく原因は分かってきたのですが,まだ修正をどうするかまでが決まっておりません.修正法を含めて考えてみますので,少しお時間を頂きますようお願いいたします(おそらく何らかのセーフガードを入れることになります).
とりあえず,大まかな原因と解決法は分かったので共有いたします.簡単に言えば,入力信号にごく小さい(結果に影響を及ぼさないと思われる範囲でやや大きめな)雑音を加えればOKです.
for (int i = 0; i < x_length; ++i) x[i] = x[i] + 0.000001 * randn();
今回でしたら,上記のコードをAperiodicityEstimationの手前に入れれば動きました.
問題はそもそもの原因ですが,これは短時間フーリエ変換でパワースペクトルを求めた際に,ナイキスト周波数付近で極端に小さな値になっていることです.その帯域のパワーが途中の処理で完全な0になってしまっており,途中でパワーで割り算する処理があるためそこから破綻していくようです.そのため,上記のように全帯域にパワーを乗せることで回避そのものはできます.
元々この影響は想定しており,D4CでもGetWindowedWaveform内部関数で同様の処理を入れていましたが,ノイズ量が小さすぎて効果が発揮されなかったようです.これを増やすことでも解決できそうではありますが,この値は音声に雑音を加えることで根本的に非周期性成分を増やすことになりますので,エラーが生じないバランスをどうとるかについては議論の余地があります.
その辺についてはなんとも言いにくいのですが,もしご希望があればお知らせ頂ければ検討いたします.
こちら,前のコメントで書いたとおり加算するノイズ量を調整することで解決することにしました.通常音声を対象に影響を調べたところ,概ね0.001%未満の誤差で収まりそうなので,推定結果に与える影響はないと思います.ノイズ量の定数は新たに追加したので,d4c.cppとconstantnumbers.hの2つを修正しました.こちらでは問題なくNaNが消えておりますので,ご確認いただけると助かります.
返信遅くなりすみません! 迅速な調査・修正助かります...! あまり知識が深くはないのですが、誤差が大きくならないのであれば、雑音成分を足すのが良いのかなと思いました。 後ほどこちらでも確認してみます。
ありがとうございます!!
大変おそくなりました、こちらでも複数のファイルで試してみましたが、nanの出現がなくなったので、無事に解決できたものと思います。 こちらのIssueはcloseとしたいと思います! ありがとうございました...!
こんにちは、音声合成の研究を行っているy-chanと申します。素晴らしいライブラリの提供をありがとうございます。
WorldのPythonラッパーであるPyWorldを用いて、音声分析を行なっていた際、d4cの出力結果である非周期性指標にnanが含まれる場合があることを確認しました。 これは、Worldでの再合成でも、別の手法を用いた場合でも再合成に大きな影響をもたらします。
しかし、nanを引き起こすwavファイルを、Worldのexample(
examples/analysis_synthesis/analysis.cpp
をコンパイルしたバイナリ)で直接読み込むことはできませんでした。そのためexampleを改変し、double型の配列をバイナリから読み込むものをexamples/analysis_synthesis/analysis_dat.cpp
として作成して調べた結果、World単体でも再現することを確認しました。PyWorldでnanを引き起こしたファイルEMOTION100_010.wav.datを以下の手順で分析させたところ、出力結果にnanが含まれることがわかりました。
examples/analysis_synthesis/analysis_dat.cpp
を配置して、以下のコマンドを実行します。 当方の環境はMacですが、WindowsやLinuxでも同様に実行できるはずです。analysis_dat.cpp
このファイルでは、datファイルを読み込む以外にも、f0推定手法をHarvestに変更したり、`frame_period`を変更したりして、該当ファイルでnanが出る条件を合わせています。 また、doubleの配列バイナリとしてではなく、可読性の観点から数値を文字列として出力しています。 ```cpp //----------------------------------------------------------------------------- // Copyright 2016 seblemaguer // Author: https://github.com/seblemaguer // Last update: 2017/02/01 // // Summary: // The example analyzes a .wav file and outputs three files in each parameter. // Files are used to synthesize speech by "synthesis.cpp". // // How to use: // The format is shown in the line 253. //----------------------------------------------------------------------------- #includeここで、伺いたい点が2点あります。
static_group_delay
が怪しいように感じましたが、私には適切な修正方法がわかりませんでした。coarse aperiodicity
を補完して生成しているものであるので、グラデーションのような値でうめるべきかと考えています。しかし、d4cの出力に対してアプローチすると実装が複雑化しそうで、coarse aperiodicity
の時点でnanを消せると一番綺麗になるのかなと思っています。とはいえ、現時点でWorldはcoarse aperiodicity
を出力していないので、アプローチが難しいのが現状です。以上、ご回答いただければ幸いです。 よろしくお願いします。