初音ミクに喋らせてみた(Perl版004)
初音ミクに喋らせるスクリプトをちょっとだけバージョンアップしてみました。
相変わらずハードコーディングですが、$myTalk の文字列(平仮名のみ限定)を書き換えることで、任意文字列の発音ができるようにしています。
ハードコーディングしている理由は、エラー処理をしていない為です。たぶん半角文字やカタカナを入れるとミクが黙りこむとおもいます。親切に実行手順を書いていないのは、「まだα版なので、わかる人だけ触ってください」という趣旨です。
Perl スクリプトと、生成される VSQファイルは以下のものです。
「miku_talk004.zip」をダウンロード
生成される音声は「わたしわ、はつねみく。わたしわ、しゃべるのがすき」です。音声ファイルと照合してください。
「test_miku004.mp3」をダウンロード
そして、ソースコードはこちら。ちょっとだけ手を入れて美化。
#!/Perl
########################################################################
# miku_talk ver.0.0.4
#
# Programmed by Akira Izumi
# Ver.0.0.1:ハードコーディング"みく" ... 6/Dec/2007
# Ver.0.0.4:任意の平仮名入力を受付ける...15/Dec/2007
#
use MIDI;
use Jcode;
use strict;
use warnings;
my $myTalk = "わたしわ、はつねみく、わたしわ、しゃべるのがすき。";
miku_VsqGenerate($myTalk,"test_miku004.vsq");
exit(0);
#-----------------------------------------------------------------------
#
# 平仮名文字列からVSQファイルを生成する
# 第1引数:平仮名のみのテキスト文字列
# 第2引数:出力VSQファイル名
#
sub miku_VsqGenerate {
my $myStr2Talk = $_[0];
my $myVsqFile = $_[1];
#
# マスタートラックの定義
#
my @masterEvents = (
['track_name', 0, 'Master Track'],
['set_tempo', 0, 500_000], # 1qn = .50 seconds
['time_signature',0,4,2,24,8 ],
['end_track' , 0],
);
#
# 平仮名からミク発音記号への変換ハッシュ表
#
my %phonetic =
("あ"=>"a", "い"=>"i", "う"=>"M", "え"=>"e", "お"=>"o",
"か"=>"k a","き"=>"k' i","く"=>"k M", "け"=>"k e", "こ"=>"k o",
"さ"=>"s a","し"=>"S i", "す"=>"s M", "せ"=>"s e", "そ"=>"s o",
"た"=>"t a","ち"=>"tS i","つ"=>"ts M", "て"=>"t e", "と"=>"t o",
"な"=>"n a","に"=>"J i", "ぬ"=>"n M", "ね"=>"n e", "の"=>"n o",
"は"=>"h a","ひ"=>"C i", "ふ"=>"p\\ M","へ"=>"h e", "ほ"=>"h o",
"ま"=>"m a","み"=>"m' i","む"=>"m M", "め"=>"m e", "も"=>"m o",
"や"=>"j a", "ゆ"=>"j M", "いぇ"=>"j e","よ"=>"j o",
"ら"=>"4 a","り"=>"4' i","る"=>"4 M", "れ"=>"4 e", "ろ"=>"4 o",
"わ"=>"w a",
# "ゐ"=>"w i", "ゑ"=>"w e",
"を"=>"o",
"うぃ"=>"w i", "うぇ"=>"w e",
"ん"=>"n",
"んが"=>"N a", "んぎ"=>"N i", "んぐ"=>"N M", "んげ"=>"N e", "んご"=>"N o",
"んにゃ"=>"N' a","んにぃ"=>"N' i","んにゅ"=>"N' M","んにぇ"=>"N' e","んにょ"=>"N' o",
"が"=>"g a", "ぎ"=>"g' i", "ぐ"=>"g M", "げ"=>"g e", "ご"=>"g o",
"ざ"=>"dz a", "じ"=>"dZ i", "ず"=>"dz M", "ぜ"=>"dz e", "ぞ"=>"dz o",
"だ"=>"d a", "ぢ"=>"dZ i", "づ"=>"dz M", "で"=>"d e", "ど"=>"d o",
"ば"=>"b a", "び"=>"b' i", "ぶ"=>"b M", "べ"=>"b e", "ぼ"=>"b o",
"ぱ"=>"p a", "ぴ"=>"p' i", "ぷ"=>"p M", "ぺ"=>"p e", "ぽ"=>"p o",
"きゃ"=>"k' a","きぃ"=>"k' i","きゅ"=>"k' M","きぇ"=>"k' e","きょ"=>"k' o",
"しゃ"=>"S a", "しぃ"=>"S i", "しゅ"=>"S M", "しぇ"=>"S e", "しょ"=>"S o",
"ちゃ"=>"tS a","ちぃ"=>"tS i","ちゅ"=>"tS M","ちぇ"=>"tS e","ちょ"=>"tS o",
"にゃ"=>"J a", "にぃ"=>"J i", "にゅ"=>"J M", "にぇ"=>"J e", "にょ"=>"J o",
"ひゃ"=>"C a", "ひぃ"=>"C i", "ひゅ"=>"C M", "ひぇ"=>"C e", "ひょ"=>"C o",
"ふゃ"=>"p\\' a","ふぃ"=>"p\\' i","ふゅ"=>"p\\' M","ふぇ"=>"p\\' e","ふょ"=>"p\\' o",
"みゃ"=>"m' a","みぃ"=>"m' i","みゅ"=>"m' M","みぇ"=>"m' e","みょ"=>"m' o",
"りゃ"=>"4' a","りぃ"=>"4' i","りゅ"=>"4' M","りぇ"=>"4' e","りょ"=>"4' o",
"ぎゃ"=>"g' a","ぎぃ"=>"g' i","ぎゅ"=>"g' M","ぎぇ"=>"g' e","ぎょ"=>"g' o",
"じゃ"=>"Z a", "じぃ"=>"Z i", "じゅ"=>"Z M", "じぇ"=>"Z e", "じょ"=>"Z o",
"じゃ"=>"dZ a","じぃ"=>"dZ i","じゅ"=>"dZ M","じぇ"=>"dZ e","じょ"=>"dZ o",
"ぢゃ"=>"dZ a","ぢぃ"=>"dZ i","ぢゅ"=>"dZ M","ぢぇ"=>"dZ e","ぢょ"=>"dZ o",
"びゃ"=>"b' a","びぃ"=>"b' i","びゅ"=>"b' M","びぇ"=>"b' e","びょ"=>"b' o",
"ぴゃ"=>"p' a","ぴぃ"=>"p' i","ぴゅ"=>"p' M","ぴぇ"=>"p' e","ぴょ"=>"p' o",
"ふぁ"=>"p\\ a","ふぃ"=>"p\\ i","ふぅ"=>"p\\ M","ふぇ"=>"p\\ e","ふぉ"=>"p\\ o",
"てゃ"=>"t' a","てぃ"=>"t' i","てゅ"=>"t' M","てぇ"=>"t' e","てょ"=>"t' o",
"でゃ"=>"d' a","でぃ"=>"d' i","でゅ"=>"d' M","でぇ"=>"d' e","でょ"=>"d' o",
"ぁ"=>"h\\ a", "ぃ"=>"h\\ i", "ぅ"=>"h\\ M","ぇ"=>"h\\ e", "ぉ"=>"h\\ o",
"っ"=>"tS ",
"すぃ"=>"s i", "ずぃ"=>"dz i", "とぅ"=>"t M","どぅ"=>"d M");
#
# ミクの発音用テキストに於ける初期値の設定。
#
my @myCommonSection =();
push @myCommonSection, "[Common]";
push @myCommonSection, "Version=DSB301";
push @myCommonSection, "Name=Voice1";
push @myCommonSection, "Color=181,162,123";
push @myCommonSection, "DynamicsMode=1";
push @myCommonSection, "PlayMode=1";
my @myMasterSection =();
push @myMasterSection, "[Master]";
push @myMasterSection, "PreMeasure=4";
my @myMixerSection =();
push @myMixerSection, "[Mixer]";
push @myMixerSection, "MasterFeder=0";
push @myMixerSection, "MasterPanpot=0";
push @myMixerSection, "MasterMute=0";
push @myMixerSection, "OutputMode=0";
push @myMixerSection, "Tracks=1";
push @myMixerSection, "Feder0=0";
push @myMixerSection, "Panpot0=0";
push @myMixerSection, "Mute0=0";
push @myMixerSection, "Solo0=0";
my @myEventListSection =();
push @myEventListSection, "[EventList]";
push @myEventListSection, "0=ID#0000";
my @myIDSection =();
push @myIDSection, "[ID#0000]";
push @myIDSection, "Type=Singer";
push @myIDSection, "IconHandle=h#0000";
my @myHandleSection =();
push @myHandleSection, "[h#0000]";
push @myHandleSection, "IconID=\$07010000";
push @myHandleSection, "IDS=Miku";
push @myHandleSection, "Original=0";
push @myHandleSection, "Caption=";
push @myHandleSection, "Length=1";
push @myHandleSection, "Language=0";
push @myHandleSection, "Program=0";
my @mikuMidiEvents = ();
push @mikuMidiEvents,['control_change' , 0, 0, 99, 96];
push @mikuMidiEvents,['control_change' , 0, 0, 98, 0];
push @mikuMidiEvents,['control_change' , 0, 0, 6, 0];
push @mikuMidiEvents,['control_change' , 0, 0, 38, 0];
push @mikuMidiEvents,['control_change' , 0, 0, 98, 1];
push @mikuMidiEvents,['control_change' , 0, 0, 6, 0];
push @mikuMidiEvents,['control_change' , 0, 0, 38, 0];
push @mikuMidiEvents,['control_change' , 0, 0, 98, 2];
push @mikuMidiEvents,['control_change' , 0, 0, 6, 0];
push @mikuMidiEvents,['control_change' , 0, 0, 99, 83];
push @mikuMidiEvents,['control_change' , 0, 0, 98, 2];
push @mikuMidiEvents,['control_change' , 0, 0, 6, 0];
#
# ミク発音(平仮名)を、ミク発音用メタデータに変換し、
# 同時にMIDIイベントを生成する。
#
my $i=0;
my $idxLyric = 0;
my $pitch = 240;
my $note = 64;
for($i=0; $idxLyric<length($myStr2Talk); $i++ ) {
my $myLyricLen = 6;
my $myLyric = "";
my $myPhonetic = "";
for($myLyricLen=6; $myLyricLen>0; $myLyricLen-=2) {
$myLyric = substr($myStr2Talk,$idxLyric,$myLyricLen);
$myPhonetic = $phonetic{$myLyric};
if( defined($myPhonetic) || $myLyricLen==2 ) {
last;
}
}
$idxLyric += $myLyricLen;
if( defined($myPhonetic)) {
push @myEventListSection, sprintf("%d=ID#%04d",$i*$pitch+7680,$i+1);
push @myIDSection, sprintf("[ID#%04d]",$i+1);
push @myIDSection, "Type=Anote";
push @myIDSection, "Length=".$pitch;
push @myIDSection, "Note#=".$note;
push @myIDSection, "Dynamics=64";
push @myIDSection, "PMBendDepth=20";
push @myIDSection, "PMBendLength=0";
push @myIDSection, "PMbPortamentoUse=0";
push @myIDSection, "DEMdecGainRate=50";
push @myIDSection, "DEMaccent=50";
push @myIDSection, sprintf("LyricHandle=h#%04d",$i+1);
push @myHandleSection, sprintf("[h#%04d]",$i+1);
push @myHandleSection, "L0=\"".$myLyric."\",\"". $myPhonetic."\",1.000000,64,0,0";
}
if( $i==0 ) {
push @mikuMidiEvents,['control_change', 5760, 0, 99, 80];
} else {
push @mikuMidiEvents,['control_change', $pitch, 0, 99, 80];
}
push @mikuMidiEvents,['control_change', 0, 0, 98, 0];
push @mikuMidiEvents,['control_change', 0, 0, 6, 0];
push @mikuMidiEvents,['control_change', 0, 0, 38, 0];
push @mikuMidiEvents,['control_change', 0, 0, 98, 1];
push @mikuMidiEvents,['control_change', 0, 0, 6, 15];
push @mikuMidiEvents,['control_change', 0, 0, 38, 80];
push @mikuMidiEvents,['control_change', 0, 0, 98, 2];
push @mikuMidiEvents,['control_change', 0, 0, 6, 64];
push @mikuMidiEvents,['control_change', 0, 0, 98, 3];
push @mikuMidiEvents,['control_change', 0, 0, 6, 64];
push @mikuMidiEvents,['control_change', 0, 0, 98, 4];
push @mikuMidiEvents,['control_change', 0, 0, 6, 1];
push @mikuMidiEvents,['control_change', 0, 0, 38, 122];
push @mikuMidiEvents,['control_change', 0, 0, 98, 5];
push @mikuMidiEvents,['control_change', 0, 0, 6, 1];
push @mikuMidiEvents,['control_change', 0, 0, 98, 18];
push @mikuMidiEvents,['control_change', 0, 0, 6, 3];
push @mikuMidiEvents,['control_change', 0, 0, 98, 19];
push @mikuMidiEvents,['control_change', 0, 0, 6, 109];
push @mikuMidiEvents,['control_change', 0, 0, 38, 64];
push @mikuMidiEvents,['control_change', 0, 0, 98, 20];
push @mikuMidiEvents,['control_change', 0, 0, 6, 39];
push @mikuMidiEvents,['control_change', 0, 0, 98, 21];
push @mikuMidiEvents,['control_change', 0, 0, 6, 105];
push @mikuMidiEvents,['control_change', 0, 0, 38, 0];
push @mikuMidiEvents,['control_change', 0, 0, 98, 79];
push @mikuMidiEvents,['control_change', 0, 0, 6, 127];
push @mikuMidiEvents,['control_change', 0, 0, 98, 80];
push @mikuMidiEvents,['control_change', 0, 0, 6, 12];
push @mikuMidiEvents,['control_change', 0, 0, 98, 81];
push @mikuMidiEvents,['control_change', 0, 0, 6, 8];
push @mikuMidiEvents,['control_change', 0, 0, 98, 82];
push @mikuMidiEvents,['control_change', 0, 0, 6, 20];
push @mikuMidiEvents,['control_change', 0, 0, 98, 83];
push @mikuMidiEvents,['control_change', 0, 0, 6, 28];
push @mikuMidiEvents,['control_change', 0, 0, 98, 84];
push @mikuMidiEvents,['control_change', 0, 0, 6, 24];
push @mikuMidiEvents,['control_change', 0, 0, 98, 85];
push @mikuMidiEvents,['control_change', 0, 0, 6, 10];
push @mikuMidiEvents,['control_change', 0, 0, 98, 86];
push @mikuMidiEvents,['control_change', 0, 0, 6, 12];
push @mikuMidiEvents,['control_change', 0, 0, 98, 87];
push @mikuMidiEvents,['control_change', 0, 0, 6, 12];
push @mikuMidiEvents,['control_change', 0, 0, 98, 88];
push @mikuMidiEvents,['control_change', 0, 0, 6, 0];
push @mikuMidiEvents,['control_change', 0, 0, 98, 89];
push @mikuMidiEvents,['control_change', 0, 0, 6, 50];
push @mikuMidiEvents,['control_change', 0, 0, 98, 90];
push @mikuMidiEvents,['control_change', 0, 0, 6, 50];
push @mikuMidiEvents,['control_change', 0, 0, 98, 127];
push @mikuMidiEvents,['control_change', 0, 0, 6, 127];
}
push @mikuMidiEvents,['end_track' , $pitch+1920];
push @myEventListSection, sprintf("%d=EOS",$i*$pitch+7620);
#
# ミク発音用メタデータのセクションを結合する
#
my $my_miku_phonetics="";
my $phonetic = "";
foreach $phonetic (@myCommonSection) {
$my_miku_phonetics = $my_miku_phonetics.$phonetic."\n";
}
foreach $phonetic (@myMasterSection) {
$my_miku_phonetics = $my_miku_phonetics.$phonetic."\n";
}
foreach $phonetic (@myMixerSection) {
$my_miku_phonetics = $my_miku_phonetics.$phonetic."\n";
}
foreach $phonetic (@myEventListSection) {
$my_miku_phonetics = $my_miku_phonetics.$phonetic."\n";
}
foreach $phonetic (@myIDSection) {
$my_miku_phonetics = $my_miku_phonetics.$phonetic."\n";
}
foreach $phonetic (@myHandleSection) {
$my_miku_phonetics = $my_miku_phonetics.$phonetic."\n";
}
#
# Voice1トラックを生成する。
#
my @voice1Events = (
['track_name', 0, 'Voice1'],
);
for($i=0; $i*119<length($my_miku_phonetics); $i++) {
push @voice1Events, ['text_event', 0,
sprintf("DM:%04d:",$i).substr($my_miku_phonetics,$i*119,119) ];
}
my $mikuMidi = "";
foreach $mikuMidi (@mikuMidiEvents) {
push @voice1Events,$mikuMidi;
}
#
# マスタートラックとVoice1トラックからVSQファイルを生成する。
#
my $master_track = MIDI::Track->new({ 'events' => \@masterEvents });
my $voice1_track = MIDI::Track->new({ 'events' => \@voice1Events });
my $opus = MIDI::Opus->new(
{ 'format' => 1, 'ticks' => 480, 'tracks' => [ $master_track, $voice1_track ] } );
$opus->write_to_file( $myVsqFile );
}
| 固定リンク
「初音ミク」カテゴリの記事
- MikuMikuTalk ver.0.2.1c(2012.04.20)
- MikuMikuTalk ver.0.2.1(2012.04.13)
- Tda式Appendミク・ver.βのMMM対応パッチ(2012.04.08)
- Tell Your World MMD-PV(2012.04.04)
- Tda式Appendミクさんの物理演算対応(2012.02.22)
この記事へのコメントは終了しました。
コメント