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

モロ屋

アキバではたらくWebエンジニア。JavaScript / AWS / Mac

「初音ミクが自動で喋るツール」をVY1で作ってみた


おとつい、Skypeで「これ見てみろ!」と送られてきた動画がありましたとさ。


D


「うおおおなにこれっべー! っべーわこれ!」とか言って華麗に釣られました。

こんちくしょうネタの仕込みが上手いよね!


というわけで釣られたのがすげー悔しかったので、正攻法で対抗することにした。


脳内会議

  • VOCALOIDが喋るといえばVOCALOID-flex
  • Softalkと同じくらい誰でも汎用的に使えるならVOCALOID2持ってなくてもOKにしたい
  • じゃあNetVOCALOID-flexか
  • 幸いにもMashupAward6の時にYAMAHAに申し込んでたAPIがまだ使える
  • MA6は急遽同人誌を作ることになったので作れなかった
  • 今こそ作るチャンスでは
  • やるかーやるしかないかー

仕様案まず考えたけど、あの釣り動画の解説って割と現実味を帯びてるんだよね。(だからこそ釣られた)

というわけで、それに近しい形で試しに実装してみる。


  1. 日本語を入力する
  2. 形態素解析器にかける
  3. 文章の文節・品詞・よみがなを取得
  4. ひらがなの文章からミク語に翻訳
  5. 単語のアクセントを生成
  6. 意味辞書からイントネーションを生成(未定)
  7. それらの情報から発話のピッチを演算して生成
  8. Voice Synthesis XMLを生成
  9. YAMAHAのNetVOCALOID-flexサーバに投げる
  10. しゃべる!

形態素解析器はMeCab使うかなーと思ったけど、面倒だったのでYahoo! デベロッパーネットワークのテキスト解析APIを使った。

ミク語変換だけど、これは普通のVOCALOID2の場合と違っているため独自に実装した。


例えば動画中で出てくる「家に帰ると妻が必ず死んだふりをしています」は

 array(3) {
    ["str"]=>
    string(60) "家に帰ると妻が必ず死んだふりをしています"
    ["kana"]=>
    string(75) "いえにかえるとつまがかならずしんだふりをしています"
    ["speak"]=>
    string(49) "ieJikae4MtotsMmagakana4adzMSiN\dap\M4'ioSiteimasM"
  }

こうなる。


形態素解析で単語を得られたら、その情報からアクセントを取得した。

日本語のアクセントは、ネット辞書からアクセント表示をスクレイピングした。



【11.この辞書のアクセント表示】

・日本語のアクセントは、単語を発音するさいに、その単語の中に含まれる個々の「拍」を高く発音するか低く発音するかによって決まる。拍とは日本語の音の長さの単位をいい、「キャ・シュ・チョ」などの拗音はカナ2字で1拍である。

・共通語では、1拍目と2拍目との間に必ず音の高低の変化がある。

・1拍目が高で2拍目以降が低である語は「頭高型」と言い、この辞典では [1] で示した。

・1拍目が低で、あとに続く助詞を含め高から低に移る箇所のない語は「平板式」と言い [0] で示した。

・1拍目が低で、2拍目以降が高になり、語中、語末に高から低に移る箇所のある語は「中高型」または「尾高型」と言い、低に移る直前の音の位置が2拍目であれば [2]、3拍目であれば [3]… のように示した。その位置が語中にあるものを「中高型」、語末にあるものを「尾高型」と言う。

・以上のうち、平板式を除く「頭高型」「中高型」「尾高型」を総称して「起伏式」と言う。


国語辞書 - エキサイト 辞書


イントネーションの辞書は現在未定。

ただこれがあるとないとでは精度に大きな違いが現れるのは間違いないと思う。


ここからピッチ(声の高低)を生成する。

演算式には、かの有名なRobert Penner氏のイージングを使った。


Robert Penner’s Easing Functions


Tweener等のEasingと同じもの。

<?php
/**
 * Easing equation function for a quadratic (t^2) easing in: accelerating from zero velocity.
 *
 * @param t		Current time (in frames or seconds).
 * @param b		Starting value.
 * @param c		Change needed in value.
 * @param d		Expected easing duration (in frames or seconds).
 * @return		The correct value.
 */

function easeNone ($t,$b,$c,$d) {
	return $c*$t/$d + $b;
}

function easeInQuad ($t,$b,$c,$d) {
	return $c*($t/=$d)*$t*$t*$t + $b;
}

function easeOutQuad ($t,$b,$c,$d) {
	return -$c *($t/=$d)*($t-2) + $b;
}

// 続きを読むには(ry
?>

ここからYAMAHAが定義した、VSXML (Voice Synthesis XML)ファイルを生成する。

これには「せりふ(発音記号)・発音位置・長さ・韻律パラメーター(音量、音高)」が含まれる。


f:id:Molokheiya:20101215130520p:image


というわけで「こんにちは 初音ミクです」と喋るXMLを生成してみた。

ちなみにこの一文だけで300行近いXMLが必要。現在はピッチ情報のみなので、さらに改良していったら3倍にはなりそう。


基本発話データ

  [0]=>
  array(3) {
    ["str"]=>
    string(34) "こんにちわ 初音ミクです"
    ["kana"]=>
    string(37) "こんにちわ はつねみくです"
    ["speak"]=>
    string(27) "koN\JitSiwahatsMnem'ikMdesM"
  }


例の動画にならって、棒読みモードと並べてみる。



棒読みモード


Download



感情モード


Download



とりあえずアクセントが自動でついたよ! やったねたえちゃん!!



だが現状、完成度はまだまだと言わざるを得ないので、時間が空いたらまたボチボチ改良していこうかなとかなんとか。

あと公開は別に構わないんですが、YAMAHAのY2 Projectから承認もらわないといけないので、声が多ければ聞いてみます。


そして重要なことが一つ。



現在NetVOCALOID-flexではVY1しか使えないので


実はミクさんじゃないんだなコレHAHAHAHA!!



みんながYAMAHAとクリプトンに要望すれば、データベース使わせてくれるかもね!!!11



んではでは!w



(C)Yamaha Corporation / Molokheiya