こんにちは。@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
EH
や AA
は(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.
発音制御コマンド列:
[[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までまだまだ枠に空きがあるので、多分また何か書きます!