« 2007年11月 | トップページ | 2008年1月 »

初音ミクに喋らせてみた(Perl版012)

miku_talk を、バージョンアップしてみました。年末ですから他のフリーソフト作者や職人の方々に遊んでいただこうという趣旨です。
今回の主なバージョンアップ機能は、任意のテキストを入力とできるようにしたことです。

「miku_talk012_1.zip」をダウンロード

以下、Readme.txt からの抜粋です。ちょっとだけインストールについて親切に記載してみました。

miku_talkとは:
 miku_talk は、自然文をもとに「VOCALOID2 初音ミク」の入出力ファイルを生成するソフトウエアです。

 miku_talk はフリーソフトウェアです.GPL(the GNU General Public License),  LGPL(Lesser GNU General Public License), または BSD ライセンスに従って 本ソフトウェアを使用,再配布することができます.  詳細は COPYING, GPL, LGPL, BSD各ファイルを参照して下さい.

動作環境:
 WindowsXP Home での動作を確認しています。UNIX/Linux 上で動作させる場合には、Mecab に入力する文字コードを EUC-JP に変更すれば動作するとおもいますが、未検証です。

インストール方法:
 事前に以下のインストールが必要となります。何れも無償で公開されています。なお、インストールは何れもWindowsXP が前提となっています。Unix/Linux では夫々のOSに適合したインストールをおこなってください。

  ActivePerl 5.8.x
   MeCab-096.exe
  Midi-Perl
   MeCab-Perl-binding

 ・・・・


この miku_talk012.pl を使って、前回のブログを初音ミクに読んでもらいました。ちょっとだけ手で修正したテキストを読ませています。

「test_miku012.mp3」をダウンロード

| | コメント (4) | トラックバック (0)

初音ミクに喋らせてみた(Perl版011)

Perl で漢字仮名混じり文から、VSQファイルを自動生成させてみました。形態素解析にはMecabを使用しています。Mecabは、自然文の読みまでを出力してくれるので、音声合成に楽に適用できます。
ここで、Mecab の設計者およびプログラマの方々に感謝いたします。

ミクに喋らせる文章は、特許法1条 「この法律は、発明の保護及び利用を図ることにより、発明を奨励し、もつて産業の発達に寄与することを目的とする。」 です。

「test_miku011.mp3」をダウンロード

「test_miku011.vsq」をダウンロード

今回は、アクセントっぽいのも入れてあります。あくまでテスト用の仮コーディングであり、標準語のアクセントではありません。

ソースコードはこちらです、UTF8の文字コードでセーブしてください。

#!/Perl
########################################################################
#    miku_talk ver.0.1.1
#
#   Programmed by Akira Izumi
#   Ver.0.0.1:ハードコーディング"みく" ...  6/Dec/2007
#   Ver.0.0.4:任意の平仮名入力を受付ける...15/Dec/2007
#   Ver.0.1.1:ソースをUTF8化し、形態素解析Mecabを組込...26/Dec/2007
#
use MIDI;
use Encode;
use MeCab;
use strict;
use warnings;

# my $myTalk = "発明とは、自然法則を利用した技術的思想の創作のうち高度のものをいう。";
  my $myTalk = "この法律は、発明の保護及び利用を図ることにより、発明を奨励し、もつて産業の発達に寄与することを目的とする。";
  miku_VsqGenerate($myTalk,"test_miku011.vsq");
  exit(0);

