Skip to content
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

Refactor: _synthesis_impl 内前処理の整理 #783

Closed
3 tasks done
tarepan opened this issue Nov 26, 2023 · 1 comment · Fixed by #790
Closed
3 tasks done

Refactor: _synthesis_impl 内前処理の整理 #783

tarepan opened this issue Nov 26, 2023 · 1 comment · Fixed by #790

Comments

@tarepan
Copy link
Contributor

tarepan commented Nov 26, 2023

内容

要望: _synthesis_impl 内の前処理を関数化、テスト導入、リファクタリング

現在の _synthesis_impl()pre_processcore.decode_forward の間に約60行の(第2の)前処理が存在する。
この部分はフレーム化・global特徴量の適用・onehot化など複数の重要機能が混在しており、可読性に改善の余地がある。
よってこの領域のリファクタリングを提案します。

Pros 良くなる点

  • テストによる保守性向上
  • リファクタリングによる可読性向上

Cons 悪くなる点

  • 無し

実現方法

対象領域は(幸いにも)ステートレスである。

# OjtPhonemeのリストからOjtPhonemeのPhoneme ID(OpenJTalkにおける音素のID)のリストを作る
phoneme_list_s = numpy.array(
[p.phoneme_id for p in phoneme_data_list], dtype=numpy.int64
)
# length
# 音素の長さをリストに展開・結合する。ここには前後の無音時間も含まれる
phoneme_length_list = (
[query.prePhonemeLength]
+ [
length
for mora in flatten_moras
for length in (
[mora.consonant_length] if mora.consonant is not None else []
)
+ [mora.vowel_length]
]
+ [query.postPhonemeLength]
)
# floatにキャスト
phoneme_length = numpy.array(phoneme_length_list, dtype=numpy.float32)
# lengthにSpeed Scale(話速)を適用する
phoneme_length /= query.speedScale
# pitch
# モーラの音高(ピッチ)を展開・結合し、floatにキャストする
f0_list = [0] + [mora.pitch for mora in flatten_moras] + [0]
f0 = numpy.array(f0_list, dtype=numpy.float32)
# 音高(ピッチ)の調節を適用する(2のPitch Scale乗を掛ける)
f0 *= 2**query.pitchScale
# 有声音素(音高(ピッチ)が0より大きいもの)か否かを抽出する
voiced = f0 > 0
# 有声音素の音高(ピッチ)の平均値を求める
mean_f0 = f0[voiced].mean()
# 平均値がNaNではないとき、抑揚を適用する
# 抑揚は音高と音高の平均値の差に抑揚を掛けたもの((f0 - mean_f0) * Intonation Scale)に抑揚の平均値(mean_f0)を足したもの
if not numpy.isnan(mean_f0):
f0[voiced] = (f0[voiced] - mean_f0) * query.intonationScale + mean_f0
# OjtPhonemeの形に分解された音素リストから、vowel(母音)の位置を抜き出し、numpyのarrayにする
_, _, vowel_indexes_data = split_mora(phoneme_data_list)
vowel_indexes = numpy.array(vowel_indexes_data)
# forward decode
# 音素の長さにrateを掛け、intにキャストする
rate = 24000 / 256
phoneme_bin_num = numpy.round(phoneme_length * rate).astype(numpy.int32)
# Phoneme IDを音素の長さ分繰り返す
phoneme = numpy.repeat(phoneme_list_s, phoneme_bin_num)
# f0を母音と子音の長さの合計分繰り返す
f0 = numpy.repeat(
f0,
[a.sum() for a in numpy.split(phoneme_bin_num, vowel_indexes[:-1] + 1)],
)
# phonemeの長さとOjtPhonemeのnum_phoneme(45)分の0で初期化された2次元配列を用意する
array = numpy.zeros((len(phoneme), OjtPhoneme.num_phoneme), dtype=numpy.float32)
# 初期化された2次元配列の各行をone hotにする
array[numpy.arange(len(phoneme)), phoneme] = 1
phoneme = array

よって次の複数ステップ/プルリクエストを経てリファクタリングを行える:

  • step1a: 関数(①)への切り出し
  • step1b: テストの追加
  • step2a: 関数内コード順序の整理
  • step2b: 関数内の機能別関数化・テスト追加
  • step2c: 関数 ① の廃止

VOICEVOXのバージョン

0.14.10

OSの種類/ディストリ/バージョン

  • Windows
  • macOS
  • Linux
@github-actions github-actions bot added OS 依存:linux Linux に依存した現象 OS 依存:mac macOS に依存した現象 OS 依存:win Windows に依存した現象 labels Nov 26, 2023
@Hiroshiba
Copy link
Member

提案ありがとうございます!
リファクタリング対象と流れ、自分的には良さそうに感じました!!🙏

@tarepan tarepan removed OS 依存:mac macOS に依存した現象 OS 依存:linux Linux に依存した現象 OS 依存:win Windows に依存した現象 labels Mar 17, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants