みなさん、こんにちは。
新しい物好き一階です。
 
ざっと調べた限りArudinoとWebAudioApiのサンプルはあれどWindowsC++ or C#のサンプルがありませんでした。これも時代の流れかなぁと寂しく思いつつ、WindowsのC++でプログラミング開始。
1.まずはお勉強
実はMIDIデータは作ったり再生した事はあるものの、プログラム上から命令を出したことがないので、まずはMIDIのフォーマットやWin32APIの使い方を勉強。
※.net FrameworkにはMIDI制御用の機能がないのでWin32APIを利用しています。
このサイトやこのサイトを参考にしました。
 
2.eVY1の使い方
eVY1では事前に歌詞をエクスクルーシブメッセージでデバイスに送信しておくと、音をならす度に歌詞を1文字ずつ音に合わせて発生してくれる。
なのでプログラム的には以下のような流れになる。
MIDIデバイスOpen⇒エクスクルーシブメッセージ送信⇒音を鳴らす⇒MIDIデバイスクローズ
 
3.まずは音を鳴らす
| 
					 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33  | 
						// ライブラリの使用宣言 #pragma comment (lib, "winmm.lib") int PlayMidi() { 	// MIDIデバイス取得 	HMIDIOUT hMidiOut; 	if ( midiOutOpen( (LPHMIDIOUT)&hMidiOut, 1, (DWORD_PTR)NULL, (DWORD_PTR)0, CALLBACK_NULL ) != MMSYSERR_NOERROR ) 	{ 		// MIDIデバイスがない。 		return 1; 	} 	// 送信準備 	midiOutShortMsg(hMidiOut, 0x000000c0); 	Sleep(100); 	// ド 	midiOutShortMsg(hMidiOut, 0x00403c90); 	Sleep(1000); 	midiOutShortMsg(hMidiOut, 0x00003c90); 	// レ 	midiOutShortMsg(hMidiOut, 0x00403e90); 	Sleep(1000); 	midiOutShortMsg(hMidiOut, 0x00003e90); 	// MIDIデバイス解放 	midiOutReset(hMidiOut); 	midiOutClose(hMidiOut); 	return 0; }  | 
					
※midiOutOpenの第2引数は自分の環境に合わせて変えてください。
デフォルトで”あ”が設定されているみたいなので、このプログラムを実行すると”ド”と”レ”を、あ↑あ↑と歌ってくれます。
無事音が出たので次は「さくらさくら」を歌わせてみます。
 
[歌っている動画]
 
4.歌詞の送信データの中身
歌詞はASCIIコードで送信するので、どの文字がどういうコードで構成されているかをYAMAHAのマニュアルページの一番下からMIDI仕様書をダウンロードして確認する。(今日現在だと34ページに該当情報が記載されている)
 
5.エクスクルーシブメッセージの送信
下記ロジックをその1の送信準備の直前に入れると、歌詞が”あ”から”き”に変更されることが確認できる。
| 
					 1 2 3 4 5 6 7 8 9 10 11 12 13 14  | 
						MIDIHDR mhMidi; ZeroMemory(&mhMidi, sizeof(mhMidi)); // 歌詞データ BYTE vocalData[] = {0xF0, 0x43, 0x79, 0x09, 0x00, 0x50, 0x10, 0x6B, 0x27, 0x20, 0x69, 0x00, 0xF7 }; mhMidi.lpData = (LPSTR)vocalData; mhMidi.dwBufferLength = 13; mhMidi.dwBytesRecorded = 13; midiOutPrepareHeader(hMidiOut, &mhMidi, sizeof(mhMidi)); midiOutLongMsg(hMidiOut, &mhMidi, sizeof(mhMidi)); while ((mhMidi.dwFlags & MHDR_DONE) == 0); midiOutUnprepareHeader(hMidiOut, &mhMidi, sizeof(mhMidi));  | 
					
 
6.歌詞データの作成
特にプログラム上で動的に変更しないのならばここの歌唱データ変換ツールを使うと便利。
0x付加&SysExで作成した文字をカンマ区切りで上記ロジックの”BYTE vocalData[]”に入れれば歌詞が入れ替わる。
 
プログラムで生成する場合は以下(大分手抜きですが)。
[変換部分]
| 
					 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30  | 
						void WordStringToByte( char* wordData, BYTE* byteWord ) { 	// ヘッダ情報 	byteWord[0] = 0xF0; 	byteWord[1] = 0x43; 	byteWord[2] = 0x79; 	byteWord[3] = 0x09; 	byteWord[4] = 0x00; 	byteWord[5] = 0x50; 	byteWord[6] = 0x10; 	// 歌詞情報 	int j = 0; 	int length = strlen( wordData ); 	for( int i = 7; i < length+7; i++ ) 	{ 		byteWord[i] = (int)(unsigned char)wordData[j]; 		j++; 		if( j == length ) 		{ 			break; 		} 	} 	// 終了情報 	byteWord[length+7] = 0x00; 	byteWord[length+8] = 0xF7; 	return; }  | 
					
[呼び出し元]
| 
					 1 2 3 4  | 
						// 歌詞を"ふぁ"と"ずぃ"に設定。歌詞の連結は"," wordData = "p\ a,dz i"; BYTE byteWord[255]; WordStringToByte( wordData, byteWord );  | 
					
[エクスクルーシブメッセージ設定部分]
| 
					 1 2 3 4 5 6 7 8  | 
						/* mhMidi.lpData = (LPSTR)vocalData; mhMidi.dwBufferLength = 13; mhMidi.dwBytesRecorded = 13; */ mhMidi.lpData = (LPSTR)byteWord; mhMidi.dwBufferLength = strlen( wordData )+9; mhMidi.dwBytesRecorded = strlen( wordData )+9;  | 
					
次はこれをKinectかPerCあたりと組み合わせてみます。
