Improve: switch pyworld to pyworld-prebuilt and enable it by default
Prebuilt wheels for almost every OS/architecture (except musl) are now available on PyPI, eliminating the need for a build environment. ref: https://pypi.org/project/pyworld-prebuilt/
This commit is contained in:
@@ -36,7 +36,7 @@ dependencies = [
|
|||||||
'pydantic>=2.0',
|
'pydantic>=2.0',
|
||||||
'pyopenjtalk-dict',
|
'pyopenjtalk-dict',
|
||||||
'pypinyin',
|
'pypinyin',
|
||||||
# 'pyworld',
|
'pyworld-prebuilt',
|
||||||
'safetensors',
|
'safetensors',
|
||||||
'scipy',
|
'scipy',
|
||||||
'torch>=2.1,<2.2',
|
'torch>=2.1,<2.2',
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ pyloudnorm
|
|||||||
# pyopenjtalk-prebuilt # Should be manually uninstalled
|
# pyopenjtalk-prebuilt # Should be manually uninstalled
|
||||||
pyopenjtalk-dict
|
pyopenjtalk-dict
|
||||||
pypinyin
|
pypinyin
|
||||||
# pyworld # Not supported on Windows without Cython...
|
pyworld-prebuilt
|
||||||
PyYAML
|
PyYAML
|
||||||
requests
|
requests
|
||||||
safetensors
|
safetensors
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
import pyworld
|
||||||
from numpy.typing import NDArray
|
from numpy.typing import NDArray
|
||||||
|
|
||||||
|
|
||||||
@@ -10,29 +11,34 @@ def adjust_voice(
|
|||||||
pitch_scale: float = 1.0,
|
pitch_scale: float = 1.0,
|
||||||
intonation_scale: float = 1.0,
|
intonation_scale: float = 1.0,
|
||||||
) -> tuple[int, NDArray[Any]]:
|
) -> tuple[int, NDArray[Any]]:
|
||||||
|
"""
|
||||||
|
音声のピッチとイントネーションを調整する。
|
||||||
|
変更すると若干音質が劣化するので、どちらも初期値のままならそのまま返す。
|
||||||
|
|
||||||
|
Args:
|
||||||
|
fs (int): 音声のサンプリング周波数
|
||||||
|
wave (NDArray[Any]): 音声データ
|
||||||
|
pitch_scale (float, optional): ピッチの高さ. Defaults to 1.0.
|
||||||
|
intonation_scale (float, optional): イントネーションの高さ. Defaults to 1.0.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
tuple[int, NDArray[Any]]: 調整後の音声データのサンプリング周波数と音声データ
|
||||||
|
"""
|
||||||
|
|
||||||
if pitch_scale == 1.0 and intonation_scale == 1.0:
|
if pitch_scale == 1.0 and intonation_scale == 1.0:
|
||||||
# 初期値の場合は、音質劣化を避けるためにそのまま返す
|
# 初期値の場合は、音質劣化を避けるためにそのまま返す
|
||||||
return fs, wave
|
return fs, wave
|
||||||
|
|
||||||
try:
|
|
||||||
import pyworld
|
|
||||||
except ImportError:
|
|
||||||
raise ImportError(
|
|
||||||
"pyworld is not installed. Please install it by `pip install pyworld`"
|
|
||||||
)
|
|
||||||
|
|
||||||
# pyworld で f0 を加工して合成
|
# pyworld で f0 を加工して合成
|
||||||
# pyworld よりもよいのがあるかもしれないが……
|
# pyworld よりもよいのがあるかもしれないが……
|
||||||
## pyworld は Cython で書かれているが、スタブファイルがないため型補完が全く効かない…
|
|
||||||
|
|
||||||
wave = wave.astype(np.double)
|
wave = wave.astype(np.double)
|
||||||
|
|
||||||
# 質が高そうだしとりあえずharvestにしておく
|
# 質が高そうだしとりあえずharvestにしておく
|
||||||
f0, t = pyworld.harvest(wave, fs) # type: ignore
|
f0, t = pyworld.harvest(wave, fs)
|
||||||
|
|
||||||
sp = pyworld.cheaptrick(wave, f0, t, fs) # type: ignore
|
sp = pyworld.cheaptrick(wave, f0, t, fs)
|
||||||
ap = pyworld.d4c(wave, f0, t, fs) # type: ignore
|
ap = pyworld.d4c(wave, f0, t, fs)
|
||||||
|
|
||||||
non_zero_f0 = [f for f in f0 if f != 0]
|
non_zero_f0 = [f for f in f0 if f != 0]
|
||||||
f0_mean = sum(non_zero_f0) / len(non_zero_f0)
|
f0_mean = sum(non_zero_f0) / len(non_zero_f0)
|
||||||
@@ -42,5 +48,5 @@ def adjust_voice(
|
|||||||
continue
|
continue
|
||||||
f0[i] = pitch_scale * f0_mean + intonation_scale * (f - f0_mean)
|
f0[i] = pitch_scale * f0_mean + intonation_scale * (f - f0_mean)
|
||||||
|
|
||||||
wave = pyworld.synthesize(f0, sp, ap, fs) # type: ignore
|
wave = pyworld.synthesize(f0, sp, ap, fs)
|
||||||
return fs, wave
|
return fs, wave
|
||||||
|
|||||||
@@ -294,7 +294,6 @@ def create_inference_app(model_holder: TTSModelHolder) -> gr.Blocks:
|
|||||||
value=1,
|
value=1,
|
||||||
step=0.05,
|
step=0.05,
|
||||||
label="音程(1以外では音質劣化)",
|
label="音程(1以外では音質劣化)",
|
||||||
visible=False, # pyworldが必要
|
|
||||||
)
|
)
|
||||||
intonation_scale = gr.Slider(
|
intonation_scale = gr.Slider(
|
||||||
minimum=0,
|
minimum=0,
|
||||||
@@ -302,7 +301,6 @@ def create_inference_app(model_holder: TTSModelHolder) -> gr.Blocks:
|
|||||||
value=1,
|
value=1,
|
||||||
step=0.1,
|
step=0.1,
|
||||||
label="抑揚(1以外では音質劣化)",
|
label="抑揚(1以外では音質劣化)",
|
||||||
visible=False, # pyworldが必要
|
|
||||||
)
|
)
|
||||||
|
|
||||||
line_split = gr.Checkbox(
|
line_split = gr.Checkbox(
|
||||||
|
|||||||
Reference in New Issue
Block a user