########################################################################
#
#   サブルーチン名:miku_VsqGenerate
#
#    日本語文字列からVSQファイルを生成する
#   第1引数:漢字仮名交じりのテキスト文字列
#   第2引数:出力VSQファイル名
#
#
sub miku_VsqGenerate {
my $myTalk  = $_[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",
"ア"=>"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",
#                             "ヴ"=>""p M",
"キャ"=>"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 %phonetic_class = (
"ー"=>"長音",
"-"=>"長音",
"-"=>"長音"
);

#
# ミクの発音用テキストに於ける初期値の設定。
#
  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 $pitch = 180;
  my $note = 64;
  my $myIdPos = 7680;
  my $myIdPosLast = $myIdPos;
  my $myHinsiLast = "";

  Encode::from_to($myTalk,"UTF8","shiftjis");

  my $mecab = MeCab::Tagger->new();
  my $node = $mecab->parseToNode($myTalk);
  for( ; $node; $node = $node->{next} ) {
    next unless defined $node->{surface};
    my $midasi = $node->{surface};
    my( $hinsi, $yomi ) = (split( /,/, $node->{feature} ))[0,8];
    if( $hinsi eq "BOS/EOS" ) {
      next;
    }
print $midasi, "\t<", $yomi, ">\t", $hinsi, "\n";

#
# 文節の区切りを判断して、発音間隔を空ける
# アクセント($note) は仮
#
    Encode::from_to($hinsi,"shiftjis","UTF8");
    if( ( $hinsi eq "名詞" || $hinsi eq "動詞" || $hinsi eq "形容詞" || $hinsi eq "形容動詞" )
    && ($myHinsiLast eq "助詞" || $myHinsiLast eq "接続詞" || $myHinsiLast eq "記号") ) {
      $myIdPos += $pitch;
      $note = 64;
    }
    if( $hinsi eq "記号" ) {
      $note = 64;
    }
    my $idxLyric = 0;
    my $j=0;
    for($j=0; $idxLyric<length($yomi); $j++,$i++) {
      my $myLyricLen = 6;
      my $myLyric = "";
      my $myLyric_utf8 = "";
      my $myPhonetic = "";
      for($myLyricLen=6; $myLyricLen>0; $myLyricLen-=2) {
        $myLyric_utf8 = $myLyric = substr($yomi,$idxLyric,$myLyricLen);
        Encode::from_to($myLyric_utf8,"shiftjis","UTF8");
        $myPhonetic = $phonetic{$myLyric_utf8};
        if( defined($myPhonetic) || $myLyricLen==2 ) {
          last;
        }
      }
      $idxLyric += $myLyricLen;
      my $myLength = $pitch;
      if( $idxLyric + 2 <= length($yomi) ){
        $myLyric_utf8 = substr($yomi,$idxLyric,2);
        Encode::from_to($myLyric_utf8,"shiftjis","UTF8");
        if( $myLyric_utf8 eq "ー" ) {
          $myLength += $pitch;
          $idxLyric += 2;
        }
      }
      if( defined($myPhonetic)) {
        push @myEventListSection, sprintf("%d=ID#%04d",$myIdPos,$i+1);
        push @myIDSection, sprintf("[ID#%04d]",$i+1);
        push @myIDSection, "Type=Anote";
        push @myIDSection, "Length=".$myLength;
        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";
        $myIdPos += $myLength;
#  print "L0=\"".$myLyric."\",\"". $myPhonetic."\",1.000000,64,0,0","\n";
        if( $i==0 ) {
          push @mikuMidiEvents,['control_change', 5760, 0, 99,  80];
        } else {
          push @mikuMidiEvents,['control_change', $myIdPos - $myIdPosLast, 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];
        $myIdPosLast = $myIdPos;
      } else {
        $myIdPos += $myLength;
#  print "No Phonetic\n";
      }
      if($note == 64) {
        $note = 65;
      }
    }
    $myHinsiLast = $hinsi;
  }
  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 );
}

| | コメント (0) | トラックバック (1)

「著作権の効力の制限」を考えてみる #3

こちらの記事を拝見しましたので、この記事をもとに自分なりに著作権法38条についてコメントしてみます。

なんで著作権法38条が話題にのぼらないんだ?
http://anond.hatelabo.jp/20071218190036

ここで、著作権法38条をご紹介します。(法令データ提供システムより)

