やってみる

アウトプットすべく己を導くためのブログ。その試行錯誤すらたれ流す。

PyOpenJTalkのコードを見てみる1

 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だ。引数のtextextract_fullcontextに渡して、それをさらに渡している。

 synthesizeは音声データを生成する。HTSEngineクラスのインスタンスを生成している。ここでボイスデータであるhtsvoiceファイルパスを引数に渡している。

 そんな感じでコードを追っていくと、以下のような流れだった。

 つまりHTSEngine, OpenJTalkクラスのインスタンスを生成するとき、引数にhtsvoiceファイルパスと辞書ファイルパスを渡せば、任意のそれらを使うことができそうだ。以下のようなコードになるか。

import pyopenjtalk
from pyopenjtalk import *
engine = pyopenjtalk.HTSEngine(htsvoice_path.encode('ascii'))
ojt = pyopenjtalk.OpenJTalk(dn_mecab=dic_path.encode('ascii'))

 HTSEngineインスタンスを使って音声合成してみる。

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を使って音声合成できる。

 任意の辞書を使うときも、おなじように頑張ればできそう。

所感

 ところで、speedhalf_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]

対象環境

$ uname -a
Linux raspberrypi 5.4.83-v7l+ #1379 SMP Mon Dec 14 13:11:54 GMT 2020 armv7l GNU/Linux