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:
tsukumi
2024-03-10 16:51:58 +00:00
parent 733a9d838d
commit be265d42ed
4 changed files with 20 additions and 16 deletions

View File

@@ -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',

View File

@@ -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

View File

@@ -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

View File

@@ -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(