HTSEngeneをPythonでラップしてくれる。おかげで合成した音声をメモリ上で生成・再生できる。ファイル作成せずに済む。ただ、open_jtalk
のツール版における引数のうち、一部しかないのが気になった。なんとかそれらも実装できないか。まずはコードを読んでみた。
成果物
情報源
PyOpenJTalk
PyOpenJTalkはOpenJTalk, HTSEngeneのラッパである。C/C++で実装されたそれらをPythonで利用できるようにしてくれる。
import pyopenjtalk import simpleaudio as sa x, sr = pyopenjtalk.tts('読み上げる') ply = sa.play_buffer(x.astype(numpy.int16), 1, 2, sr) ply.wait_done()
コードを読む
まずは上記。PyOpenJTalkのインタフェースである。たとえば以下のようにして使うtts()
メソッドの実装が書いてある。
ttsは音声データとサンプリングレートを返す。処理内容はほぼsynthesizeだ。引数のtext
をextract_fullcontextに渡して、それをさらに渡している。
synthesizeは音声データを生成する。HTSEngineクラスのインスタンスを生成している。ここでボイスデータであるhtsvoiceファイルパスを引数に渡している。
そんな感じでコードを追っていくと、以下のような流れだった。
- tts
- 音声データを生成する
- synthesize
- HTSEngine
引数=htsvoiceファイルパス
- HTSEngine
- synthesize
- HTS-style full-context labelsを生成する
- 音声データを生成する
つまりHTSEngine, OpenJTalkクラスのインスタンスを生成するとき、引数にhtsvoiceファイルパスと辞書ファイルパスを渡せば、任意のそれらを使うことができそうだ。以下のようなコードになるか。
import pyopenjtalk from pyopenjtalk import * engine = pyopenjtalk.HTSEngine(htsvoice_path.encode('ascii')) ojt = pyopenjtalk.OpenJTalk(dn_mecab=dic_path.encode('ascii'))
sr = engine.get_sampling_frequency() engine.set_speed(speed) engine.add_half_tone(half_tone) x = engine.synthesize(pyopenjtalk.extract_fullcontext(text))
それを再生する。
import simpleaudio as sa ply = sa.play_buffer(x.astype(numpy.int16), 1, 2, sr) ply.wait_done()
これで任意のhtsvoiceを使って音声合成できる。
任意の辞書を使うときも、おなじように頑張ればできそう。
所感
ところで、speed
やhalf_tone
という引数はあるが、ほかの引数がない。OpenJTalkのコマンド版には次のような引数があった。それらもPyOpenJTalkで使いたい。どうしたらいいか。次回、コードをさらに読んでみる。
open_jtalk
usage: open_jtalk [ options ] [ infile ] options: [ def][ min-- max] -x dir : dictionary directory [ N/A] -m htsvoice : HTS voice files [ N/A] -ow s : filename of output wav audio (generated speech) [ N/A] -ot s : filename of output trace information [ N/A] -s i : sampling frequency [ auto][ 1-- ] -p i : frame period (point) [ auto][ 1-- ] -a f : all-pass constant [ auto][ 0.0-- 1.0] -b f : postfiltering coefficient [ 0.0][ 0.0-- 1.0] -r f : speech speed rate [ 1.0][ 0.0-- ] -fm f : additional half-tone [ 0.0][ -- ] -u f : voiced/unvoiced threshold [ 0.5][ 0.0-- 1.0] -jm f : weight of GV for spectrum [ 1.0][ 0.0-- ] -jf f : weight of GV for log F0 [ 1.0][ 0.0-- ] -g f : volume (dB) [ 0.0][ -- ] -z i : audio buffer size (if i==0, turn off) [ 0][ 0-- ] infile: text file [stdin]
options | comment | 既存 | API |
---|---|---|---|
-x dir |
dictionary directory |
○ | OpenJTalk(dn_mecab=dn_mecab.encode('ascii')) |
-m htsvoice |
HTS voice files |
○ | HTSEngine(htsvoice.encode('ascii')) |
-ow s |
filename of output wav audio (generated speech) |
☓ | 実装対象外 |
-ot s |
filename of output trace information |
☓ | 実装対象外 |
-s i |
sampling frequency |
☓ | HTS_Engine_set_sampling_frequency |
-p i |
frame period (point) |
☓ | HTS_Engine_set_fperiod |
-a f |
all-pass constant |
? | ? 対応API不明 |
-b f |
postfiltering coefficient |
? | ? 対応API不明 |
-r f |
speech speed rate |
○ | pyopenjtalk. tts(speed=1.0) |
-fm f |
additional half-tone |
○ | pyopenjtalk. tts(half_tone=0.0) |
-u f |
voiced/unvoiced threshold |
☓ | HTS_Engine_set_msd_threshold |
-jm f |
weight of GV for spectrum |
☓ | HTS_Engine_set_gv_weight |
-jf f |
weight of GV for log F0 |
☓ | HTS_Engine_set_gv_interpolation_weight |
-g f |
volume (dB) |
☓ | HTS_Engine_set_volume |
-z i |
audio buffer size (if i==0, turn off) |
☓ | HTS_Engine_set_audio_buff_size |
infile |
text file (default = stdin) |
○ | pyopenjtalk. tts(text) |
usage: open_jtalk [ options ] [ infile ] options: [ def][ min-- max] -x dir : dictionary directory [ N/A] 既存: OpenJTalk(dn_mecab=dn_mecab.encode('ascii')) -m htsvoice : HTS voice files [ N/A] 既存: HTSEngine(htsvoice.encode('ascii')) -ow s : filename of output wav audio (generated speech) [ N/A] -ot s : filename of output trace information [ N/A] -s i : sampling frequency [ auto][ 1-- ] HTS_Engine_set_sampling_frequency -p i : frame period (point) [ auto][ 1-- ] HTS_Engine_set_fperiod -a f : all-pass constant [ auto][ 0.0-- 1.0] ? -b f : postfiltering coefficient [ 0.0][ 0.0-- 1.0] ? -r f : speech speed rate [ 1.0][ 0.0-- ] 既存: pyopenjtalk.tts(speed=1.0) -fm f : additional half-tone [ 0.0][ -- ] 既存: pyopenjtalk.tts(half_tone=0.0) -u f : voiced/unvoiced threshold [ 0.5][ 0.0-- 1.0] HTS_Engine_set_msd_threshold -jm f : weight of GV for spectrum [ 1.0][ 0.0-- ] HTS_Engine_set_gv_weight -jf f : weight of GV for log F0 [ 1.0][ 0.0-- ] HTS_Engine_set_gv_interpolation_weight -g f : volume (dB) [ 0.0][ -- ] HTS_Engine_set_volume -z i : audio buffer size (if i==0, turn off) [ 0][ 0-- ] HTS_Engine_set_audio_buff_size infile: text file [stdin]
対象環境
- Raspbierry pi 4 Model B
- Raspberry Pi OS buster 10.0 2020-08-20 ※
- bash 5.0.3(1)-release
$ uname -a Linux raspberrypi 5.4.83-v7l+ #1379 SMP Mon Dec 14 13:11:54 GMT 2020 armv7l GNU/Linux