第三十八条  公表された著作物は、営利を目的とせず、かつ、聴衆又は観衆から料金(いずれの名義をもつてするかを問わず、著作物の提供又は提示につき受ける対価をい う。以下この条において同じ。)を受けない場合には、公に上演し、演奏し、上映し、又は口述することができる。ただし、当該上演、演奏、上映又は口述につ いて実演家又は口述を行う者に対し報酬が支払われる場合は、この限りでない。
 放送される著作物は、営利を目的とせず、かつ、聴衆又は観衆から料金を受けない場合には、有線放送し、又は専ら当該放送に係る放送対象地域にお いて受信されることを目的として自動公衆送信(送信可能化のうち、公衆の用に供されている電気通信回線に接続している自動公衆送信装置に情報を入力するこ とによるものを含む。)を行うことができる。
 放送され、又は有線放送される著作物(放送される著作物が自動公衆送信される場合の当該著作物を含む。)は、営利を目的とせず、かつ、聴衆又は 観衆から料金を受けない場合には、受信装置を用いて公に伝達することができる。通常の家庭用受信装置を用いてする場合も、同様とする。
 公表された著作物(映画の著作物を除く。)は、営利を目的とせず、かつ、その複製物の貸与を受ける者から料金を受けない場合には、その複製物 (映画の著作物において複製されている著作物にあつては、当該映画の著作物の複製物を除く。)の貸与により公衆に提供することができる。
 映画フィルムその他の視聴覚資料を公衆の利用に供することを目的とする視聴覚教育施設その他の施設(営利を目的として設置されているものを除 く。)で政令で定めるものは、公表された映画の著作物を、その複製物の貸与を受ける者から料金を受けない場合には、その複製物の貸与により頒布することが できる。この場合において、当該頒布を行う者は、当該映画の著作物又は当該映画の著作物において複製されている著作物につき第二十六条に規定する権利を有 する者(第二十八条の規定により第二十六条に規定する権利と同一の権利を有する者を含む。)に相当な額の補償金を支払わなければならない。

 非営利目的の実演などの場合には、かなり幅広い著作権の効力の制限が認められていることが判ります。音楽を学ぶという場合には、他人の楽曲をそのまま実演することが多いからです。著作権の効力に制限を加えて、他人の楽曲を練習する機会を与えることは、文化の発展(著作権法1条)に寄与すると思われます。これは丁度、試験または研究には特許権が及ばない(特許法69条)と同様の趣旨です。
 然るに、その他人の著作物(楽曲など)を実演したものを非営利目的でネットワークにアップロードしたらどうなるか。これは自動公衆送信(23条)に該当し、著作権法38条1項の「上演し、演奏し、上映し、又は口述」に該当しないため、少なくとも38条1項の例外規定には含まれません。よって非営利目的であっても著作権が及び、権利者が申し立てたならば差止等を受けることになります。
 しかし、著作権法38条2項には、放送される著作物は非営利目的ならば自動公衆送信により放送できることが記載されていることを鑑みると、他人の著作物の実演かつ非営利目的ならば自動公衆送信することを許して良いようにも思われます。ニコニコ動画などで、視聴者が寄せるコメントが、その実演を更に良いものへとブラッシュアップする役割を果たし、更に良いものを生み出しているからです。これは文化の発展の法目的に寄与すると判断します。
 よって、非営利目的ならば、他人の著作物の実演を公衆送信することに著作権が及ばないよう著作権法が改正されることを期待いたします。

| | コメント (0) | トラックバック (0)

「著作権の効力の制限」を考えてみる #2

法政大学の白田先生が、こちらに面白い記事を書いておられますので紹介します。

もう一つの著作権の話
http://orion.mt.tama.hosei.ac.jp/hideaki/another.htm

 著作権なき時代にも人は創作活動をしていた訳だから、人は必ずしも著作権による著作物の専有を目的として著作物を創作する訳ではないという趣旨の指摘には、思わずはっとしました。それは、自分が何ら金にもならないのに、初音ミクに喋らせるツール miku_talk.pl を作ろうとしている事も同様とおもいます。
 たぶん、自分はリン・レンは買って互換性チェックしたり、リン・レンの読上げツールを作成するとおもいますし、金と時間が許せばMEIKO/KAITO も扱いたいとおもいます。

白田先生のHPはこちらですね。

Research Papers of Hideaki Shirata
http://orion.mt.tama.hosei.ac.jp/hideaki/indexj.htm

こういう頁もあったりします。

Thanksgiving Day
http://orion.mt.tama.hosei.ac.jp/hideaki/thanksgiving.htm

| | コメント (0) | トラックバック (0)

「著作権の効力の制限」を考えてみる

著作権法は著作者保護を目的とする法律ではありません。目的は「文化の発展」であり(著作権法1条)、その目的を達するために第5款で、著作権の効力の制限が記載されています。

30条:私的使用のための複製
31条:図書館等における複製
32条:引用
33条:教科書図書等への複製
33条の2:教科用拡大図書等の作成のための複製
34条:学校教育番組の放送等
35条:学校その他の教育機関における複製等
36条:試験問題としての複製等
37条:点字による複製等
37条の2:聴覚障害者のための自動公衆送信
38条:営利を目的としない上演等
39条:時事問題に関する論説の転載等
40条:政治上の演説等の利用
41条:時事の事件の報道のための利用
42条:裁判手続等における複製
42条の2:行政機関情報公開法等による開示のための利用
43条:翻訳、翻案による利用
44条:放送事業者等による一時的固定
45条:美術の著作物等の原作品の所有者による展示
46条:公開の美術の著作物等の利用
47条:美術の著作物等の展示に伴う複製
47条の2:プログラムの著作物の複製物の所有者による複製等
47条の3:複製権の制限により作成された複製物の譲渡

