Python
NLP
音声合成
Latin

ラテン語文を合成音声で読み上げる技術

More than 5 years have passed since last update.

こんにちは。@naoya_t です。

12/2の拙記事「ラテン語文解析プログラムを書くことを目的としたラテン語学習(前編)」で紹介した拙作解析ツール
https://github.com/naoyat/latin
では、MacOSXに搭載されている英文音声合成技術を利用して、ラテン語文を音読することが可能です。

この記事では、その辺りの事について語ってみたいと思います。

実装については speak_latin.py, latin/latin_syllable.py あたりをご覧ください。

デモ

$ echo "Cerēs erat dea frūmentī." | python latin.py -s

-s (--speech) が音読をONにするオプションです。

マクロン(長音記号)の入力が面倒なら、大文字を長音と認識させる -m (--capital-to-macron) オプションを使って

$ echo "vEnI, vIdI, vIcI." | python latin.py -m -s

のようにも使えます。

音声合成と発音

MacOSX の音声合成機能(text-to-speech)は今では英語以外の多くの言語での発話に対応していますが、細かい制御に対応しているのが(とりあえず手元のOS X 10.7.xでは)英語だけなので、発話したい内容を(北米)英語の発音記号に落としこむ必要があります。それぞれの音の高さ(周波数)や長さも設定する必要があります。

詳しくはApple社が公開している開発資料 https://developer.apple.com/library/mac/documentation/userexperience/conceptual/SpeechSynthesisProgrammingGuide/SpeechOverview/SpeechOverview.html#//apple_ref/doc/uid/TP40004365-CH3-SW6 辺りをご覧ください。

音素と長さ

ラテン語のアルファベットを、対応する音素の発音記号に置き換えます。

例:"Crētā" → k r EH t AA

EHAA は(k, r, t もそうですが)text-to-speech内部で用いられる音素表現です。

北米英語で用いられる音素に対応したものしか存在しないので、これを並べると何を喋っても北米訛りになる、という弱点が存在しますが、その点には目を瞑って頂ければ幸いです。

ちなみに母音の長短は(英語側で対応する短母音/長母音ではなく)音の長さで表しています。
(speak_latin.py の実装では、子音と短母音の長さを110msec、長母音の長さを220msecにしています。上の例では k, r, t が110msec、EH, AA が220msecです)

周波数(ピッチ)

ラテン語は高低アクセントなので、アクセントはとりあえず周波数の高低で表現することができます。

とりあえず、というのは、音声学的にどうこうというのはさておき、それっぽく聞こえるという精度を念頭においています。

アクセントはどこに来るのか

ラテン語では2音節語は最初の音節(=「paenultima 後ろから2番目の(音節)」)に、3音節語はpaenultimaの長短によって最初の音節ないし2番目の音節にアクセントが来ますので、アクセントが来る音節の周波数を他よりも高めに発声させます。

例: "Crētā" → C-rē-tā → C-[rē]-tā

speak_latin.py の実装では、低い方を135Hz(CとC#の間ぐらい?)、高い方をその4/3倍(低い音の4度上に相当)にしています。

音節の区切り方自体は概ね規則通りなので規則を実装します。(latin/latin_syllable.py)

  • lūx → lūx
  • caesar → cae-sar → [cae]-sar
  • cōnsulēs → cōn-su-lēs → [cōn]-su-lēs

発音制御コマンド列の生成

ここまで来ればラテン語の文を、(北米英語の)音素・長さ・ピッチ(周波数)の列に分解することができるので、text-to-speechの"TUNEフォーマット"(https://developer.apple.com/library/mac/documentation/userexperience/conceptual/SpeechSynthesisProgrammingGuide/FineTuning/FineTuning.html#//apple_ref/doc/uid/TP40004365-CH5-SW7 参照)で表現し、APIを叩くなり say コマンドに

[[inpt TUNE]] 発音制御コマンド列 [[inpt TEXT]]

のように投げるなりすれば発話が可能です。

例:"Crētā"

  k {D 110; P 135:0}
  r {D 110; P 180:0}
  EH {D 220; P 180:0}
  ~t {D 110; P 135:0}
  AA {D 220; P 135:0}
  % {D 110}

~ は前後の音素を一続きに読まないための記号で、% は無音を表します。

発音制御コマンド列の例

元のラテン語文:

In Crētā īnsulā māgnum labyrinthum Daedalus aedificāvit plēnum viārum flexuōsārum.

発音制御コマンド列:

tune.txt
[[inpt TUNE]]
   IY {D 110; P 135:0}
   n {D 110; P 135:0}
   % {D 110}

   k {D 110; P 135:0}
   r {D 110; P 180:0}
   EH {D 220; P 180:0}
   ~t {D 110; P 135:0}
   AA {D 220; P 135:0}
   % {D 110}

   IY {D 220; P 180:0}
   n {D 110; P 180:0}
   s {D 110; P 135:0}
   UW {D 110; P 135:0}
   l {D 110; P 135:0}
   AA {D 220; P 135:0}
   % {D 110}

   m {D 110; P 180:0}
   AA {D 220; P 180:0}
   g {D 110; P 180:0}
   n {D 110; P 135:0}
   UW {D 110; P 135:0}
   m {D 110; P 135:0}
   % {D 110}

   l {D 110; P 135:0}
   AA {D 110; P 135:0}
   b {D 110; P 135:0}
   yUW {D 110; P 135:0}
   r {D 110; P 180:0}
   IY {D 110; P 180:0}
   n {D 110; P 180:0}
   ~t {D 110; P 135:0}
   h {D 110; P 135:0}
   UW {D 110; P 135:0}
   m {D 110; P 135:0}
   % {D 110}

   d {D 110; P 180:0}
   AA {D 110; P 180:0}
   EH {D 110; P 180:0}
   d {D 110; P 135:0}
   AA {D 110; P 135:0}
   l {D 110; P 135:0}
   UW {D 110; P 135:0}
   s {D 110; P 135:0}
   % {D 110}

   AA {D 110; P 135:0}
   EH {D 110; P 135:0}
   d {D 110; P 135:0}
   IY {D 110; P 135:0}
   f {D 110; P 135:0}
   IY {D 110; P 135:0}
   k {D 110; P 180:0}
   AA {D 220; P 180:0}
   w {D 110; P 135:0}
   IY {D 110; P 135:0}
   ~t {D 110; P 135:0}
   % {D 110}

   p {D 110; P 180:0}
   l {D 110; P 180:0}
   EH {D 220; P 180:0}
   n {D 110; P 135:0}
   UW {D 110; P 135:0}
   m {D 110; P 135:0}
   % {D 110}

   w {D 110; P 180:0}
   IY {D 110; P 180:0}
   AA {D 220; P 180:0}
   r {D 110; P 135:0}
   UW {D 110; P 135:0}
   m {D 110; P 135:0}
   % {D 110}

   f {D 110; P 135:0}
   l {D 110; P 135:0}
   EH {D 110; P 135:0}
   ks {D 220; P 135:0}
   UW {D 110; P 135:0}
   OW {D 220; P 135:0}
   s {D 110; P 180:0}
   AA {D 220; P 180:0}
   r {D 110; P 135:0}
   UW {D 110; P 135:0}
   m {D 110; P 135:0}
   ~ {D 110; P 135:0}
   % {D 110}
[[inpt TEXT]]

結果

$ say < tune.txt
→ http://www1419ue.sakura.ne.jp/tune.mp3

終わりに

12/25までまだまだ枠に空きがあるので、多分また何か書きます!