主にandroidとかのメモ

eVY1 shieldとMIDI shieldで楽器化テスト

YAMAHAのボーカロイドチップNSX-1にVY1簡易版歌声データを載せたっぽい、ボカロシールドが発売されたので実験用に購入。

http://www.switch-science.com/catalog/1490/

USBでPCと繋ぐとUSB-MIDIとして認識。PCでMIDIファイルを再生するだけで遊ぶことが出来ます。Arduinoなくても遊べますね。
(Win7やVistaだとMIDIマッパーが切り替えできなくなってるので、MIDISelectionとか切り替えるツール使ってください)

■サンプルMIDIデータ

サンプルの故郷(ふるさと)のMIDIデータが凄く良い出来でびっくり。これは一見(一聴)の価値ありです。

こんな小さいボードで、MIDI音源(YAMAHA XG音源)で楽器鳴らすのと、歌声を同時に鳴らせている事に衝撃。
サンプル曲、歌声が和音に聞こえるような(2音同時発声できるとは思えないしエフェクターなのかな)

この衝撃は、PC-98で86ボードってサウンドボード出て、PCMで声なった!なんだこれ!?ってなったの思い出しました。

XG音源はまあこのサイズでの合成なので期待してませんでしたが、クソと評判のWindows標準「Microsoft GS Wavetable Synth」より断然良い音をしています。(でも若干音色にもよる)

MIDIデータに歌詞埋め込まれてますが、結果から言うとSysEx(システムエクスクルーシブ)なので、他の楽器では無視されて普通に再生できます。

■arduino用のサンプルコード

かえるのうたを歌うサンプルコード。

・歌詞を送って、MIDIで音符を再生すると、その音階で歌ってくれる感じ。
・通信は31250bpsなのでいわゆるMIDIそのまま
・音鳴らす時はMIDIのNote ONメッセージ(鍵盤押した)コマンド3byte送ってる
・歌詞は0xf0で始まって0xf7で終わるSysExメッセージ。発音を文字列で送るけど単なるローマ字ではない部分ある。ボカロ触った事ないからよく分からない。

つまり完全にMIDIじゃねーの

音階部分はMML(ドレミファをCDEFって書くやつ)だったけど、完全に手抜きだったので・・・
(サンプルが複雑にならないようにだと思うけど)
過去何度も作ったので時間あれば移植したい

■eVY1 shield + MIDI shild

そういえばMIDI-IFのシールド買ってたなーと載せてみた。

arduinoにeVY1シールド載せてその上にMIDIシールドの3段構成。

元のサンプルはシリアル通信でeVY1とやり取りしてるが、MIDIシールドが使っちゃうので、ソフトウェアシリアル使うように変更。
(eVY1シールド上のジャンパでソフトウェアシリアルにピン変更できるようになってます)

でハードシリアルから入った31250bpsデータをそのままソフトウェアシリアルに1バイトずつ流しだすだけで完成。

歌詞をソース直に書いてるので、楽器としてはイマイチ。
「ラ~」固定にしたら汎用性ありそうだけど面白くなかった。

音声入力などでサッと歌詞登録して、すぐ鍵盤演奏するくらいじゃないと使い物にはならない感

ソースはこんな感じ

#include <avr/pgmspace.h>
#include <SoftwareSerial.h>

/*
 * 注意:
 * SoftwareSerial使用の為eYV1shieldのJP2を2-3に変更する事
 */

int led = 13;
//SW-Serial: eVY1 shield
SoftwareSerial swSerial(2, 3);

void setup() {

  // initialize the digital pin as an output.
  pinMode(led, OUTPUT);
  //  Set MIDI baud rate:
  swSerial.begin(31250);
  // HW-Serial: MIDI-IN
  Serial.begin(31250);
  delay(5000);
  set_lylic();

}

//変更しない
const char* phoneticSymbols[] = {
	"a", "i", "M", "e", "o",		// あいうえお0-4
	"k a", "k' i", "k M", "k e", "k o",	// かきくけこ5-9
	"s a", "S i", "s M", "s e", "s o", // さしすえそ10-14
	"t a", "tS i", "ts M", "t e", "t o",	// たちつてと15-19
	"n a", "J i", "n M", "n e", "n o",	//なにぬねの20-24
	"h a", "C i", "p\\ M", "h e", "h o",	// はひふへほ25-29
	"m a", "m' i", "m M", "m e", "m o", // まみむめも30-34
	"j a","i", "j M","e","j o",//やいゆえよ35-39
	"4 a", "4' i", "4 M", "4 e", "4 o", // らりるれろ40-44
	"w a","w o","N\\","","",// わをん 45-49
	"g a", "g' i", "g M", "g e", "g o",//がぎぐげご 50-54
	"dz a", "dZ i", "dz M", "dz e", "dz o",//ざじずぜぞ55-59
	"d a", "dZ i", "dz M", "d e", "d o",//だじづでど60-64
	"b a", "b' i", "b M", "b e", "b o",//ばびぶべぼ	65-69
        "p a", "p' i", "p M", "p e", "p o"//ぱぴぷぺぽ70-74
};

//歌詞
//int lylics[]={40}; //”ら”固定
int lylics[]={52,44,4,4,4,4,4, 4,4,4,4,4, 4,4,4,4,4, 41,0
              ,1,47, 3,7, 11,3,42, 11,12, 63,4
             ,52,44,4,4,4,4,4, 4,4,4,4,4, 4,4,4,4,4, 41,0
              ,1,47, 3,7, 11,3,42, 11,12, 63,3,4       };//あめのみつかいの

void loop(){

  //シリアル受信処理
  while(Serial.available()>0){
    swSerial.write((byte)Serial.read());//そのまま転送出力
  }

}

void set_lylic() {
  int lylic_len = sizeof(lylics) / sizeof(lylics[0]);
  lylic_send(lylic_len);
}

//lylic send
void lylic_send(int num){
  //hedaer
  swSerial.write((byte)0xF0);
  swSerial.write((byte)0x43);
  swSerial.write((byte)0x79);
  swSerial.write((byte)0x09);
  swSerial.write((byte)0x00);
  swSerial.write((byte)0x50);
  swSerial.write((byte)0x10);

  for(int i=0;i<num;i++){
    if(i != 0) swSerial.write((byte)0x2c);
    swSerial.write(phoneticSymbols[lylics[i]]);
  }
  //footer
  swSerial.write((byte)0x00);
  swSerial.write((byte)0xF7);

}