公開の美術の著作物等については、利用又は二次利用することができます。(46条)公開された美術作品の利用が著作権により制約されるとするならば、新た著作活動を阻害し、文化の発展に寄与しなくなる恐れがあるためです。

 

(公開の美術の著作物等の利用)

第四十六条  美術の著作物でその原作品が前条第二項に規定する屋外の場所に恒常的に設置されているもの又は建築の著作物は、次に掲げる場合を除き、いずれの方法によるかを問わず、利用することができる。
 彫刻を増製し、又はその増製物の譲渡により公衆に提供する場合
 建築の著作物を建築により複製し、又はその複製物の譲渡により公衆に提供する場合
 前条第二項に規定する屋外の場所に恒常的に設置するために複製する場合
 専ら美術の著作物の複製物の販売を目的として複製し、又はその複製物を販売する場合

ここでいう「前条第二項に規定する屋外の場所」とは、街路、公園その他一般公衆に開放されている屋外の場所又は建造物の外壁その他一般公衆の見やすい屋外の場所をいいます。(著作権法45条2項)

著作権法46条に規定されているのは、美術の著作物で、原作品が45条2項に規定する屋外の場所に恒常的に設置されているものと、建築の著作物に限定されています。
しかし、46条の趣旨から、音楽の著作物で恒常的にインターネットで一般公衆に公開されているものは、自由に利用可能とする事が文化の発展に寄与すると判断します。

ニコニコ動画へのアップロードが、「一般公衆に公開」に該当するかは議論の余地があります。ニコニコ動画は登録ユーザーのみに公開されたシステムだからです。自分は、メールアカウントの登録のみで一般会員になれるという緩い制限しかないため、ニコニコ動画は「一般公衆に公開」にあたると解釈いたします。

将来的にはインターネットで一般公衆に公開された音楽の著作物は、少なくとも一般公衆に公開されつづけている限りにおいて、自由に利用可能とするように法改正がなされる事を希望いたします。

| | コメント (0) | トラックバック (0)

初音ミク関連ソフトウエア・リンク集

Vocalips を作られたzhuoさんが、初音ミク関連ソフトウエア・リンク集を作成いただきました、当該ブログにもリンクを貼っていただき、ありがとうございます。>zhuoさん。

Software Study Notes
http://www.geocities.jp/zhuoware/software_study.html

VOCALOID2 には、まだまだ色々な周辺ソフトウエアが出てくる余地があると思います。初音ミク VOCALOID2 はいわば、「音声合成ソフトウエアのアセンブラ」であり、時間を労力を膨大に費やして、やっと人前に出せる作品ができるという代物ですが、もっと直感的に簡単に楽しくVOCALOIDで音楽が作れるようになれば、世の中を変えるムーブメントすら起こせるかもしれない。そんな可能性を垣間見せてくれる商品です。

また、十数年もの長きにわたりYAMAHAが挑戦してきた音声合成技術が、研究と商品化の間に横たわる「死の谷」を超えて、商品として羽ばたきつつあるのが興味深いです。

| | コメント (0) | トラックバック (0)

「みくみくにしてあげる♪」がJASRAC信託に

 初音ミク・オリジナル曲「みくみくにしてあげる♪」は、先週JASRAC信託となりました。ということは、当該ブログで紹介しているyoutubeのリンクはブログ内のウインドウで再生されることにより、当該ブログがストリーム配信を行っていると解される恐れがあります。これは公衆送信権(著作権23条)の侵害を構成していると解される恐れを有することと同一です。対策として、「みくみくにしてあげる♪」を含め、youtube にリンクしている初音ミク・オリジナル曲のハイパーリンクは全て削除しました。今後、他のオリジナル曲がJASRAC管理下になった場合に備えてです。
 ニコニコ動画のリンクは消していません。ニコニコ動画の場合には別ウインドウが開くため当該ブログは引用(著作権32条)しているに過ぎず、ストリーム配信に該当しないと解される事と、ドワンゴは「みくみくにしてあげる♪」の公衆送信権を有しているのではないかと思われるからです。
 詳しくは、この週末にJASRAC規約を読んで判断したいと思います。

 無事に弁理士登録を終わりましたので、会社で「弁理士」と呼ばれるのですが、まだなんとなくしっくりとこないです。某所で呼ばれた「アキバ系弁理士」という呼称が妙に気に入ったので、ブログのサブタイトルを併せて変更します。

| | コメント (0) | トラックバック (0)

melody...3D PV ver1.50

