いろいろ調べてまとまってから書こうと思っていたが、なかなか終わらないので、途中までを記録しておこうと思う。
(1) flite
前回書いた通り、TTSをいじると、何やら面白い物が作れるのではないかという気がしたので、今週はそのまわりをいろいろと眺めてみた。とはいっても、日本語のものはaquestalkを使えば当面は遊べそうな気がしたので、どちらかと言えば英語をサポートしているTTSエンジンに興味が向かう。
そんなわけで、最初にTTSエンジンとして思い出したのはfestivalだ。CMUで開発されていて、C++ベースなのが難点だと思ったが、festival.hを見るとC++の色がついている感じではなかった...のだけど、実際にこれでP/Invokeするコードを書こうと思ったら、どうもこのヘッダにある関数だけでは足りず、インクルードされている他の型を使おうとしたらC++を避けて通ることはできなそうだ。
しかし、もう少し調べてみたら、このfestivalをベースにしてCで書き換えて組み込み用にしたfliteというものがあった。これなら問題なくP/Invokeできそうだ。と思ったが、グローバル変数などが使われていて、そのままでは使えなそうだ(といっても別のライブラリを作ってポインタを返せばいいだけだが)。今はとりあえず関数をソースに追加してビルドしている。これはまだ途中までしか出来ていないので、正しくinterop出来ているかどうかは分からない: FliteSharp.cs
flite.hにはwaveストリームにTTSの合成結果を落とし込むAPIが用意されていないようなので、flite.cでファイルに落としている関数を眺めつつ、相当のコードを書かなければならなそうだ。ただおそらくC#で書けるだろうと思う。
ちなみに、もうひとつ思いつくTTSエンジンでFreeTTSというJavaの実装があって、もうローカルに既定のプロトコルをしゃべるクライアント/サーバか何かを立てて、それ経由で共通APIを実装する形にしたらinteropもあまり気にしなくて良いだろう、と考えたのだけど、よく見たらFreeTTSはfliteに基づいているようだったので、とりあえずいらないと考えることにした。
(2) System.Speech.Synthesis
さて、実装できそうな雰囲気は何となく出てきたけど、これをどう使えばいいのかよく分からないし、TTSがどんなものなのかもあまり分かっていない。fliteのドキュメントはあまり親切ではなく、中で使われているfeaturesやpropertiesがどう提供されているのかもよく分からない。
そんなわけで、手始めにSystem.Speech.dllのSystem.Speech.Synthesis namespace相当のライブラリをこれで実装してみようかと思った。ただ、msdnを見ると分かるが、単なるSAPI (Speech API)のラッパーでしかなく、全くと言っていいほどドキュメントが無い。APIである程度分かるだろうと考えて、一通りのスタブ的なコードを書いて、pluggableな基底ライブラリを作ってみた。System.Speechはエンジン別に実装されたこれの派生クラスを生成して機能を呼び出すだけだ。fliteはLinux/Mac/Windowsで動くようなので、とりあえず普通に使えるだろう。
とりあえずfliteとSystem.Speechの機能の対応はこんな感じだろうと(現時点では)考えているが、実際に使ってみないと分からない:
- 音声データベース: cst_voice / VoiceInfo
- 発音センテンス: cst_utterance / Prompt(Builder)
- lexicon(センテンス データベース)操作: flite_voice_add_lex_addenda() / SpeechSynthesizer.AddLexicon()
変換元としては、単純なテキスト文字列の他にSSMLというW3C標準の言語が使える。
SpeechSynthesizerは、発音の構成要素となるイベントを詳細に追いかけることが出来るeventなどを用意しているが、これがfliteでfeatureとして提供されているかは分からない。カスタムコールバックを提供している関数で、とりあえず把握しているのは、ストリーミングを出力とする実装で発音バッファがいっぱいになったら送られる、というものだけだ。
(3) SSML
SSMLはもう5年以上前にrecommendationになったXMLボキャブラリの仕様で、発音の仕方(上記のcst_utteranceやPromptに相当する)を記述する言語だ。fliteもSAPI/System.Speechもこれをサポートしている。
System.SpeechはSSMLを前提としているようなAPIにもなっている。たとえばVoiceGenderはvoice要素のgender属性の規定値と同じだ。VoiceAgeは年齢の数値ではなく列挙型になっているが、音色属性にageを含めるというのはSSMLと同じだ。
vocaloid(鏡音リン・レン)の場合はgender factorは数値で調整するが、TTSエンジンの音色データベース(cst_voiceやVoiceInfo)でそこまで調整できるとは考えにくい。最終目標は単なるTTSではないので、この辺は気になるところだが、むしろ合成結果の波形に対するエフェクトとして実装できるかどうか、ではないかと思う(出来ると期待したい)。いずれにしろ、エフェクトの類は、原理を全然知らないので、調べてみないと分からない。
vocaloidのようなものが実装できるかどうかに影響する、より重要な要素は、発音についてどれだけ詳細に記述できるかどうかだ。TTSは厳密な音の表現を目的としていないだろうから、「しゃべれれば何でも良い」になりそうに思う。この辺も調べてみないと分からない。以前mugeneで書いたVSQサポートの歌詞マクロ相当のことは出来てほしい。
今日はとりあえずここまで。とりあえずTTSでしゃべれるようにする必要がある。