Arduino互換テストボードのMaruduinoでMIDI演奏にチャレンジ [ATmarquino Arduino]
※著作権表記及び署名の改竄以外はご自由にお使いください。
※ところでヘッダー情報の4分音符の分解能とデルタタイムを使っての時間指定の計算ってどうすればいいのでしょう?。
※デルタタイムを引数としてdelay関数を使って次のイベントまでの待ち時間を生成していますが、この為delayの引数の時間とそれ以外の処理時間の累積となって、実はテンポがいい加減です。さて、どうしたものかね。
※スケッチ改良しました。多分大体テンポは合っているかと思う。
前からMIDIをやってみたいとは思っていたんです。
ただMIDIに関すると言うか音楽全般に関する知識は皆無、音符とか読めませんし、そんな状態なので結構苦労しています。Arduinoの例題をベースにスケッチを書いてみましたが、まだまだバグバグで、しかも複数トラックを持つフォーマットには対応していません。
ですが、楽器を鳴らせるのは楽しいですな。
現状はキーを押すとMIDI出力するとかそう言ったものではなく、MIDIファイルをROM化して、それを流しています。
本当はMIDIファイルをそのまま垂れ流す程度で済むかと思っていましたが、そうではないんですね。データを送るタイミングとかはこちらでコントロールする必要が有るみたい。
あ、ちなみに物理的な接続はやけに簡単です。
スケッチとバイナリーデータをCソースに変換するプログラムも一応。
※MIDIのフォーマット0のみに対応
※ところでヘッダー情報の4分音符の分解能とデルタタイムを使っての時間指定の計算ってどうすればいいのでしょう?。
※デルタタイムを引数としてdelay関数を使って次のイベントまでの待ち時間を生成していますが、この為delayの引数の時間とそれ以外の処理時間の累積となって、
※スケッチ改良しました。多分大体テンポは合っているかと思う。
前からMIDIをやってみたいとは思っていたんです。
ただMIDIに関すると言うか音楽全般に関する知識は皆無、音符とか読めませんし、そんな状態なので結構苦労しています。Arduinoの例題をベースにスケッチを書いてみましたが、まだまだバグバグで、しかも複数トラックを持つフォーマットには対応していません。
ですが、楽器を鳴らせるのは楽しいですな。
現状はキーを押すとMIDI出力するとかそう言ったものではなく、MIDIファイルをROM化して、それを流しています。
本当はMIDIファイルをそのまま垂れ流す程度で済むかと思っていましたが、そうではないんですね。データを送るタイミングとかはこちらでコントロールする必要が有るみたい。
あ、ちなみに物理的な接続はやけに簡単です。
スケッチとバイナリーデータをCソースに変換するプログラムも一応。
※MIDIのフォーマット0のみに対応
Prototyping Lab ―「作りながら考える」ためのArduino実践レシピ
- 作者: 小林 茂
- 出版社/メーカー: オライリージャパン
- 発売日: 2010/05/27
- メディア: 大型本
新 裏口からのMIDI入門―「楽器が弾けない」「楽譜が読めない」初心者必見! (I・O BOOKS)
- 作者: 御池 鮎樹
- 出版社/メーカー: 工学社
- 発売日: 2009/11
- メディア: 単行本
SANWA SUPPLY KB-MID01-18 MIDIケーブル
- 出版社/メーカー: サンワサプライ
- メディア: エレクトロニクス
/* MIDI player The circuit: * digital in 1 connected to MIDI jack pin 5 * MIDI jack pin 2 connected to ground * MIDI jack pin 4 connected to +5V through 220-ohm resistor Attach a MIDI cable to the jack, then to a MIDI synth, and play music. created 13 Jun 2006 modified 2 Jul 2009 by Tom Igoe http://www.arduino.cc/en/Tutorial/MIDI */ #include <LiquidCrystal.h> #include <avr/pgmspace.h> /*************************************************************************/ /* defines */ /*************************************************************************/ #define DI13 13 #define DI12 12 #define DI11 11 #define DI10 10 #define DI9 9 #define DI8 8 #define DI7 7 #define DI6 6 #define DI5 5 #define DI4 4 #define DI3 3 #define DI2 2 #define DI1 1 #define DI0 0 #define AN0 14 #define AN1 15 #define AN2 16 #define AN3 17 #define AN4 18 #define AN5 19 #define PWM11 DI11 #define PWM10 DI10 #define PWM9 DI9 #define PWM6 DI6 #define PWM5 DI5 #define PWM3 DI3 typedef struct { struct { unsigned char chunk[4]; unsigned char len[4]; unsigned char format[2]; unsigned char tracks[2]; unsigned char period[2]; } header; struct { unsigned char type[4]; unsigned char len[4]; unsigned char data[4]; } track; } MIDI; static unsigned long swap_l( unsigned char src[] ); static unsigned short swap_w( unsigned char src[] ); extern const unsigned char PROGMEM midi_data[]; LiquidCrystal lcd(DI2,DI3,DI4,DI5,DI6,DI7); unsigned long data_len; unsigned short period; PGM_P ptr; void setup() { MIDI *midi = (MIDI *)malloc( sizeof(MIDI) ); memcpy_P( midi, midi_data, sizeof(MIDI) ); data_len = swap_l(midi->track.len); period = swap_w(midi->header.period); lcd.begin(16,2); lcd.clear(); lcd.setCursor(0,1); lcd.print( period ); // Set MIDI baud rate: Serial.begin(31250); // Serial.begin(38400); free( midi ); } void loop() { unsigned char c; unsigned long temp,delta_time,old_time,new_time; ptr = (PGM_P)(((MIDI *)midi_data)->track.data); old_time = 0; while( 1 ) { delta_time = 0; c = pgm_read_byte_near(ptr++); if( c == 0x00 ) {} else { while( 1 ) { delta_time <<= 7; delta_time |= c & 0x7f; if( c & 0x80 ) c = pgm_read_byte_near(ptr++); else break; } } #if 1 lcd.setCursor(4,1); lcd.print( " " ); lcd.setCursor(4,1); lcd.print( delta_time ); #endif if( old_time == 0 ) new_time = 0; else new_time = millis(); temp = (delta_time * 1000 * 10) / period / 35; if( temp <= (new_time - old_time) ) temp = 0; else temp -= new_time - old_time; delay( temp ); old_time = new_time; if( event() == (-1) ) { delay( 10000UL ); break; } } } int event() { unsigned char c; int ret = 0; c = pgm_read_byte_near(ptr++); // switch( c & 0xf0 ) { case 0xf0 : if( c == 0xff ) ret = meta(); else { if( c == 0xf0 ) { c = pgm_read_byte_near(ptr++); // for( int i = c; i > 0; i-- ) { c = pgm_read_byte_near(ptr++); // } } else { c = pgm_read_byte_near(ptr++); // for( int i = c; i > 0; i-- ) { c = pgm_read_byte_near(ptr++); // } } } break; case 0x80 : // 3bytes pattern case 0x90 : // 3bytes pattern case 0xa0 : // 3bytes pattern case 0xb0 : // 3bytes pattern case 0xe0 : // 3bytes pattern lcd.setCursor(8,1); lcd.print( " " ); lcd.setCursor(8,1); Serial.print(c,BYTE); lcd.print( c,HEX ); lcd.print( ":" ); c = pgm_read_byte_near(ptr++); Serial.print(c,BYTE); lcd.print( c,HEX ); lcd.print( ":" ); c = pgm_read_byte_near(ptr++); Serial.print(c,BYTE); lcd.print( c,HEX ); break; default : // 2bytes pattern lcd.setCursor(8,1); lcd.print( " " ); lcd.setCursor(8,1); Serial.print(c,BYTE); lcd.print( c,HEX ); lcd.print( ":" ); c = pgm_read_byte_near(ptr++); Serial.print(c,BYTE); lcd.print( c,HEX ); break; } return ret; } int meta() { unsigned char c,len; int ret = 0; c = pgm_read_byte_near(ptr++); switch( c ) { case 0x00 : Serial.print(0xff,BYTE);Serial.print(c,BYTE); c = pgm_read_byte_near(ptr++); Serial.print(c,BYTE); break; case 0x01 : case 0x02 : case 0x03 : case 0x04 : case 0x05 : case 0x06 : Serial.print(0xff,BYTE);Serial.print(c,BYTE); len = pgm_read_byte_near(ptr++); Serial.print(len,BYTE); lcd.setCursor(0,0); lcd.print( " " ); lcd.setCursor(0,0); for( ;len > 0; len-- ) { c = pgm_read_byte_near(ptr++); Serial.print(c, BYTE); lcd.print( c ); } break; case 0x2f : Serial.print(0xff,BYTE);Serial.print(c,BYTE); c = pgm_read_byte_near(ptr++); Serial.print(c,BYTE); ret = (-1); break; case 0x51 : case 0x58 : case 0x59 : Serial.print(0xff,BYTE);Serial.print(c,BYTE); len = pgm_read_byte_near(ptr++); Serial.print(len,BYTE); for( ;len > 0; len-- ) { c = pgm_read_byte_near(ptr++); Serial.print(c, BYTE); } break; default : break; } return ret; } static unsigned long swap_l( unsigned char src[] ) { unsigned long temp = 0; temp += src[0]; temp <<= 8; temp += src[1]; temp <<= 8; temp += src[2]; temp <<= 8; temp += src[3]; return temp; } static unsigned short swap_w( unsigned char src[] ) { unsigned short temp = 0; temp += src[0]; temp <<= 8; temp += src[1]; return temp; }
/* ------------------------------------------------------------------------ */ /* バイナリファイルをCソースファイルに変換するプログラム */ /* */ /* Copyright (C) 2004- by hamayan */ /* ------------------------------------------------------------------------ */ #include <stdio.h> #include <string.h> #include <time.h> /* ------------------------------------------------------------------------ */ /* メインね! */ /* ------------------------------------------------------------------------ */ int main( int argc, char *argv[] ) { char str[32]; int i,c; long length; FILE *in,*out; time_t timer; struct tm *tblock; if( argc != 3 ) { fprintf( stderr, "Argument Missmatch.\r\n" ); return EOF; } if( (in = fopen( argv[1], "rb" )) == NULL ) { fprintf( stderr, "Image File Open Error.\r\n" ); return EOF; } if( (out = fopen( argv[2], "wb" )) == NULL ) { fprintf( stderr, "Output File Open Error.\r\n" ); fclose( in ); return EOF; } /*ヘッダー部の出力*/ fprintf( out, "/* ------------------------------------------------------------------------ */\r\n" ); fprintf( out, "/* Binary data file convert to C source file program. */\r\n" ); fprintf( out, "/* designed by hamayan */\r\n" ); fprintf( out, "/* Copyright(C) hamayan */\r\n" ); fprintf( out, "/* since 2004 - */\r\n" ); fprintf( out, "/* ------------------------------------------------------------------------ */\r\n" ); /*ヘッダーファイルの取り込み*/ fprintf( out, "#include\t<avr/pgmspace.h>\r\n" ); /*変換後のデータ表現*/ fprintf( out, "const unsigned char PROGMEM midi_data[] =\r\n" ); fprintf( out, "{\r\n" ); do { fprintf( out, "\t" ); for( i = 0; i < 16; i++ ) { if( (c = fgetc( in )) == EOF ) break; fprintf( out, "0x%02X,", c ); } fprintf( out, "\r\n" ); } while( c != EOF ); fprintf( out, "};\r\n\r\n" ); /*フッター部の出力*/ fprintf( out, "/* ------------------------------------------------------------------------ */\r\n" ); fprintf( out, "/* designed by hamayan */\r\n" ); fprintf( out, "/* Copyright(C) hamayan */\r\n" ); fprintf( out, "/* since 2004 - */\r\n" ); fprintf( out, "/* ------------------------------------------------------------------------ */\r\n" ); fclose( in ); fclose( out ); return 0; } /* ------------------------------------------------------------------------ */ /* Copyright (C) 2004- by hamayan */ /* ------------------------------------------------------------------------ */
2010-06-06 09:21
nice!(0)
コメント(0)
トラックバック(0)
コメント 0