初音ミクの3Dモデリングを用いたオリジナル曲のプロモーションビデオ(PV)は幾つかありますが、あまりにも演出の出来が良すぎるので備忘録としてリンクを貼ります。

コメントの数が再生数より多いのも特筆ものです、いま現在で再生3239、コメント3366です。

| | コメント (0) | トラックバック (0)

初音ミクに喋らせてみた(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 );
}

| | コメント (0) | トラックバック (0)

CVシリーズ Vocal CD Volume 01 星のカケラ

「初音ミク」の公認デビューCDが発売されるようですね。広告リンクはこちらです。

CVシリーズ Vocal CD Volume 01 星のカケラ/初音ミク
http://www.animate.tv/pv/detail.php?id=pcd071211a
発売日:2008/1/25
価格:2,000円(税込)
発売元:株式会社フロンティアワークス

 最初のフレーズのみのサンプル音声を視聴すると、流石と思わせる出来栄えでした。恐らく購入する事になると思います。
 他に収録されることになる「納得のカバーソング」ってどんな曲でしょう。「奇跡の海」とかだったらちょっと面白いんですけれど。

| | コメント (0) | トラックバック (0)

社内弁理士の飲み会

 今日は、平成19年度弁理士試験合格者の祝賀会という名目での、社内弁理士が集まっての飲み会です。自分は半分くらいの方しか面識がなかったので、全員の方と知り合えたのは良かったです。
 今年の合格者は自分と、もうお一方おられました。その方から試験にまつわる恐ろしい話をお聞きしました。

その1 「1枚目の特実Ⅰだけ解いて、2枚目の特実Ⅱの問題の存在を知らず、全く解いていなかった人」(例年は特実の問題は1枚だけなので、1枚目だけ解いて安心してしまったそうです) 
その2 「特実の問題が終わったあと、トイレの前のベンチで仰向けに倒れていて、特許庁の試験官に『大丈夫ですか』とゆすぶられていた人」とか、

まあ、恐ろしい話はこのくらいにしておきます。

 もう一人の合格者の方は、2年間帰っていなかった実家に帰って挨拶し、2年前に封印したビデオゲーム(ドラゴンクエスト)を今まさにやっているそうです。
 自分は今でも空き時間は落ち着かず、定義趣旨をノートに走り書きしたりしていますが、そろそろ受験時代の垢を流してさっぱりして、新たに有意義なことをしなければと考えています。やっぱ初音ミク用フリーソフトでも作ってVector に流すしかないかな?(笑)
 自分は侵害訴訟代理試験にも挑戦したいと思っています。幸いなことに、社内弁理士のうち、今年に受験された方が何人かいらっしゃいますので、心強いです。

| | コメント (0) | トラックバック (0)

サクラサク

 無事に弁理士試験に合格したので、ブログテンプレートを「もみじ」に変更してみました。季節はもう秋から冬になろうとする頃ですから、季節に合わせてということもあります。
 今までは「春の窓辺」という名前のブログテンプレートでした。桜が咲いてる絵柄のテンプレートなんて受験生が縁起担ぎにはぴったりと思って貼ったものです、うちの奥さんに「なんだか女の子のブログみたいだね」とからかわれていましたが、合格するまではと思い、あえて変えませんでした。考えてみればもう合格した訳だから、もうテンプレートを替えてもいい頃です。
 昨日は同じゼミに通っていた仲間たちに合格祝賀会をしてもらいました。せめてものお返しに、「論文合格したら、口述練習会をやろうぜ。」自分の連絡先を書いた自作名刺を配ってきました。彼等は自分の一年前と比べ物にならないくらいの高得点を叩き出しているようで、何人が来年度の論文式筆記試験を突破できるか楽しみです。祝賀会の席で「来年度の論文式筆記試験予測」も大胆におこないましたが、うまく当たるかな。予測はあえてここには書きません。予測が著名になると特許庁が自らの意思で回避しますからね。(笑)
 来年度の論文式筆記試験に合格して、連絡してくれるゼミ仲間たちが一人でも多くいることを期待しています。

| | コメント (3) | トラックバック (0)

初音ミクに喋らせてみた(Perl版)

まだ、ハードコーディング段階ですが、とりあえず Perl スクリプトで .VSQ を自動生成してみました。
必要なものは ActivePerl 5.8.8 と MIDI-Perlだけです。ActivePerl をインストールしたのち、ppm-shell を起動して MIDI-Perl をインストールしてください。

 こちらが、「みく」と喋るVSQファイルを生成する Perlスクリプトです。
 「miku_talk001.zip」をダウンロード

 こちらが、その生成されたVSQファイルです。
 「test_miku.zip」をダウンロード

