読者です 読者をやめる 読者になる 読者になる

Emacsで日本語/英語音声合成

emacs

はじめに

ふと,Emacsから音声合成できたらおもしろいのではないかと思った.
偉大な先人達はすでにいくつか実現している:

上の各記事では, 音声合成にsayコマンドを利用している.
これは英語のテキストを与えるとそれを読み上げてくれるコマンドで,音質もなかなかだと思う.
しかしながら,Emacsから日本語で音声合成を実践した例はあまり見られない.
そこで今回は,上記記事も参考にしつつ,日本語/英語の音声合成をEmacsから行おうと試みた.

テスト済の計算機環境

使用するソフトウェア

日本語の音声合成のためにOpen JTalkを用いることにした.
また,英語音声合成のためにFlite+hts_engineを用いることにした.
これらにはhts_engine APIが必要なため,あらかじめインストールしておく必要がある.
hts_engine-APIのバージョンは1.07,Open JTalkのバージョンは1.06, flite+hts_engineのバージョンは1.04である.
上記ソフトウェアはソースコードからコンパイルしている.
なおOpen JTalkについてはhttp://d.nishimotz.com/archives/744 にあるような修正をしておいたほうがいいかもしれない.
また音声再生のためにsoxを,非同期処理のためにdeferred.elをあらかじめインストールしておく.

ソースコード

Githubにリポジトリを作成し,そこに置いてある:
https://github.com/tam17aki/speech-synth

インストール

(require 'speech-synth)
(setq speech-synth-dictionary-directory "/usr/local/share/dic")
(setq speech-synth-Flite-voice-file
      "/usr/local/share/hts_engine/cmu_us_arctic_slt.htsvoice")
(setq speech-synth-OpenJTalk-voice-file
      "/usr/local/share/hts_engine/nitech_jp_atr503_m001.htsvoice")

speech-synth-dictionary-directoryはOpen JTalk用の辞書ファイルが格納されているディレクトリ名である.
またspeech-synth-{Flite, OpenJTalk}-voice-fileは音声合成用のパラメータ情報が格納されたファイル名であり,
これらは指定必須である.

仕様

コマンド

コマンド名 説明
speech-synth-from-region リージョン内のテキストを音声に変換し,再生.
speech-synth-from-buffer バッファ内のテキストを音声に変換し,再生.

M-x speech-synth-from-{region, buffer}により,言語を自動選択して音声を合成・再生することが可能である.
テキストに含まれるアルファベットの比率がspeech-synth-lang-select-percentにより指定される値(%)を超えていたら英語が選択され,さもなくば日本語が選択される.
なおspeech-synth-lang-select-percentのデフォルト値は40である.

また,以下のコマンドを用いることで,話速や声の高さを変更することが可能である.

コマンド名 説明
speech-synth-set-parameter-interactive 音声合成時のパラメータを対話的に変更する.
speech-synth-set-parameter 音声合成時のパラメータを非対話的に変更する.

M-x speech-synth-set-parameter-interactiveにより,声質(Spectral warping),話速(Speech rate),音高(Pitch-shift),音量(Voice volume),抑揚(Intonation),ポストフィルタ(Postfilter)の各値を指定することができる.
speech-synth-set-parameterは非対話的にパラメータを変更することができる.
例えば,以下のようにしてLisp関数として呼び出す.

(speech-synth-set-parameter "Spectral warping" 0.48)

メジャーモード

コマンド名 説明
speech-synth 音声合成用テキスト入力のためのバッファを立ち上げる.

また,M-x speech-synthを実行することで,合成用テキスト入力のためのバッファ*Speech Synth*がポップアップする.
このバッファ内で専用のメジャーモードであるspeech-synth-modeが定義されており,
以下のキーバインドが使用可能である.

キーバインド 関数 説明
C-c C-r speech-synth-from-region リージョン内のテキストを音声に変換し,再生.言語は自動選択.
C-c C-b speech-synth-from-buffer バッファ内のテキストを音声に変換し,再生.言語は自動選択.
C-c C-q speech-synth-quit バッファを閉じる.

注意点

合成エンジンの仕様上,あまりに長い文章の合成は難しい.
環境に依存する部分があるかもしれず,実際に音が再生されないことはあるかもしれない.
文字コード周りの問題もあるかもしれない.

API

内部的に,音声合成用のAPIとして以下の関数speech-synth-execute-synthesisが用意されている.

(defun* speech-synth-execute-synthesis (text &key wav-file)

textにより実際に合成したいテキストを指定する.
テキストに改行文字が含まれる場合,改行文字直前までのテキストで音声合成されるので注意が必要である.
wav-fileは合成した音声を保存するWAVファイル名を指定するパラメータである.
もしWAVファイル名に何も指定しない,もしくはnilを指定した場合は,WAVファイルは保存されない.

使用例

1文章の合成

(speech-synth-execute-synthesis "おはようございます.")

とすれば合成された「おはようございます.」が再生される.WAVファイルは残らない.

M-x doctorに喋らせる場合

以下のようにするとよい.

(defadvice doctor-read-print (after say activate)
  "Let the psychotherapist speak with synthetic speech."
  (save-excursion
    (speech-synth-execute-synthesis
     (buffer-substring-no-properties
      (progn
        (re-search-backward "\n\n" nil t 2)
        (forward-char 2)
        (point))
      (progn
        (re-search-forward "\n\n" nil t)
        (forward-char -2)
        (point))))))

使う側としては,改行文字を取り除いたりすることで合成したいテキストをきちんと1行に整形して与えることが肝要である.

さらなるカスタマイズのために(上級者向け)

音響モデルの自作

HMM音声合成について理解のある諸氏は,Open JTalkらで使用する音響モデルを自作することが可能である.
これにより,様々な人の声で喋らせることが理論上可能ではある.
ただし少なからず音声データベースの類は必要となり,またHMM学習用ツールであるHTSを使いこなす必要があるため,いちから音響モデルを構築することは初心者には難しい点が多かろうと思う.

おわりに

日本語/英語音声合成をEmacsから試みた.
バッファから入力する場合とリージョンで選択された文字列を入力する場合の両方を実装し,実際に音が鳴ることを確認した.
今回書いたコードは言ってしまえばおもちゃのようなものだが,私はそれなりに楽しめている.

以上.