Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
F0推定アルゴリズムHarvestは中で何をしているのか
Search
nagiss
September 25, 2023
Technology
1.9k
3
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
F0推定アルゴリズムHarvestは中で何をしているのか
DeNAの2023/5/24の音声トークの発表資料を焼き直したものです。
nagiss
September 25, 2023
More Decks by nagiss
See All by nagiss
サンタコンペの話をさくっと
nagiss
0
82
Fujitsuの量子化技術を完全理解する
nagiss
0
890
F0推定の手法を色々試してみる
nagiss
1
1.5k
音信号の電子透かし
nagiss
0
1.5k
ヒューリスティックコンテストで機械学習しよう
nagiss
10
6.9k
XNNPACKを直接使ってみた
nagiss
0
980
SantaとAHCと遺伝的アルゴリズム
nagiss
8
4.4k
Kaggleシミュレーションコンペの動向
nagiss
2
1.8k
Other Decks in Technology
See All in Technology
顧客価値を追いかけたら、プライシングにたどり着いた
sansantech
PRO
2
1k
導入から定着へ ~コーディングエージェントを日常業務に組み込む実践知~
yukisakai1225
0
240
シンプルな設定ファイルで実現する AWS IAM Identity Center の ユーザー管理Terraformフレームワークを公開しました / Simplifying AWS IAM Identity Center User Management: An Open-Source Terraform Framework
yamaguchitk333
1
320
バフェットコード開発チームの心得(v1.1)
shoe116
0
110
AI秘書と毎日働くのはもう当たり前。開発以外の業務に足りない機能をどう埋める?
minorun365
PRO
4
1.8k
ドメインエキスパートは いかにして AI を使って プロダクト開発をするか
tatsuyashiraishi
1
200
撮るだけでは終わらない。ソニーが挑むB2Bカメラソリューション開発
sony
0
110
演劇と私とスクラム
chinmo
0
160
書き手が人でもAIでも正しくなる道、SREを埋め込んだDeveloper Platform / tech drivers day8
chmikata
4
770
Vue.jsのGitHubから学ぶ意思決定
yut0naga1_fa
1
290
DevelopersIO 2026 Tokyo 現時点の衛星通信サービスの現状を整理してみる
maroon1st
0
310
Obsidian Vault Architectures
x5gtrn
PRO
0
170
Featured
See All Featured
Agile Leadership in an Agile Organization
kimpetersen
PRO
0
290
Fight the Zombie Pattern Library - RWD Summit 2016
marcelosomers
234
18k
Jess Joyce - The Pitfalls of Following Frameworks
techseoconnect
PRO
1
450
New Earth Scene 8
popppiees
4
2.7k
A Tale of Four Properties
chriscoyier
163
24k
I Don’t Have Time: Getting Over the Fear to Launch Your Podcast
jcasabona
35
2.9k
SEO in 2025: How to Prepare for the Future of Search
ipullrank
3
3.9k
GraphQLとの向き合い方2022年版
quramy
50
15k
Visualizing Your Data: Incorporating Mongo into Loggly Infrastructure
mongodb
50
10k
Become a Pro
speakerdeck
PRO
31
6.3k
Optimizing for Happiness
mojombo
378
71k
Public Speaking Without Barfing On Your Shoes - THAT 2023
reverentgeek
1
620
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