流石に「みく」の決めうちじゃあさびしいので、せめて任意の平仮名入力をVSQ変換したいと思い、VOCALOID2 の平仮名→発音記号テーブルをちょっと見てみたら、世の中にはもう調べ終わっている人がいるものですね。こちらの方です。

初心者になるための耳コピMIDI講座 マニュアル (VSTi)
VOCALOID2 Domino 定義ファイル
http://mimikopi.nomaki.jp/domino/vocaloid2/manual/index.html#HEADER

恥を忍んでソースをご紹介します。いや・・・、今日1時間ほどで作ったものなんで汚いのはご容赦ください。

#!/Perl
#
#  miku_talk ver.0.0.1
#
#  Programmed by Akira Izumi 6/Dec/2007
#
use MIDI;
use strict;
use warnings;

my $myTalk = "みく";
my $miku_talk_metatext = miku_phonetics($myTalk);

my @masterEvents = (
  ['text_event',    0, 'Master Track'],
  ['set_tempo',     0, 500_000], # 1qn = .50 seconds
  ['time_signature',0,4,2,24,8 ],
  ['end_track' ,    0],
);

  my @voice1Events = (
    ['text_event',    0, 'Voice1'],
  );
  my $i=0;
  for($i=0; $i*119<length($miku_talk_metatext); $i++) {
    push @voice1Events, ['text_event', 0, sprintf("DM:%04d:",$i).substr($miku_talk_metatext,$i*119,119) ];
  }
  push @voice1Events,['control_change' , 0, 0,  99, 96];
  push @voice1Events,['control_change' , 0, 0,  98,  0];
  push @voice1Events,['control_change' , 0, 0,   6,  0];
  push @voice1Events,['control_change' , 0, 0,  38,  0];
  push @voice1Events,['control_change' , 0, 0,  98,  1];
  push @voice1Events,['control_change' , 0, 0,   6,  0];
  push @voice1Events,['control_change' , 0, 0,  38,  0];
  push @voice1Events,['control_change' , 0, 0,  98,  2];
  push @voice1Events,['control_change' , 0, 0,   6,  0];
  push @voice1Events,['control_change' , 0, 0,  99, 83];
  push @voice1Events,['control_change' , 0, 0,  98,  2];
  push @voice1Events,['control_change' , 0, 0,   6,  0];

  push @voice1Events,['control_change', 5760, 0, 99,  80];
  push @voice1Events,['control_change', 0, 0, 98,   0];
  push @voice1Events,['control_change', 0, 0,  6,   0];
  push @voice1Events,['control_change', 0, 0, 38,   0];
  push @voice1Events,['control_change', 0, 0, 98,   1];
  push @voice1Events,['control_change', 0, 0,  6,  15];
  push @voice1Events,['control_change', 0, 0, 38,  80];
  push @voice1Events,['control_change', 0, 0, 98,   2];
  push @voice1Events,['control_change', 0, 0,  6,  64];
  push @voice1Events,['control_change', 0, 0, 98,   3];
  push @voice1Events,['control_change', 0, 0,  6,  64];
  push @voice1Events,['control_change', 0, 0, 98,   4];
  push @voice1Events,['control_change', 0, 0,  6,   1];
  push @voice1Events,['control_change', 0, 0, 38, 122];
  push @voice1Events,['control_change', 0, 0, 98,   5];
  push @voice1Events,['control_change', 0, 0,  6,   1];
  push @voice1Events,['control_change', 0, 0, 98,  18];
  push @voice1Events,['control_change', 0, 0,  6,   3];
  push @voice1Events,['control_change', 0, 0, 98,  19];
  push @voice1Events,['control_change', 0, 0,  6, 109];
  push @voice1Events,['control_change', 0, 0, 38,  64];
  push @voice1Events,['control_change', 0, 0, 98,  20];
  push @voice1Events,['control_change', 0, 0,  6,  39];
  push @voice1Events,['control_change', 0, 0, 98,  21];
  push @voice1Events,['control_change', 0, 0,  6, 105];
  push @voice1Events,['control_change', 0, 0, 38,   0];
  push @voice1Events,['control_change', 0, 0, 98,  79];
  push @voice1Events,['control_change', 0, 0,  6, 127];
  push @voice1Events,['control_change', 0, 0, 98,  80];
  push @voice1Events,['control_change', 0, 0, 6,   12];
  push @voice1Events,['control_change', 0, 0, 98,  81];
  push @voice1Events,['control_change', 0, 0,  6,   8];
  push @voice1Events,['control_change', 0, 0, 98,  82];
  push @voice1Events,['control_change', 0, 0,  6,  20];
  push @voice1Events,['control_change', 0, 0, 98,  83];
  push @voice1Events,['control_change', 0, 0,  6,  28];
  push @voice1Events,['control_change', 0, 0, 98,  84];
  push @voice1Events,['control_change', 0, 0,  6,  24];
  push @voice1Events,['control_change', 0, 0, 98,  85];
  push @voice1Events,['control_change', 0, 0,  6,  10];
  push @voice1Events,['control_change', 0, 0, 98,  86];
  push @voice1Events,['control_change', 0, 0,  6,  12];
  push @voice1Events,['control_change', 0, 0, 98,  87];
  push @voice1Events,['control_change', 0, 0,  6,  12];
  push @voice1Events,['control_change', 0, 0, 98,  88];
  push @voice1Events,['control_change', 0, 0,  6,   0];
  push @voice1Events,['control_change', 0, 0, 98,  89];
  push @voice1Events,['control_change', 0, 0,  6,  50];
  push @voice1Events,['control_change', 0, 0, 98,  90];
  push @voice1Events,['control_change', 0, 0,  6,  50];
  push @voice1Events,['control_change', 0, 0, 98, 127];
  push @voice1Events,['control_change', 0, 0,  6, 127];

  push @voice1Events,['end_track' , 2160];

  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( 'test_miku.vsq' );
  exit(0);
