File size: 3,877 Bytes
5cda731 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 |
from logging import getLogger
from typing import Any, Dict, List, Optional
import numpy as np
from pyopenjtalk import tts
from scipy.signal import resample
from ...model import AccentPhrase, AudioQuery
from ...synthesis_engine import SynthesisEngineBase
from ...synthesis_engine.synthesis_engine import to_flatten_moras
class MockSynthesisEngine(SynthesisEngineBase):
"""
SynthesisEngine [Mock]
"""
def __init__(
self,
speakers: str,
supported_devices: Optional[str] = None,
):
"""
__init__ [Mock]
"""
super().__init__()
self._speakers = speakers
self._supported_devices = supported_devices
self.default_sampling_rate = 24000
@property
def speakers(self) -> str:
return self._speakers
@property
def supported_devices(self) -> Optional[str]:
return self._supported_devices
def replace_phoneme_length(
self, accent_phrases: List[AccentPhrase], speaker_id: int
) -> List[AccentPhrase]:
"""
replace_phoneme_length 入力accent_phrasesを変更せずにそのまま返します [Mock]
Parameters
----------
accent_phrases : List[AccentPhrase]
フレーズ句のリスト
speaker_id : int
話者
Returns
-------
List[AccentPhrase]
フレーズ句のリスト(変更なし)
"""
return accent_phrases
def replace_mora_pitch(
self, accent_phrases: List[AccentPhrase], speaker_id: int
) -> List[AccentPhrase]:
"""
replace_mora_pitch 入力accent_phrasesを変更せずにそのまま返します [Mock]
Parameters
----------
accent_phrases : List[AccentPhrase]
フレーズ句のリスト
speaker_id : int
話者
Returns
-------
List[AccentPhrase]
フレーズ句のリスト(変更なし)
"""
return accent_phrases
def _synthesis_impl(self, query: AudioQuery, speaker_id: int) -> np.ndarray:
"""
synthesis voicevox coreを使わずに、音声合成する [Mock]
Parameters
----------
query : AudioQuery
/audio_query APIで得たjson
speaker_id : int
話者
Returns
-------
wave [npt.NDArray[np.int16]]
音声波形データをNumPy配列で返します
"""
# recall text in katakana
flatten_moras = to_flatten_moras(query.accent_phrases)
kana_text = "".join([mora.text for mora in flatten_moras])
wave = self.forward(kana_text)
# volume
wave *= query.volumeScale
return wave.astype("int16")
def forward(self, text: str, **kwargs: Dict[str, Any]) -> np.ndarray:
"""
forward tts via pyopenjtalk.tts()
参照→SynthesisEngine のdocstring [Mock]
Parameters
----------
text : str
入力文字列(例:読み上げたい文章をカタカナにした文字列、等)
Returns
-------
wave [npt.NDArray[np.int16]]
音声波形データをNumPy配列で返します
Note
-------
ここで行う音声合成では、調声(ピッチ等)を反映しない
# pyopenjtalk.tts()の出力仕様
dtype=np.float64, 16 bit, mono 48000 Hz
# resampleの説明
非モック実装(decode_forward)と合わせるために、出力を24kHzに変換した。
"""
logger = getLogger("uvicorn") # FastAPI / Uvicorn 内からの利用のため
logger.info("[Mock] input text: %s" % text)
wave, sr = tts(text)
wave = resample(wave, 24000 * len(wave) // 48000)
return wave
|