#1 MIDI入力の処理
レガシーなMIDI音源モジュールを作るための下ごしらえとしてArduino用MIDIの入力処理プログラムを書いてみます。動作のためにMIDIインターフェスが必要ですがインターフェースはスイッチサイエンスのMIDIシールドキットを使いました。
このスケッチは2年ほど前に書いたものでMIDIライブラリは使っていません。MIDI規格書にありますMIDI-IN ランニングステータス処理のアルゴリズムをそのままインプリメントしました。今の処システムエクルクルーシブ等は処理せずに捨てる様になっています。
入力されたMIDIメッセージのランニングステータスを個々のフルMIDIメッセージに展開してmidi-in のバッファ mbuff[]へ格納します。mbuffから順繰りにデータを読込んで行って個々のメッセージの処理が出来る様になるはず、です。
この例では確認のためにKeyOnメッセージでLEDオン、KeyOffでLEDオフするようにしました。MIDI-INタイミングでのLED点滅もしてみたのですがアクティブセンシングが頻繁に来るので点滅タイミングは間引きするようにしています。
ちょとあやしいところは、mbuff[]は256バイトのリングバッファで、読出し・格納ポインタとして unsigned char の変数 inpt,outptを使っています。が、outpt=255 の時に a = mbuff[outpt+1] とした場合 a にmbuff[0] が入ってくれるか mbuff[256] が入ってしまうか、、、DOS時代にはこれで問題無く処理してくれましたがもしかしたらバグってるかもしれません。その辺ご注意下さい。
/* -------------------------------
MIDI IN LED Blink
Ringoro
2015/5/12
2017/8/16
--------------------------------- */
unsigned char runsts=0;
unsigned char byt3flg=0;
unsigned char inpt=0;
unsigned char outpt=0;
unsigned char mbuff[256];
unsigned char laston;
void setup() {
// put your setup code here, to run once:
Serial.begin(31250);
runsts=0;
byt3flg=0;
inpt=0;
outpt=0;
pinMode(6, OUTPUT);
pinMode(7, OUTPUT);
// digitalWrite(6,HIGH); // LED LOW Active
// digitalWrite(7,HIGH);
}
void bit71(char); // Bit7 = 1 proc.
void bit70(char); // Bit7 = 0 proc.
/*
* MIDI Running Status Proc.
*
* Apendix-2
* http://amei.or.jp/midistandardcommittee/MIDIspcj.html
*
*
*/
void midi_in_proc(char d)
{
if((d & 0x80)){
bit71(d);
return;
} else {
bit70(d);
}
}
// bit7=1 Status Byte proc
void bit71(char d)
{
if(d>=0xF8){ // do nothing
return;
}
runsts = d;
byt3flg=0;
if(d == 0xF6){ // data push
mbuff[inpt++]=d;
}
else {
// not increment pt
}
}
// Data Byte proc
void bit70(char d)
{
if(byt3flg){
byt3flg=0;
mbuff[inpt+2]=d;
inpt=inpt+3;
return;
}
// else
if(runsts==0){
return; // do nothing
}
if(runsts < 0xC0){
goto proc2;
}
if (runsts<0xE9){
goto proc3;
}
if(runsts < 0xF0){
goto proc2;
}
if(runsts==0xF2){ // song position pt
runsts=0;
goto proc2;
}
if(runsts==0xF3 || runsts == 0xF1){
runsts = 0; // 2bytes Status
goto proc3;
}
// else do nothing
// !! SysExc not proceed. !!
runsts=0;
return;
proc2: // byt 2 of 3-Bytes data proc
byt3flg=1;
mbuff[inpt]=runsts;
mbuff[inpt+1]=d;
// not increment. wait 3byt
return;
proc3: // 2-bytes Status
mbuff[inpt]=runsts;
mbuff[inpt+1]=d;
inpt = inpt+2;
return;
}
void loop() {
// MIDI IN Buffer check
if(inpt == outpt)
return;
if(mbuff[outpt] <= 0x7F){
outpt++;
return;
}
if((mbuff[outpt] & 0xF0)==0x90){
outpt = outpt+2;
if(mbuff[outpt] == 0){
digitalWrite(7, HIGH); // KeyOFF
outpt=outpt+1;
return;
} else {
digitalWrite(7, LOW); // KeyON
outpt = outpt+1;
return;
}
}
if((mbuff[outpt] & 0xF0)==0x80){
digitalWrite(7,HIGH); // KeyOFF
outpt = outpt+3;
return;
}
// else...
outpt++;
}
/*
* When MIDI IN
*/
void serialEvent() {
static int c;
while (Serial.available()) {
// digitalWrite(6, LOW);
// get the new byte:
char c = (char)Serial.read();
midi_in_proc(c);
}
if (c++ & 0x04){
digitalWrite(6, !digitalRead(6));
}
}