#-----------------------------------------------------------------------
#
#  ミクの発音用メタテキスト
#
sub miku_phonetics {

my @myPhonetics=();

  push @myPhonetics, "[Common]";
  push @myPhonetics, "Version=DSB301";
push @myPhonetics, "Name=Voice1";
push @myPhonetics, "Color=181,162,123";
push @myPhonetics, "DynamicsMode=1";
push @myPhonetics, "PlayMode=1";

push @myPhonetics, "[Master]";
push @myPhonetics, "PreMeasure=4";

push @myPhonetics, "[Mixer]";
push @myPhonetics, "MasterFeder=0";
push @myPhonetics, "MasterPanpot=0";
push @myPhonetics, "MasterMute=0";
push @myPhonetics, "OutputMode=0";
push @myPhonetics, "Tracks=1";
push @myPhonetics, "Feder0=0";
push @myPhonetics, "Panpot0=0";
push @myPhonetics, "Mute0=0";
push @myPhonetics, "Solo0=0";

push @myPhonetics, "[EventList]";
push @myPhonetics, "0=ID#0000";
push @myPhonetics, "7680=ID#0001";
push @myPhonetics, "7920=ID#0002";
push @myPhonetics, "8160=EOS";

push @myPhonetics, "[ID#0000]";
push @myPhonetics, "Type=Singer";
push @myPhonetics, "IconHandle=h#0000";

push @myPhonetics, "[ID#0001]";
push @myPhonetics, "Type=Anote";
push @myPhonetics, "Length=240";
push @myPhonetics, "Note#=64";
push @myPhonetics, "Dynamics=64";
push @myPhonetics, "PMBendDepth=20";
push @myPhonetics, "PMBendLength=0";
push @myPhonetics, "PMbPortamentoUse=0";
push @myPhonetics, "DEMdecGainRate=50";
push @myPhonetics, "DEMaccent=50";
push @myPhonetics, "LyricHandle=h#0001";

push @myPhonetics, "[ID#0002]";
push @myPhonetics, "Type=Anote";
push @myPhonetics, "Length=240";
push @myPhonetics, "Note#=64";
push @myPhonetics, "Dynamics=64";
push @myPhonetics, "PMBendDepth=20";
push @myPhonetics, "PMBendLength=0";
push @myPhonetics, "PMbPortamentoUse=0";
push @myPhonetics, "DEMdecGainRate=50";
push @myPhonetics, "DEMaccent=50";
push @myPhonetics, "LyricHandle=h#0002";

push @myPhonetics, "[h#0000]";
push @myPhonetics, "IconID=\$07010000";
push @myPhonetics, "IDS=Miku";
push @myPhonetics, "Original=0";
push @myPhonetics, "Caption=";
push @myPhonetics, "Length=1";
push @myPhonetics, "Language=0";
push @myPhonetics, "Program=0";

push @myPhonetics, "[h#0001]";
push @myPhonetics, "L0=\"み\",\"m' i\",1.000000,64,0,0";

  push @myPhonetics, "[h#0002]";
  push @myPhonetics, "L0=\"く\",\"k M\",1.000000,64,0,0";

  my $my_miku_phonetics="";
  my $phonetic = "";
  foreach $phonetic (@myPhonetics) {
    $my_miku_phonetics = $my_miku_phonetics.$phonetic."\n";
  }
  return $my_miku_phonetics;
}


