Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
F0推定アルゴリズムHarvestは中で何をしているのか
Search
nagiss
September 25, 2023
Technology
3
1.1k
F0推定アルゴリズムHarvestは中で何をしているのか
DeNAの2023/5/24の音声トークの発表資料を焼き直したものです。
nagiss
September 25, 2023
Tweet
Share
More Decks by nagiss
See All by nagiss
F0推定の手法を色々試してみる
nagiss
1
310
音信号の電子透かし
nagiss
0
190
ヒューリスティックコンテストで機械学習しよう
nagiss
8
5k
XNNPACKを直接使ってみた
nagiss
0
500
SantaとAHCと遺伝的アルゴリズム
nagiss
8
3.5k
Kaggleシミュレーションコンペの動向
nagiss
1
950
Other Decks in Technology
See All in Technology
BLADE: An Attempt to Automate Penetration Testing Using Autonomous AI Agents
bbrbbq
0
290
第1回 国土交通省 データコンペ参加者向け勉強会③- Snowflake x estie編 -
estie
0
120
サイバーセキュリティと認知バイアス:対策の隙を埋める心理学的アプローチ
shumei_ito
0
380
Exadata Database Service on Dedicated Infrastructure(ExaDB-D) UI スクリーン・キャプチャ集
oracle4engineer
PRO
2
3.2k
Taming you application's environments
salaboy
0
180
社内で最大の技術的負債のリファクタリングに取り組んだお話し
kidooonn
1
550
Terraform CI/CD パイプラインにおける AWS CodeCommit の代替手段
hiyanger
1
240
誰も全体を知らない ~ ロールの垣根を超えて引き上げる開発生産性 / Boosting Development Productivity Across Roles
kakehashi
1
220
Platform Engineering for Software Developers and Architects
syntasso
1
510
dev 補講: プロダクトセキュリティ / Product security overview
wa6sn
1
2.3k
SREによる隣接領域への越境とその先の信頼性
shonansurvivors
2
510
Amazon CloudWatch Network Monitor のススメ
yuki_ink
1
200
Featured
See All Featured
The Psychology of Web Performance [Beyond Tellerrand 2023]
tammyeverts
44
2.2k
Sharpening the Axe: The Primacy of Toolmaking
bcantrill
38
1.8k
Navigating Team Friction
lara
183
14k
Measuring & Analyzing Core Web Vitals
bluesmoon
4
120
The Cost Of JavaScript in 2023
addyosmani
45
6.7k
Stop Working from a Prison Cell
hatefulcrawdad
267
20k
RailsConf & Balkan Ruby 2019: The Past, Present, and Future of Rails at GitHub
eileencodes
131
33k
Build your cross-platform service in a week with App Engine
jlugia
229
18k
Easily Structure & Communicate Ideas using Wireframe
afnizarnur
191
16k
We Have a Design System, Now What?
morganepeng
50
7.2k
Statistics for Hackers
jakevdp
796
220k
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
356
29k
Transcript
© DeNA Co., Ltd. 1 nagiss ソリューション事業本部データ統括部AI技術開発部 株式会社ディー・エヌ・エー F0 推定アルゴリズム
Harvest は 中で何をしているのか
© DeNA Co., Ltd. 2 1 • Harvest のコードをある程度読み解いたので、せっかくなら公開しておこうと資料の形にしたもの ◦
隅々まで読み解こうとはしていないので所々「よくわからない」があります • 参考にしたもの ◦ 実装 https://github.com/mmorise/World/blob/master/src/harvest.cpp ◦ 森勢将雅, “高い雑音耐性と推定精度を両立する基本周波数推定法の提案と評価,” 信学技報, 2016 http://www.isc.meiji.ac.jp/~mmorise/lab/publication/paper/SP2016-62.pdf この資料は何?
© DeNA Co., Ltd. 3 2 • Harvest では内部的に 1ms
を 1 フレームとして扱っている。 ◦ 1ms 以外で出力する場合は最後に最近傍補間している。 • 例として JVS003 UT-PARAPHRASE-sent239-phrase2 を分析 人生は結局、孤独を和らげるために、生きているようなもんだ ◦ 下線部の 1 秒間 ◦ 「き」が無声化している 前置き 分析対象とした音声のスペクトログラム
© DeNA Co., Ltd. 4 3 コード概観 - Harvest -
HarvestGeneralBody - GetWaveformAndSpectrum ... 直流成分の除去、後の畳み込みのための FFT - GetWaveformAndSpectrumSub - HarvestGeneralBodySub - GetRawF0Candidates - (number_of_bands) GetF0CandidateFromRawEvent - GetFilteredSignal ... FFT でその帯域の BPF を畳み込む - (2) fft_execute - GetFourZeroCrossingIntervals ... ゼロ交叉/ピークの点を列挙、間隔から f0 を計算 - GetF0CandidateContour - (4) interp1 ... f0 を時間方向に補間 - GetF0CandidateContourSub ... 4 つの平均を計算、ばらけていたら 0 - DetectOfficialF0Candidates - (f0_length) DetectOfficialF0CandidatesSub1 ... 台を検出 - (f0_length) DetectOfficialF0CandidatesSub2 ... 各台の平均 f0 を計算、細い台は無視 - OverlapF0Candidates ... 前後 3 フレームに f0 候補をコピー - RefineF0Candidates ... f0 候補を瞬時周波数で修正 - (f0_length * num_candidates) GetRefinedF0 ... 窓長の計算、GetMeanF0 - GetMeanF0 - GetBaseIndex ... 窓をかける場所を求める - GetMainWindow ... 地味に重い - GetDiffWindow ... MainWindow の微分した窓を求める - GetSpectra ... 2 つの窓で FFT する、ここが重い - (2) fft_execute - FixF0 ... 瞬時周波数の計算 - RemoveUnreliableCandidates ... 前後どちらのフレームにも差が 5% 以内の f0 候補が無いような f0 候補を削除 - ((f0_length - 2) * number_of_candidates) RemoveUnreliableCandidatesSub ... 前後 1 フレームに対して SelectBestF0 - (2) SelectBestF0 ... 自身に最も近い f0 を得る - FixF0Contour - SearchF0Base ... 各フレームで最もスコアの高い f0 候補を抽出する - FixStep1 ... 前フレームの f0 と前2フレームから線形で予測した f0 の両方から 0.8% 以上の差がある場合は f0 を 0 にする - FixStep2 ... 5 フレーム以下しか連続しない有声区間を削除 - GetBoundaryList ... 有声部の閉区間のリストを作る - FixStep3 ... - GetBoundaryList - GetMultiChannelF0 ... 有声区間ごとに分けて別の配列にする - Extend ... 各有声区間を前後に伸ばす - (number_of_sections * 2) ExtendF0 - (distance + 1) SelectBestF0 ... 18% 以内の差なら採択する - ExtendSub ... 有声区間が十分な長さ (平均 100Hz なら 22 フレーム、200Hz なら 11 フレーム) ないものを削除 - MergeF0 ... 有声区間をマージする - MakeSortedOrder ... 有声区間たちを開始時刻の昇順にソート - MergeF0Sub ... 区間が重なる場合に、重なった部分のスコアの和が大きい方を選ぶ - (2) SearchScore - FixStep4 ... 短い無声区間を線形補間で埋める - GetBoundaryList - SmoothF0Contour ... F0 軌跡に LPF をかけて滑らかにする - GetBoundaryList - GetMultiChannelF0 ... 2 回目 - (number_of_boundaries) FilteringF0
© DeNA Co., Ltd. 5 4 • 入力音声を帯域の異なるバンドパスフィルタに通して複 製し、それぞれを正弦波と見做してゼロ交叉・山と谷の 時間間隔により
F0 を求めることで、F0の候補とする。 ◦ 1 オクターブあたり 40ch、71Hz ~ 800Hz なら計 140ch の信号になる。 ◦ 求めた F0 がその帯域の中心から 10% 以上離れて いたら候補としない。 ◦ バンドパスフィルタは次スライド ▪ FFT を使って畳み込んでいるが、ちょっとずつやらないで入力 音声全体を FFT しているので計算量は線形時間より大きい、と はいえここが律速することはなさそう GetRawF0Candidates - Harvest - HarvestGeneralBody - GetWaveformAndSpectrum ... 直流成分の除去、後の畳み込みのための FFT - GetWaveformAndSpectrumSub - HarvestGeneralBodySub - GetRawF0Candidates - (number_of_bands) GetF0CandidateFromRawEvent - GetFilteredSignal ... FFT でその帯域の BPF を畳み込む - (2) fft_execute - GetFourZeroCrossingIntervals ... ゼロ交叉/ピークの点を列挙、間隔から f0 を計算 - GetF0CandidateContour - (4) interp1 ... f0 を時間方向に補間 - GetF0CandidateContourSub ... 4 つの平均を計算、ばらけていたら 0 - DetectOfficialF0Candidates - (f0_length) DetectOfficialF0CandidatesSub1 ... 台を検出 - (f0_length) DetectOfficialF0CandidatesSub2 ... 各台の平均 f0 を計算、細い台は無視 - OverlapF0Candidates ... 前後 3 フレームに f0 候補をコピー - RefineF0Candidates ... f0 候補を瞬時周波数で修正 - (f0_length * num_candidates) GetRefinedF0 ... 窓長の計算、GetMeanF0 - GetMeanF0 - GetBaseIndex ... 窓をかける場所を求める - GetMainWindow ... 地味に重い - GetDiffWindow ... MainWindow の微分した窓を求める - GetSpectra ... 2 つの窓で FFT する、ここが重い - (2) fft_execute - FixF0 ... 瞬時周波数の計算 - RemoveUnreliableCandidates ... 前後どちらのフレームにも差が 5% 以内の f0 候補が無いような f0 候補を削除 - ((f0_length - 2) * number_of_candidates) RemoveUnreliableCandidatesSub ... 前後 1 フレームに対して SelectBestF0 - (2) SelectBestF0 ... 自身に最も近い f0 を得る - FixF0Contour - SearchF0Base ... 各フレームで最もスコアの高い f0 候補を抽出する - FixStep1 ... 前フレームの f0 と前2フレームから線形で予測した f0 の両方から 0.8% 以上の差がある場合は f0 を 0 にする - FixStep2 ... 5 フレーム以下しか連続しない有声区間を削除 - GetBoundaryList ... 有声部の閉区間のリストを作る - FixStep3 ... - GetBoundaryList - GetMultiChannelF0 ... 有声区間ごとに分けて別の配列にする - Extend ... 各有声区間を前後に伸ばす - (number_of_sections * 2) ExtendF0 - (distance + 1) SelectBestF0 ... 18% 以内の差なら採択する - ExtendSub ... 有声区間が十分な長さ (平均 100Hz なら 22 フレーム、200Hz なら 11 フレーム) ないものを削除 - MergeF0 ... 有声区間をマージする - MakeSortedOrder ... 有声区間たちを開始時刻の昇順にソート - MergeF0Sub ... 区間が重なる場合に、重なった部分のスコアの和が大きい方を選ぶ - (2) SearchScore - FixStep4 ... 短い無声区間を線形補間で埋める - GetBoundaryList - SmoothF0Contour ... F0 軌跡に LPF をかけて滑らかにする - GetBoundaryList - GetMultiChannelF0 ... 2 回目 - (number_of_boundaries) FilteringF0
© DeNA Co., Ltd. 6 5 GetRawF0Candidates - バンドパスフィルタ cos
関数とナットール窓を掛け合わせて作られた線形位相バンドパスフィルタと、 その周波数応答 (ピークの周波数が 200Hz の場合) sr = 24000 freq = 200 # バンドパスフィルタのピーク周波数 period = sr // freq # 周期 n_fft = 1 << 16 win = np.zeros(n_fft) win[:4 * period] = scipy.signal.nuttall(4 * period) win[:4 * period] *= np.cos(np.linspace(0.0, 8.0 * np.pi, 4 * period)) plt.figure(figsize=(10, 4)) plt.plot(win[:4 * period]) plt.grid(color="gray") plt.show() f = np.fft.rfft(win) w = 20 * np.log10(np.abs(f)) w -= w.max() plt.figure(figsize=(10, 4)) plt.plot(np.arange(n_fft // 2 + 1) / n_fft * sr, w) plt.grid(color="gray") plt.xlabel("frequency [Hz]") plt.ylabel("[dB]") plt.xlim(0, 1000) plt.ylim(-120, 0) plt.show() 左の図の描画コード • 200Hz の cos 関数は周波数領域で 200 Hz にピークの立つデルタ関数になる • 長さ 4/200 秒のナットール窓は周波数領域でメインローブの半径が 200Hz になる • 時間領域の掛け算は周波数領域の畳み込みなので、上記の周波数応答が得られる
© DeNA Co., Ltd. 7 6 GetRawF0Candidates - 結果の例 得られた
F0 候補
© DeNA Co., Ltd. 8 7 • 帯域を横軸、得られた周波数を縦軸に取ったグラフを書 くと、いくつかの台ができる。 ◦
論文中の図 • 各台の周波数を平均をとることで 1 つにまとめてしま う。細い台は除去する。 DetectOfficialF0Candidates - Harvest - HarvestGeneralBody - GetWaveformAndSpectrum ... 直流成分の除去、後の畳み込みのための FFT - GetWaveformAndSpectrumSub - HarvestGeneralBodySub - GetRawF0Candidates - (number_of_bands) GetF0CandidateFromRawEvent - GetFilteredSignal ... FFT でその帯域の BPF を畳み込む - (2) fft_execute - GetFourZeroCrossingIntervals ... ゼロ交叉/ピークの点を列挙、間隔から f0 を計算 - GetF0CandidateContour - (4) interp1 ... f0 を時間方向に補間 - GetF0CandidateContourSub ... 4 つの平均を計算、ばらけていたら 0 - DetectOfficialF0Candidates - (f0_length) DetectOfficialF0CandidatesSub1 ... 台を検出 - (f0_length) DetectOfficialF0CandidatesSub2 ... 各台の平均 f0 を計算、細い台は無視 - OverlapF0Candidates ... 前後 3 フレームに f0 候補をコピー - RefineF0Candidates ... f0 候補を瞬時周波数で修正 - (f0_length * num_candidates) GetRefinedF0 ... 窓長の計算、GetMeanF0 - GetMeanF0 - GetBaseIndex ... 窓をかける場所を求める - GetMainWindow ... 地味に重い - GetDiffWindow ... MainWindow の微分した窓を求める - GetSpectra ... 2 つの窓で FFT する、ここが重い - (2) fft_execute - FixF0 ... 瞬時周波数の計算 - RemoveUnreliableCandidates ... 前後どちらのフレームにも差が 5% 以内の f0 候補が無いような f0 候補を削除 - ((f0_length - 2) * number_of_candidates) RemoveUnreliableCandidatesSub ... 前後 1 フレームに対して SelectBestF0 - (2) SelectBestF0 ... 自身に最も近い f0 を得る - FixF0Contour - SearchF0Base ... 各フレームで最もスコアの高い f0 候補を抽出する - FixStep1 ... 前フレームの f0 と前2フレームから線形で予測した f0 の両方から 0.8% 以上の差がある場合は f0 を 0 にする - FixStep2 ... 5 フレーム以下しか連続しない有声区間を削除 - GetBoundaryList ... 有声部の閉区間のリストを作る - FixStep3 ... - GetBoundaryList - GetMultiChannelF0 ... 有声区間ごとに分けて別の配列にする - Extend ... 各有声区間を前後に伸ばす - (number_of_sections * 2) ExtendF0 - (distance + 1) SelectBestF0 ... 18% 以内の差なら採択する - ExtendSub ... 有声区間が十分な長さ (平均 100Hz なら 22 フレーム、200Hz なら 11 フレーム) ないものを削除 - MergeF0 ... 有声区間をマージする - MakeSortedOrder ... 有声区間たちを開始時刻の昇順にソート - MergeF0Sub ... 区間が重なる場合に、重なった部分のスコアの和が大きい方を選ぶ - (2) SearchScore - FixStep4 ... 短い無声区間を線形補間で埋める - GetBoundaryList - SmoothF0Contour ... F0 軌跡に LPF をかけて滑らかにする - GetBoundaryList - GetMultiChannelF0 ... 2 回目 - (number_of_boundaries) FilteringF0
© DeNA Co., Ltd. 9 8 DetectOfficialF0Candidates - 結果の例 F0
候補
© DeNA Co., Ltd. 10 9 RefineF0Candidates - Harvest -
HarvestGeneralBody - GetWaveformAndSpectrum ... 直流成分の除去、後の畳み込みのための FFT - GetWaveformAndSpectrumSub - HarvestGeneralBodySub - GetRawF0Candidates - (number_of_bands) GetF0CandidateFromRawEvent - GetFilteredSignal ... FFT でその帯域の BPF を畳み込む - (2) fft_execute - GetFourZeroCrossingIntervals ... ゼロ交叉/ピークの点を列挙、間隔から f0 を計算 - GetF0CandidateContour - (4) interp1 ... f0 を時間方向に補間 - GetF0CandidateContourSub ... 4 つの平均を計算、ばらけていたら 0 - DetectOfficialF0Candidates - (f0_length) DetectOfficialF0CandidatesSub1 ... 台を検出 - (f0_length) DetectOfficialF0CandidatesSub2 ... 各台の平均 f0 を計算、細い台は無視 - OverlapF0Candidates ... 前後 3 フレームに f0 候補をコピー - RefineF0Candidates ... f0 候補を瞬時周波数で修正 - (f0_length * num_candidates) GetRefinedF0 ... 窓長の計算、GetMeanF0 - GetMeanF0 - GetBaseIndex ... 窓をかける場所を求める - GetMainWindow ... 地味に重い - GetDiffWindow ... MainWindow の微分した窓を求める - GetSpectra ... 2 つの窓で FFT する、ここが重い - (2) fft_execute - FixF0 ... 瞬時周波数の計算 - RemoveUnreliableCandidates ... 前後どちらのフレームにも差が 5% 以内の f0 候補が無いような f0 候補を削除 - ((f0_length - 2) * number_of_candidates) RemoveUnreliableCandidatesSub ... 前後 1 フレームに対して SelectBestF0 - (2) SelectBestF0 ... 自身に最も近い f0 を得る - FixF0Contour - SearchF0Base ... 各フレームで最もスコアの高い f0 候補を抽出する - FixStep1 ... 前フレームの f0 と前2フレームから線形で予測した f0 の両方から 0.8% 以上の差がある場合は f0 を 0 にする - FixStep2 ... 5 フレーム以下しか連続しない有声区間を削除 - GetBoundaryList ... 有声部の閉区間のリストを作る - FixStep3 ... - GetBoundaryList - GetMultiChannelF0 ... 有声区間ごとに分けて別の配列にする - Extend ... 各有声区間を前後に伸ばす - (number_of_sections * 2) ExtendF0 - (distance + 1) SelectBestF0 ... 18% 以内の差なら採択する - ExtendSub ... 有声区間が十分な長さ (平均 100Hz なら 22 フレーム、200Hz なら 11 フレーム) ないものを削除 - MergeF0 ... 有声区間をマージする - MakeSortedOrder ... 有声区間たちを開始時刻の昇順にソート - MergeF0Sub ... 区間が重なる場合に、重なった部分のスコアの和が大きい方を選ぶ - (2) SearchScore - FixStep4 ... 短い無声区間を線形補間で埋める - GetBoundaryList - SmoothF0Contour ... F0 軌跡に LPF をかけて滑らかにする - GetBoundaryList - GetMultiChannelF0 ... 2 回目 - (number_of_boundaries) FilteringF0 • F0 候補を、瞬時周波数を求めることで再計算する。 • よくわからない方法で求めていた。 ◦ 窓関数をかけて DFT をすると複素スペクトルが得ら れるが、予め時間微分した窓関数をかけて DFT をす ると複素スペクトルの時間微分が得られ、この 2 回の DFT の結果から瞬時周波数を求めているらしい。 • F0 候補の信頼度もここでよくわからない式で求めてい た。 • とても重い ◦ F0 に対して適応的な (3 周期分の) 窓を使うので、毎 回窓関数を計算している ▪ 入力サンプリングレートが 8000Hz の倍数なら窓は 300 種類くらいになり そうなので、それを全部前計算するとかで高速化できるかも ◦ FFT が候補の数 * 2 回走る
© DeNA Co., Ltd. 11 10 RefineF0Candidates - 結果の例 精緻化された
F0 候補とその信頼度
© DeNA Co., Ltd. 12 11 RemoveUnreliableCandidates - Harvest -
HarvestGeneralBody - GetWaveformAndSpectrum ... 直流成分の除去、後の畳み込みのための FFT - GetWaveformAndSpectrumSub - HarvestGeneralBodySub - GetRawF0Candidates - (number_of_bands) GetF0CandidateFromRawEvent - GetFilteredSignal ... FFT でその帯域の BPF を畳み込む - (2) fft_execute - GetFourZeroCrossingIntervals ... ゼロ交叉/ピークの点を列挙、間隔から f0 を計算 - GetF0CandidateContour - (4) interp1 ... f0 を時間方向に補間 - GetF0CandidateContourSub ... 4 つの平均を計算、ばらけていたら 0 - DetectOfficialF0Candidates - (f0_length) DetectOfficialF0CandidatesSub1 ... 台を検出 - (f0_length) DetectOfficialF0CandidatesSub2 ... 各台の平均 f0 を計算、細い台は無視 - OverlapF0Candidates ... 前後 3 フレームに f0 候補をコピー - RefineF0Candidates ... f0 候補を瞬時周波数で修正 - (f0_length * num_candidates) GetRefinedF0 ... 窓長の計算、GetMeanF0 - GetMeanF0 - GetBaseIndex ... 窓をかける場所を求める - GetMainWindow ... 地味に重い - GetDiffWindow ... MainWindow の微分した窓を求める - GetSpectra ... 2 つの窓で FFT する、ここが重い - (2) fft_execute - FixF0 ... 瞬時周波数の計算 - RemoveUnreliableCandidates ... 前後どちらのフレームにも差が 5% 以内の f0 候補が無いような f0 候補を削除 - ((f0_length - 2) * number_of_candidates) RemoveUnreliableCandidatesSub ... 前後 1 フレームに対して SelectBestF0 - (2) SelectBestF0 ... 自身に最も近い f0 を得る - FixF0Contour - SearchF0Base ... 各フレームで最もスコアの高い f0 候補を抽出する - FixStep1 ... 前フレームの f0 と前2フレームから線形で予測した f0 の両方から 0.8% 以上の差がある場合は f0 を 0 にする - FixStep2 ... 5 フレーム以下しか連続しない有声区間を削除 - GetBoundaryList ... 有声部の閉区間のリストを作る - FixStep3 ... - GetBoundaryList - GetMultiChannelF0 ... 有声区間ごとに分けて別の配列にする - Extend ... 各有声区間を前後に伸ばす - (number_of_sections * 2) ExtendF0 - (distance + 1) SelectBestF0 ... 18% 以内の差なら採択する - ExtendSub ... 有声区間が十分な長さ (平均 100Hz なら 22 フレーム、200Hz なら 11 フレーム) ないものを削除 - MergeF0 ... 有声区間をマージする - MakeSortedOrder ... 有声区間たちを開始時刻の昇順にソート - MergeF0Sub ... 区間が重なる場合に、重なった部分のスコアの和が大きい方を選ぶ - (2) SearchScore - FixStep4 ... 短い無声区間を線形補間で埋める - GetBoundaryList - SmoothF0Contour ... F0 軌跡に LPF をかけて滑らかにする - GetBoundaryList - GetMultiChannelF0 ... 2 回目 - (number_of_boundaries) FilteringF0 • 前後どちらのフレームにも差が 5% 以内の F0 候補が無い ような F0 候補を削除する。
© DeNA Co., Ltd. 13 12 RemoveUnreliableCandidates - 結果の例 F0
候補とその信頼度
© DeNA Co., Ltd. 14 13 SearchF0Base - Harvest -
HarvestGeneralBody - GetWaveformAndSpectrum ... 直流成分の除去、後の畳み込みのための FFT - GetWaveformAndSpectrumSub - HarvestGeneralBodySub - GetRawF0Candidates - (number_of_bands) GetF0CandidateFromRawEvent - GetFilteredSignal ... FFT でその帯域の BPF を畳み込む - (2) fft_execute - GetFourZeroCrossingIntervals ... ゼロ交叉/ピークの点を列挙、間隔から f0 を計算 - GetF0CandidateContour - (4) interp1 ... f0 を時間方向に補間 - GetF0CandidateContourSub ... 4 つの平均を計算、ばらけていたら 0 - DetectOfficialF0Candidates - (f0_length) DetectOfficialF0CandidatesSub1 ... 台を検出 - (f0_length) DetectOfficialF0CandidatesSub2 ... 各台の平均 f0 を計算、細い台は無視 - OverlapF0Candidates ... 前後 3 フレームに f0 候補をコピー - RefineF0Candidates ... f0 候補を瞬時周波数で修正 - (f0_length * num_candidates) GetRefinedF0 ... 窓長の計算、GetMeanF0 - GetMeanF0 - GetBaseIndex ... 窓をかける場所を求める - GetMainWindow ... 地味に重い - GetDiffWindow ... MainWindow の微分した窓を求める - GetSpectra ... 2 つの窓で FFT する、ここが重い - (2) fft_execute - FixF0 ... 瞬時周波数の計算 - RemoveUnreliableCandidates ... 前後どちらのフレームにも差が 5% 以内の f0 候補が無いような f0 候補を削除 - ((f0_length - 2) * number_of_candidates) RemoveUnreliableCandidatesSub ... 前後 1 フレームに対して SelectBestF0 - (2) SelectBestF0 ... 自身に最も近い f0 を得る - FixF0Contour - SearchF0Base ... 各フレームで最もスコアの高い f0 候補を抽出する - FixStep1 ... 前フレームの f0 と前2フレームから線形で予測した f0 の両方から 0.8% 以上の差がある場合は f0 を 0 にする - FixStep2 ... 5 フレーム以下しか連続しない有声区間を削除 - GetBoundaryList ... 有声部の閉区間のリストを作る - FixStep3 ... - GetBoundaryList - GetMultiChannelF0 ... 有声区間ごとに分けて別の配列にする - Extend ... 各有声区間を前後に伸ばす - (number_of_sections * 2) ExtendF0 - (distance + 1) SelectBestF0 ... 18% 以内の差なら採択する - ExtendSub ... 有声区間が十分な長さ (平均 100Hz なら 22 フレーム、200Hz なら 11 フレーム) ないものを削除 - MergeF0 ... 有声区間をマージする - MakeSortedOrder ... 有声区間たちを開始時刻の昇順にソート - MergeF0Sub ... 区間が重なる場合に、重なった部分のスコアの和が大きい方を選ぶ - (2) SearchScore - FixStep4 ... 短い無声区間を線形補間で埋める - GetBoundaryList - SmoothF0Contour ... F0 軌跡に LPF をかけて滑らかにする - GetBoundaryList - GetMultiChannelF0 ... 2 回目 - (number_of_boundaries) FilteringF0 • 各フレームで最もスコアの高い F0 候補を抽出する。 • 注: F0 候補は後 (FixStep3) でまた使うことになる
© DeNA Co., Ltd. 15 14 SearchF0Base - 結果の例 各フレームで最も信頼度の高いF0
候補
© DeNA Co., Ltd. 16 15 FixStep1 - Harvest -
HarvestGeneralBody - GetWaveformAndSpectrum ... 直流成分の除去、後の畳み込みのための FFT - GetWaveformAndSpectrumSub - HarvestGeneralBodySub - GetRawF0Candidates - (number_of_bands) GetF0CandidateFromRawEvent - GetFilteredSignal ... FFT でその帯域の BPF を畳み込む - (2) fft_execute - GetFourZeroCrossingIntervals ... ゼロ交叉/ピークの点を列挙、間隔から f0 を計算 - GetF0CandidateContour - (4) interp1 ... f0 を時間方向に補間 - GetF0CandidateContourSub ... 4 つの平均を計算、ばらけていたら 0 - DetectOfficialF0Candidates - (f0_length) DetectOfficialF0CandidatesSub1 ... 台を検出 - (f0_length) DetectOfficialF0CandidatesSub2 ... 各台の平均 f0 を計算、細い台は無視 - OverlapF0Candidates ... 前後 3 フレームに f0 候補をコピー - RefineF0Candidates ... f0 候補を瞬時周波数で修正 - (f0_length * num_candidates) GetRefinedF0 ... 窓長の計算、GetMeanF0 - GetMeanF0 - GetBaseIndex ... 窓をかける場所を求める - GetMainWindow ... 地味に重い - GetDiffWindow ... MainWindow の微分した窓を求める - GetSpectra ... 2 つの窓で FFT する、ここが重い - (2) fft_execute - FixF0 ... 瞬時周波数の計算 - RemoveUnreliableCandidates ... 前後どちらのフレームにも差が 5% 以内の f0 候補が無いような f0 候補を削除 - ((f0_length - 2) * number_of_candidates) RemoveUnreliableCandidatesSub ... 前後 1 フレームに対して SelectBestF0 - (2) SelectBestF0 ... 自身に最も近い f0 を得る - FixF0Contour - SearchF0Base ... 各フレームで最もスコアの高い f0 候補を抽出する - FixStep1 ... 前フレームの f0 と前2フレームから線形で予測した f0 の両方から 0.8% 以上の差がある場合は f0 を 0 にする - FixStep2 ... 5 フレーム以下しか連続しない有声区間を削除 - GetBoundaryList ... 有声部の閉区間のリストを作る - FixStep3 ... - GetBoundaryList - GetMultiChannelF0 ... 有声区間ごとに分けて別の配列にする - Extend ... 各有声区間を前後に伸ばす - (number_of_sections * 2) ExtendF0 - (distance + 1) SelectBestF0 ... 18% 以内の差なら採択する - ExtendSub ... 有声区間が十分な長さ (平均 100Hz なら 22 フレーム、200Hz なら 11 フレーム) ないものを削除 - MergeF0 ... 有声区間をマージする - MakeSortedOrder ... 有声区間たちを開始時刻の昇順にソート - MergeF0Sub ... 区間が重なる場合に、重なった部分のスコアの和が大きい方を選ぶ - (2) SearchScore - FixStep4 ... 短い無声区間を線形補間で埋める - GetBoundaryList - SmoothF0Contour ... F0 軌跡に LPF をかけて滑らかにする - GetBoundaryList - GetMultiChannelF0 ... 2 回目 - (number_of_boundaries) FilteringF0 • 前フレームの F0 と前 2 フレームから線形予測した F0 の 両方から 0.8% 以上の差がある場合は F0 を 0 にする。
© DeNA Co., Ltd. 17 16 FixStep1 - 結果の例 F0
軌跡
© DeNA Co., Ltd. 18 17 FixStep2 - Harvest -
HarvestGeneralBody - GetWaveformAndSpectrum ... 直流成分の除去、後の畳み込みのための FFT - GetWaveformAndSpectrumSub - HarvestGeneralBodySub - GetRawF0Candidates - (number_of_bands) GetF0CandidateFromRawEvent - GetFilteredSignal ... FFT でその帯域の BPF を畳み込む - (2) fft_execute - GetFourZeroCrossingIntervals ... ゼロ交叉/ピークの点を列挙、間隔から f0 を計算 - GetF0CandidateContour - (4) interp1 ... f0 を時間方向に補間 - GetF0CandidateContourSub ... 4 つの平均を計算、ばらけていたら 0 - DetectOfficialF0Candidates - (f0_length) DetectOfficialF0CandidatesSub1 ... 台を検出 - (f0_length) DetectOfficialF0CandidatesSub2 ... 各台の平均 f0 を計算、細い台は無視 - OverlapF0Candidates ... 前後 3 フレームに f0 候補をコピー - RefineF0Candidates ... f0 候補を瞬時周波数で修正 - (f0_length * num_candidates) GetRefinedF0 ... 窓長の計算、GetMeanF0 - GetMeanF0 - GetBaseIndex ... 窓をかける場所を求める - GetMainWindow ... 地味に重い - GetDiffWindow ... MainWindow の微分した窓を求める - GetSpectra ... 2 つの窓で FFT する、ここが重い - (2) fft_execute - FixF0 ... 瞬時周波数の計算 - RemoveUnreliableCandidates ... 前後どちらのフレームにも差が 5% 以内の f0 候補が無いような f0 候補を削除 - ((f0_length - 2) * number_of_candidates) RemoveUnreliableCandidatesSub ... 前後 1 フレームに対して SelectBestF0 - (2) SelectBestF0 ... 自身に最も近い f0 を得る - FixF0Contour - SearchF0Base ... 各フレームで最もスコアの高い f0 候補を抽出する - FixStep1 ... 前フレームの f0 と前2フレームから線形で予測した f0 の両方から 0.8% 以上の差がある場合は f0 を 0 にする - FixStep2 ... 5 フレーム以下しか連続しない有声区間を削除する - GetBoundaryList ... 有声部の閉区間のリストを作る - FixStep3 ... - GetBoundaryList - GetMultiChannelF0 ... 有声区間ごとに分けて別の配列にする - Extend ... 各有声区間を前後に伸ばす - (number_of_sections * 2) ExtendF0 - (distance + 1) SelectBestF0 ... 18% 以内の差なら採択する - ExtendSub ... 有声区間が十分な長さ (平均 100Hz なら 22 フレーム、200Hz なら 11 フレーム) ないものを削除 - MergeF0 ... 有声区間をマージする - MakeSortedOrder ... 有声区間たちを開始時刻の昇順にソート - MergeF0Sub ... 区間が重なる場合に、重なった部分のスコアの和が大きい方を選ぶ - (2) SearchScore - FixStep4 ... 短い無声区間を線形補間で埋める - GetBoundaryList - SmoothF0Contour ... F0 軌跡に LPF をかけて滑らかにする - GetBoundaryList - GetMultiChannelF0 ... 2 回目 - (number_of_boundaries) FilteringF0 • 5 フレーム以下しか連続しない有声区間を削除する。
© DeNA Co., Ltd. 19 18 FixStep2 - 結果の例 F0
軌跡
© DeNA Co., Ltd. 20 19 FixStep3 - GetMultiChannelF0 -
Harvest - HarvestGeneralBody - GetWaveformAndSpectrum ... 直流成分の除去、後の畳み込みのための FFT - GetWaveformAndSpectrumSub - HarvestGeneralBodySub - GetRawF0Candidates - (number_of_bands) GetF0CandidateFromRawEvent - GetFilteredSignal ... FFT でその帯域の BPF を畳み込む - (2) fft_execute - GetFourZeroCrossingIntervals ... ゼロ交叉/ピークの点を列挙、間隔から f0 を計算 - GetF0CandidateContour - (4) interp1 ... f0 を時間方向に補間 - GetF0CandidateContourSub ... 4 つの平均を計算、ばらけていたら 0 - DetectOfficialF0Candidates - (f0_length) DetectOfficialF0CandidatesSub1 ... 台を検出 - (f0_length) DetectOfficialF0CandidatesSub2 ... 各台の平均 f0 を計算、細い台は無視 - OverlapF0Candidates ... 前後 3 フレームに f0 候補をコピー - RefineF0Candidates ... f0 候補を瞬時周波数で修正 - (f0_length * num_candidates) GetRefinedF0 ... 窓長の計算、GetMeanF0 - GetMeanF0 - GetBaseIndex ... 窓をかける場所を求める - GetMainWindow ... 地味に重い - GetDiffWindow ... MainWindow の微分した窓を求める - GetSpectra ... 2 つの窓で FFT する、ここが重い - (2) fft_execute - FixF0 ... 瞬時周波数の計算 - RemoveUnreliableCandidates ... 前後どちらのフレームにも差が 5% 以内の f0 候補が無いような f0 候補を削除 - ((f0_length - 2) * number_of_candidates) RemoveUnreliableCandidatesSub ... 前後 1 フレームに対して SelectBestF0 - (2) SelectBestF0 ... 自身に最も近い f0 を得る - FixF0Contour - SearchF0Base ... 各フレームで最もスコアの高い f0 候補を抽出する - FixStep1 ... 前フレームの f0 と前2フレームから線形で予測した f0 の両方から 0.8% 以上の差がある場合は f0 を 0 にする - FixStep2 ... 5 フレーム以下しか連続しない有声区間を削除 - GetBoundaryList ... 有声部の閉区間のリストを作る - FixStep3 ... - GetBoundaryList - GetMultiChannelF0 ... 有声区間ごとに分けて別の配列にする - Extend ... 各有声区間を前後に伸ばす - (number_of_sections * 2) ExtendF0 - (distance + 1) SelectBestF0 ... 18% 以内の差なら採択する - ExtendSub ... 有声区間が十分な長さ (平均 100Hz なら 22 フレーム、200Hz なら 11 フレーム) ないものを削除 - MergeF0 ... 有声区間をマージする - MakeSortedOrder ... 有声区間たちを開始時刻の昇順にソート - MergeF0Sub ... 区間が重なる場合に、重なった部分のスコアの和が大きい方を選ぶ - (2) SearchScore - FixStep4 ... 短い無声区間を線形補間で埋める - GetBoundaryList - SmoothF0Contour ... F0 軌跡に LPF をかけて滑らかにする - GetBoundaryList - GetMultiChannelF0 ... 2 回目 - (number_of_boundaries) FilteringF0 • 有声区間ごとに分けて別の配列にする。 • 有声区間の個数が入力音声の長さに比例すると考えると、入力音声の長さの 2 乗に比例する大きさ のメモリを確保していることになる
© DeNA Co., Ltd. 21 20 FixStep3 - GetMultiChannelF0 -
結果の例 有声区間ごとに分けられた F0 軌跡
© DeNA Co., Ltd. 22 21 FixStep3 - Extend -
Harvest - HarvestGeneralBody - GetWaveformAndSpectrum ... 直流成分の除去、後の畳み込みのための FFT - GetWaveformAndSpectrumSub - HarvestGeneralBodySub - GetRawF0Candidates - (number_of_bands) GetF0CandidateFromRawEvent - GetFilteredSignal ... FFT でその帯域の BPF を畳み込む - (2) fft_execute - GetFourZeroCrossingIntervals ... ゼロ交叉/ピークの点を列挙、間隔から f0 を計算 - GetF0CandidateContour - (4) interp1 ... f0 を時間方向に補間 - GetF0CandidateContourSub ... 4 つの平均を計算、ばらけていたら 0 - DetectOfficialF0Candidates - (f0_length) DetectOfficialF0CandidatesSub1 ... 台を検出 - (f0_length) DetectOfficialF0CandidatesSub2 ... 各台の平均 f0 を計算、細い台は無視 - OverlapF0Candidates ... 前後 3 フレームに f0 候補をコピー - RefineF0Candidates ... f0 候補を瞬時周波数で修正 - (f0_length * num_candidates) GetRefinedF0 ... 窓長の計算、GetMeanF0 - GetMeanF0 - GetBaseIndex ... 窓をかける場所を求める - GetMainWindow ... 地味に重い - GetDiffWindow ... MainWindow の微分した窓を求める - GetSpectra ... 2 つの窓で FFT する、ここが重い - (2) fft_execute - FixF0 ... 瞬時周波数の計算 - RemoveUnreliableCandidates ... 前後どちらのフレームにも差が 5% 以内の f0 候補が無いような f0 候補を削除 - ((f0_length - 2) * number_of_candidates) RemoveUnreliableCandidatesSub ... 前後 1 フレームに対して SelectBestF0 - (2) SelectBestF0 ... 自身に最も近い f0 を得る - FixF0Contour - SearchF0Base ... 各フレームで最もスコアの高い f0 候補を抽出する - FixStep1 ... 前フレームの f0 と前2フレームから線形で予測した f0 の両方から 0.8% 以上の差がある場合は f0 を 0 にする - FixStep2 ... 5 フレーム以下しか連続しない有声区間を削除 - GetBoundaryList ... 有声部の閉区間のリストを作る - FixStep3 ... - GetBoundaryList - GetMultiChannelF0 ... 有声区間ごとに分けて別の配列にする - Extend ... 各有声区間を前後に伸ばす - (number_of_sections * 2) ExtendF0 - (distance + 1) SelectBestF0 ... 18% 以内の差なら採択する - ExtendSub ... 有声区間が十分な長さ (平均 100Hz なら 22 フレーム、200Hz なら 11 フレーム) ないものを削除 - MergeF0 ... 有声区間をマージする - MakeSortedOrder ... 有声区間たちを開始時刻の昇順にソート - MergeF0Sub ... 区間が重なる場合に、重なった部分のスコアの和が大きい方を選ぶ - (2) SearchScore - FixStep4 ... 短い無声区間を線形補間で埋める - GetBoundaryList - SmoothF0Contour ... F0 軌跡に LPF をかけて滑らかにする - GetBoundaryList - GetMultiChannelF0 ... 2 回目 - (number_of_boundaries) FilteringF0 • 各有声区間を前後に伸ばす。 ◦ F0 が近いものを辿っている、多分 ◦ 自身との差が 18% より大きい F0 候補は無視して いる、多分
© DeNA Co., Ltd. 23 22 FixStep3 - Extend -
結果の例 伸ばされた F0 軌跡たち
© DeNA Co., Ltd. 24 23 FixStep3 - MergeF0 -
Harvest - HarvestGeneralBody - GetWaveformAndSpectrum ... 直流成分の除去、後の畳み込みのための FFT - GetWaveformAndSpectrumSub - HarvestGeneralBodySub - GetRawF0Candidates - (number_of_bands) GetF0CandidateFromRawEvent - GetFilteredSignal ... FFT でその帯域の BPF を畳み込む - (2) fft_execute - GetFourZeroCrossingIntervals ... ゼロ交叉/ピークの点を列挙、間隔から f0 を計算 - GetF0CandidateContour - (4) interp1 ... f0 を時間方向に補間 - GetF0CandidateContourSub ... 4 つの平均を計算、ばらけていたら 0 - DetectOfficialF0Candidates - (f0_length) DetectOfficialF0CandidatesSub1 ... 台を検出 - (f0_length) DetectOfficialF0CandidatesSub2 ... 各台の平均 f0 を計算、細い台は無視 - OverlapF0Candidates ... 前後 3 フレームに f0 候補をコピー - RefineF0Candidates ... f0 候補を瞬時周波数で修正 - (f0_length * num_candidates) GetRefinedF0 ... 窓長の計算、GetMeanF0 - GetMeanF0 - GetBaseIndex ... 窓をかける場所を求める - GetMainWindow ... 地味に重い - GetDiffWindow ... MainWindow の微分した窓を求める - GetSpectra ... 2 つの窓で FFT する、ここが重い - (2) fft_execute - FixF0 ... 瞬時周波数の計算 - RemoveUnreliableCandidates ... 前後どちらのフレームにも差が 5% 以内の f0 候補が無いような f0 候補を削除 - ((f0_length - 2) * number_of_candidates) RemoveUnreliableCandidatesSub ... 前後 1 フレームに対して SelectBestF0 - (2) SelectBestF0 ... 自身に最も近い f0 を得る - FixF0Contour - SearchF0Base ... 各フレームで最もスコアの高い f0 候補を抽出する - FixStep1 ... 前フレームの f0 と前2フレームから線形で予測した f0 の両方から 0.8% 以上の差がある場合は f0 を 0 にする - FixStep2 ... 5 フレーム以下しか連続しない有声区間を削除 - GetBoundaryList ... 有声部の閉区間のリストを作る - FixStep3 ... - GetBoundaryList - GetMultiChannelF0 ... 有声区間ごとに分けて別の配列にする - Extend ... 各有声区間を前後に伸ばす - (number_of_sections * 2) ExtendF0 - (distance + 1) SelectBestF0 ... 18% 以内の差なら採択する - ExtendSub ... 有声区間が十分な長さ (平均 100Hz なら 22 フレーム、200Hz なら 11 フレーム) ないものを削除 - MergeF0 ... 有声区間をマージする - MakeSortedOrder ... 有声区間たちを開始時刻の昇順にソート - MergeF0Sub ... 区間が重なる場合に、重なった部分のスコアの和が大きい方を選ぶ - (2) SearchScore - FixStep4 ... 短い無声区間を線形補間で埋める - GetBoundaryList - SmoothF0Contour ... F0 軌跡に LPF をかけて滑らかにする - GetBoundaryList - GetMultiChannelF0 ... 2 回目 - (number_of_boundaries) FilteringF0 • 短い有声区間は削除し、各有声区間をマージする。 ◦ 削除の基準 … 波長の長さの 2.2 倍 ▪ 区間の平均が 100Hz なら 22 フレーム未 満、200Hz なら 11 フレーム未満で削除 • 区間が重なる場合には、重なった部分の信頼度の和が大 きい方を選ぶ。
© DeNA Co., Ltd. 25 24 FixStep3 - MergeF0 -
結果の例 マージされた F0 軌跡
© DeNA Co., Ltd. 26 25 FixStep4 - Harvest -
HarvestGeneralBody - GetWaveformAndSpectrum ... 直流成分の除去、後の畳み込みのための FFT - GetWaveformAndSpectrumSub - HarvestGeneralBodySub - GetRawF0Candidates - (number_of_bands) GetF0CandidateFromRawEvent - GetFilteredSignal ... FFT でその帯域の BPF を畳み込む - (2) fft_execute - GetFourZeroCrossingIntervals ... ゼロ交叉/ピークの点を列挙、間隔から f0 を計算 - GetF0CandidateContour - (4) interp1 ... f0 を時間方向に補間 - GetF0CandidateContourSub ... 4 つの平均を計算、ばらけていたら 0 - DetectOfficialF0Candidates - (f0_length) DetectOfficialF0CandidatesSub1 ... 台を検出 - (f0_length) DetectOfficialF0CandidatesSub2 ... 各台の平均 f0 を計算、細い台は無視 - OverlapF0Candidates ... 前後 3 フレームに f0 候補をコピー - RefineF0Candidates ... f0 候補を瞬時周波数で修正 - (f0_length * num_candidates) GetRefinedF0 ... 窓長の計算、GetMeanF0 - GetMeanF0 - GetBaseIndex ... 窓をかける場所を求める - GetMainWindow ... 地味に重い - GetDiffWindow ... MainWindow の微分した窓を求める - GetSpectra ... 2 つの窓で FFT する、ここが重い - (2) fft_execute - FixF0 ... 瞬時周波数の計算 - RemoveUnreliableCandidates ... 前後どちらのフレームにも差が 5% 以内の f0 候補が無いような f0 候補を削除 - ((f0_length - 2) * number_of_candidates) RemoveUnreliableCandidatesSub ... 前後 1 フレームに対して SelectBestF0 - (2) SelectBestF0 ... 自身に最も近い f0 を得る - FixF0Contour - SearchF0Base ... 各フレームで最もスコアの高い f0 候補を抽出する - FixStep1 ... 前フレームの f0 と前2フレームから線形で予測した f0 の両方から 0.8% 以上の差がある場合は f0 を 0 にする - FixStep2 ... 5 フレーム以下しか連続しない有声区間を削除 - GetBoundaryList ... 有声部の閉区間のリストを作る - FixStep3 ... - GetBoundaryList - GetMultiChannelF0 ... 有声区間ごとに分けて別の配列にする - Extend ... 各有声区間を前後に伸ばす - (number_of_sections * 2) ExtendF0 - (distance + 1) SelectBestF0 ... 18% 以内の差なら採択する - ExtendSub ... 有声区間が十分な長さ (平均 100Hz なら 22 フレーム、200Hz なら 11 フレーム) ないものを削除 - MergeF0 ... 有声区間をマージする - MakeSortedOrder ... 有声区間たちを開始時刻の昇順にソート - MergeF0Sub ... 区間が重なる場合に、重なった部分のスコアの和が大きい方を選ぶ - (2) SearchScore - FixStep4 ... 短い無声区間を線形補間で埋める - GetBoundaryList - SmoothF0Contour ... F0 軌跡に LPF をかけて滑らかにする - GetBoundaryList - GetMultiChannelF0 ... 2 回目 - (number_of_boundaries) FilteringF0 • 短い無声区間を線形補間で埋める。
© DeNA Co., Ltd. 27 26 FixStep4 - 結果の例 F0
軌跡
© DeNA Co., Ltd. 28 27 SmoothF0Contour - Harvest -
HarvestGeneralBody - GetWaveformAndSpectrum ... 直流成分の除去、後の畳み込みのための FFT - GetWaveformAndSpectrumSub - HarvestGeneralBodySub - GetRawF0Candidates - (number_of_bands) GetF0CandidateFromRawEvent - GetFilteredSignal ... FFT でその帯域の BPF を畳み込む - (2) fft_execute - GetFourZeroCrossingIntervals ... ゼロ交叉/ピークの点を列挙、間隔から f0 を計算 - GetF0CandidateContour - (4) interp1 ... f0 を時間方向に補間 - GetF0CandidateContourSub ... 4 つの平均を計算、ばらけていたら 0 - DetectOfficialF0Candidates - (f0_length) DetectOfficialF0CandidatesSub1 ... 台を検出 - (f0_length) DetectOfficialF0CandidatesSub2 ... 各台の平均 f0 を計算、細い台は無視 - OverlapF0Candidates ... 前後 3 フレームに f0 候補をコピー - RefineF0Candidates ... f0 候補を瞬時周波数で修正 - (f0_length * num_candidates) GetRefinedF0 ... 窓長の計算、GetMeanF0 - GetMeanF0 - GetBaseIndex ... 窓をかける場所を求める - GetMainWindow ... 地味に重い - GetDiffWindow ... MainWindow の微分した窓を求める - GetSpectra ... 2 つの窓で FFT する、ここが重い - (2) fft_execute - FixF0 ... 瞬時周波数の計算 - RemoveUnreliableCandidates ... 前後どちらのフレームにも差が 5% 以内の f0 候補が無いような f0 候補を削除 - ((f0_length - 2) * number_of_candidates) RemoveUnreliableCandidatesSub ... 前後 1 フレームに対して SelectBestF0 - (2) SelectBestF0 ... 自身に最も近い f0 を得る - FixF0Contour - SearchF0Base ... 各フレームで最もスコアの高い f0 候補を抽出する - FixStep1 ... 前フレームの f0 と前2フレームから線形で予測した f0 の両方から 0.8% 以上の差がある場合は f0 を 0 にする - FixStep2 ... 5 フレーム以下しか連続しない有声区間を削除 - GetBoundaryList ... 有声部の閉区間のリストを作る - FixStep3 ... - GetBoundaryList - GetMultiChannelF0 ... 有声区間ごとに分けて別の配列にする - Extend ... 各有声区間を前後に伸ばす - (number_of_sections * 2) ExtendF0 - (distance + 1) SelectBestF0 ... 18% 以内の差なら採択する - ExtendSub ... 有声区間が十分な長さ (平均 100Hz なら 22 フレーム、200Hz なら 11 フレーム) ないものを削除 - MergeF0 ... 有声区間をマージする - MakeSortedOrder ... 有声区間たちを開始時刻の昇順にソート - MergeF0Sub ... 区間が重なる場合に、重なった部分のスコアの和が大きい方を選ぶ - (2) SearchScore - FixStep4 ... 短い無声区間を線形補間で埋める - GetBoundaryList - SmoothF0Contour ... F0 軌跡に LPF をかけて滑らかにする - GetBoundaryList - GetMultiChannelF0 ... 2 回目 - (number_of_boundaries) FilteringF0 • F0 軌跡に LPF をかけて滑らかにする。
© DeNA Co., Ltd. 29 28 最終的な結果の例 アルゴリズム全体を通して得られた F0 軌跡
© DeNA Co., Ltd. 30 29 スペクトログラムと重ねてみる スペクトログラムと F0 軌跡
© DeNA Co., Ltd. 31 こうして私たちの元へ届けられる——
© DeNA Co., Ltd. 32