-
Notifications
You must be signed in to change notification settings - Fork 118
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
fix compat breaking: revive workaround padding in decode() #867
fix compat breaking: revive workaround padding in decode() #867
Conversation
#866 (comment)
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
うおーーーありがとうございます!!!!
かなりすっきりさせられそうかもと感じました!!
start/endが範囲外ならエラーを返すようにすれば更にシンプルにできそうに感じました!
個人的には、範囲外を指定したときにclipされるのかpadされるのか自明じゃないので、エラー返すのが誤解しづらくて良いかもとちょっと思いました。
あとtrim_wave
は要らないはず・・・?
/// 変換前に追加した安全マージンを生成音声から取り除く | ||
fn trim_margin_from_wave( | ||
wave_with_margin: &ndarray::Array1<f32>, | ||
) -> Result<ndarray::ArrayView1<f32>> { | ||
let wave = wave_with_margin.slice(ndarray::s![ | ||
MARGIN * 256..wave_with_margin.len() - MARGIN * 256 | ||
]); | ||
Ok(wave) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
この関数が必要になることはない・・・はず・・・?
(必ずpaddingもmarginもない音声が出てくるので)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
render_audio_segment
では単純にonnxを回すだけの関数であるため、crop_with_margin
で取り出したマージン付きの音声特徴量を音声に変換した後、両端の(長さが256倍され、かつ一括変換の場合と結果が異なっている)マージンを削除する必要があります。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
あれ、なるほどです! ちょっとどこか認識が違うことがわかりました!! 🙇
render_audio_segment
のonnxって、MARGIN*2+N
フレーム入力すると、N*256
サンプル出力される・・・とい理解で合ってそうでしょうか 👀
であれば、crop_with_margin
は、目的の音声のフレーム数+MARGIN*2
だけクロップする感じだと思うので、出てきた音声の両端を削除する必要はない・・・・はず・・・・?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
onnxはMARGIN*2+N
に対し256*(MARGIN*2+N)
が出てきます。元のonnxと同じ実装です
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
!!!!! あっなるほどです!!! onnxの方はzero-paddingする感じになってるんですね!!
この前提が抜けていた提案をしまくっていました 🙇 🙇 🙇
これはちょっと話題が変わってしまうのですが、ちなみに元実装の方をpaddingしないようにって難しそうでしょうか・・・? 👀
というのもMARGIN*2
が28なので、仮に0.5秒ごとに生成すると93.75*0.5
≒46フレームだから、結構な計算量削減になりそうだなーーーと思い。
(再生を始められる、つまりRTFが1を下回るフレーム数をより下げることができるので、より再生開始を早められるなぁーーと・・・)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
marginについても出力の一貫性を保つためのものなので縮められません(多少は無理して減らせると思いますが..)
再生開始までの時間を早くするためにいじれる変数はおそらくバッファ長(何秒ごとに生成するか)しかないと思います。RTFから最適なバッファ長を計算する方程式を立てることができ、陽に解くことができるとおもいます
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
あ、paddingはCONVが自動的挟んでるゼロパディングのことを指していました!!
ゼロパディングありで学習した場合でも、十分なMARGINが確保されていれば同じ値が出力されます!
例えばこちらの説明だと、padding有り無しで真ん中9つの値は変わってないのがわかると思います。
https://zero2one.jp/ai-word/padding/
影響を受けるのはゼロパディングを計算に含めた場所、つまり両端14フレームだけ・・・なはず。
Nフレーム入力すれば中央N-14*2
フレームは同じが結果になります。
なので逆に両端14フレーム伸ばすことで、Nフレーム同じ結果が出力されるはず・・・!!!
decoderの再学習なしでも、ゼロパディングをなくして合成することは可能だという認識です・・・!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
つまりすべてのconvolutionのpaddingをSAMEからVALIDに変えるということですか?試したことはないですね..
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ですです!! 結構計算量が削減できるのではと思ってます!!
あ、onnxruntimeだとVALIDが指定可能なんですね!!!
変換前のpytorchで全convのpadを0にするのを考えてたのですが、onnxruntime変換時や変換後でも良さそう。
pytorchでやるなら、hifiganのmodel.modules()
を総なめしてConvの.pad=0
にするとかなのかなと考えてました。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
あ、とはいえ今マストでは無いかもです!
リリースするまでならあとで変えるとかでも良さそうですし、なんならこのままリリースも超問題ってわけではなさそう。
例えば先にエンジン作ってからという手もありだと思います!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!!!
ありがとうございました!!!\
コード中のコメントの細かいお願いがいくつかあったのでプルリクエストを出してみました。
@Yosshi999 さん側でちょっと取り込んでいただければ!(もちろんプルリクエストの内容をさらに変更しても大丈夫です!)
それとなのですが、またpythonを使った音声の生成結果がmainブランチと全く同じものになっているか確認お願いしてもよろしいでしょうか 🙇
念のために確認しておくと、あとあと計算結果が合わないときに「コアは大丈夫」と自信を持って進めそうだなーと・・・!
if range.start > audio.frame_length || range.end > audio.frame_length { | ||
panic!( | ||
"{range:?} is out of range for audio feature of length {frame_length}", | ||
frame_length = audio.frame_length, | ||
); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(細かいですが)
start>=0も確認した方が良さそう
あと原理上end>lengthを確認したならstart>lengthは自明そう?(なので処理が簡単になりそう)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
start>=0
#867 (comment)でも書きましたが、型的に無意味というかむしろそれを書いたらリンタが激怒すると思います。
あと原理上end>lengthを確認したならstart>lengthは自明そう?(なので処理が簡単になりそう)
(おそらく言語問わず)
現状だと
ただ今考えたら、一貫性のために
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
start > end
はRangeインスタンスの生成時に落ちるものと思ってたんですが、ドキュメントを見た感じそうでもなさそうですかね?
バリデーションは積極的に通すみたいな方針にするというのをどこかで話した気がするのでこれもpanicさせましょうか
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
そうですね。Range
自体はただの二つの整数の組です。あと10..0
みたいなのも、Pythonのslice
じゃなくrange
的な使い方をする分には空のイテレータを返します。リンタには怒られますが。
バリデーションは積極的に通すみたいな方針にする
ですね。パニックにしちゃいましょう。パニックメッセージ的にはこう?
if range.start > audio.frame_length || range.end > audio.frame_length { | |
panic!( | |
"{range:?} is out of range for audio feature of length {frame_length}", | |
frame_length = audio.frame_length, | |
); | |
} | |
if range.start > range.end { | |
panic!("index starts at {} but ends at {}", range.start, range.end); | |
} | |
if range.end > audio.frame_length { | |
panic!( | |
"{range:?} is out of range for audio feature of length {frame_length}", | |
frame_length = audio.frame_length, | |
); | |
} |
Python API側はIndexError
じゃなくてValueError
にすればよさそう。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
あ、30分前にコミットされてましたね。これでよさそう。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ONNX Runtimeに渡すのはマージン入れたやつ
たしかに 無駄な処理を省けるという利点はあります
Python APIではstart > endの場合、IndexErrorというよりはValueError…?
pythonでstart > endで落ちる例が思いつきません
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pythonでstart > endで落ちる例が思いつきません
むしろ普通のPythonではありえないからこそ、IndexError
は避けた方がよいのではないかと思いました。
ValueError
はJavaで言うIllegalArgumentException
だと理解しています。あとissubclass(IndexError, LookupError)
なので、AudioFeatureのlengthに関わらずstart > end
は不正ということで、ValueError
でいいんじゃないかなーと思った次第です。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
なるほど、ValueErrorにします
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
start > end
の場合を弾くようにしたので、最初ヒホさんが言ったようにrange.start > audio.frame_length
は省けそう
これについてですがRustの[T]
では
let a = [1, 2, 3];
let _ = a[5000..1000];
がslice index starts at 5000 but ends at 1000
というメッセージになる(i.e. range start index {i} out of range for slice of length {len}
やrange end index {i} out of range for slice of length {len}
よりも優先される)ので、それにならうという意味でもやった方がいいかなと思いました。
streaming有り無しの比較結果
mainブランチとの比較結果
|
検証ありがとうございます!!! 現時点の変更も確認しました、良さそう!! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!!!!!
ありがとうございました!!!
内容
#854 でdecodeからworkaround用の無音paddingを消してしまい、compatible engineの挙動が変わってしまっていた
#866 (comment) に従い、
もともと
Synthesizer::decode
... 無音パディングを付加Synthesizer::synthesis
...Synthesizer::decode
を利用extern "C" fn decode_forward
...Synthesizer::decode
をそのまま利用 (→無音パディングあり)だったものに対して #854 は
Synthesizer::generate_full_intermediate
... 無音パディングなしで中間物生成Synthesizer::render_audio_segment
... マージンなしで与えられた音声特徴全体で音声生成Synthesizer::decode
...Synthesizer::generate_full_intermediate
とSynthesizer::render_audio_segment
を利用(→無音パディングなし)Synthesizer::precompute_render
... 無音パディングを付加してSynthesizer::generate_full_intermediate
Synthesizer::render
... マージンを付けて&指定された区間でSynthesizer::render_audio_segment
(+暗黙的にパディングが除去される)Synthesizer::synthesis
...Synthesizer::precompute_render
とSynthesizer::render
を利用extern "C" fn decode_forward
...Synthesizer::decode
をそのまま利用(→無音パディングなし)になっていたので、
Synthesizer::generate_full_intermediate
... 無音パディングを付加して中間物生成Synthesizer::render_audio_segment
... マージンを付けて&指定された区間で音声生成Synthesizer::decode
...Synthesizer::generate_full_intermediate
とSynthesizer::render_audio_segment
を利用Synthesizer::precompute_render
...Synthesizer::generate_full_intermediate
を利用Synthesizer::render
...Synthesizer::render_audio_segment
を利用Synthesizer::synthesis
...Synthesizer::precompute_render
とSynthesizer::render
を利用extern "C" fn decode_forward
...Synthesizer::decode
をそのまま利用extern "C" fn generate_full_intermediate
...Synthesizer::generate_full_intermediate
をそのまま利用extern "C" fn render_audio_segment
...Synthesizer::render_audio_segment
をそのまま利用に変更した
関連 Issue
その他