| | コメント (2) | トラックバック (1)

CV02「鏡音リン・レン」

大手広告代理店のティザー広告も顔負け!

DTMマガジン12月号(11月8日)にCV02 鏡音リンの画像を発表すると同時に、メディアファージ事業部ブログでも発表、鏡音リンのネタで一通り盛り上がったところで、いきなり「実は双子です。男女の声でボーカドイロ2が使えます!」

 [VOCALOID2情報] CV02「鏡音リン・レン」公開
 http://blog.crypton.co.jp/mp/2007/12/vocaloid2_cv02_3.html

 クリプトン VOCALOID2特集 鏡音リン・レン(カガミネ リン・レン) 紹介ページ更新
 http://www.crypton.co.jp/mp/pages/prod/vocaloid/cv02.jsp

この展開を考えた人(恐らくCrypton社のwatさんと思いますが、)は天才的なプロモーターと思います。自分はCV02は買わないと決めていましたが、その決心は相当ぐらついています。

ところで、CV02を買うその前に、Midi::Perl の仕様書をちゃんと読みこなさないといけませんね。(笑)

| | コメント (0) | トラックバック (0)

VOCALOIDのデータ形式

ここにも、VOCALOID2 Editor のデータ形式をチェックされている方がおられました。

VOCALOID MIDI 形式
http://cancoffee2.at.webry.info/200711/article_8.html

今日はMecabのインストールでちょと苦労しました。
Yahoo! の形態素解析WEB-APIは「プライベート文書」を変換するには危険すぎますので、MeCabという名の形態素解析エンジンをインストールしました。お約束の特許法2条1項の文章を解析した結果は以下のものです。

発明    名詞,サ変接続,*,*,*,*,発明,ハツメイ,ハツメイ
と    助詞,格助詞,引用,*,*,*,と,ト,ト
は    助詞,係助詞,*,*,*,*,は,ハ,ワ
、    記号,読点,*,*,*,*,、,、,、
自然    名詞,形容動詞語幹,*,*,*,*,自然,シゼン,シゼン
法則    名詞,一般,*,*,*,*,法則,ホウソク,ホーソク
を    助詞,格助詞,一般,*,*,*,を,ヲ,ヲ
利用    名詞,サ変接続,*,*,*,*,利用,リヨウ,リヨー
し    動詞,自立,*,*,サ変・スル,連用形,する,シ,シ
た    助動詞,*,*,*,特殊・タ,基本形,た,タ,タ
技術    名詞,一般,*,*,*,*,技術,ギジュツ,ギジュツ
的    名詞,接尾,形容動詞語幹,*,*,*,的,テキ,テキ
思想    名詞,一般,*,*,*,*,思想,シソウ,シソー
の    助詞,連体化,*,*,*,*,の,ノ,ノ
創作    名詞,サ変接続,*,*,*,*,創作,ソウサク,ソーサク
の    助詞,連体化,*,*,*,*,の,ノ,ノ
うち    名詞,非自立,副詞可能,*,*,*,うち,ウチ,ウチ
高度    名詞,形容動詞語幹,*,*,*,*,高度,コウド,コード
な    助動詞,*,*,*,特殊・ダ,体言接続,だ,ナ,ナ
もの    名詞,非自立,一般,*,*,*,もの,モノ,モノ
を    助詞,格助詞,一般,*,*,*,を,ヲ,ヲ
いう    動詞,自立,*,*,五段・ワ行促音便,基本形,いう,イウ,イウ
。    記号,句点,*,*,*,*,。,。,。

その後、MecabをPerl から呼び出す為の Perl-binding をインストールしようとしたら、UNIXが前提になっているらしくて一苦労でしたが、ppm モジュールを公開されている方がおられましたので、そちらからインストールすることで無事に動作するようになりました。
こちらの方です。
http://namazu.asablo.jp/blog/2007/06/28/1611341

Mecab Perl-binding PPMモジュールのインストール方法は以下のものです。

C:\> ppm uninstall MeCab
C:\> ppm install http://www.akaneiro.jp/PPMPackages/800/MeCab.ppd

| | コメント (0) | トラックバック (0)

« 2007年11月 | トップページ | 2008年1月 »