Standard MIDI file player for the eVY1 shield and analog joy stick

Dependencies:   DirectoryList SDFileSystem mbed

Fork of eVY1_SMF_player by Toyomasa Watarai

MicroSDカードからSMF(スタンダードMIDIファイル)を読み込み、データをシリアルでeVY1シールドに転送して再生します。 MIDIファイル形式は、Format 0のみ対応しています。アナログジョイスティックを使用してテンポとピッチの変更が出来るようにしました。

動作確認は、mbed FRDM-K64Fで行っています。

eVY1シールドをそのまま刺して使用できます(オンボードのMicroSDスロットを使います)。

eVY1を使用した場合、MIDIデータのCH.1は強制的にeVocalodによる歌声として使用されてしまうため(プログラムチェンジも不可)、強制的にCH.16に割り当てています。そのため、CH.16を使用しているMIDIファイルはデータ通りに再生する事が出来ません。

アナログジョイスティックの X Y データは、それぞれアナログ入力の A0, A1 に接続しています。

Committer:
MACRUM
Date:
Sat Jul 18 01:40:09 2015 +0000
Revision:
0:12d69da08021
Child:
1:c536df09d2e8
Initial revision

Who changed what in which revision?

UserRevisionLine numberNew contents of line
MACRUM 0:12d69da08021 1 #include "mbed.h"
MACRUM 0:12d69da08021 2 #include "SDFileSystem.h"
MACRUM 0:12d69da08021 3 #include "DirectoryList.h"
MACRUM 0:12d69da08021 4
MACRUM 0:12d69da08021 5 #define _DEBUG
MACRUM 0:12d69da08021 6 #define _NO_eVocaloid_
MACRUM 0:12d69da08021 7
MACRUM 0:12d69da08021 8 #if defined(TARGET_K64F)
MACRUM 0:12d69da08021 9 #define USE_DIRECTORY_LIST
MACRUM 0:12d69da08021 10 SDFileSystem sd(PTE3, PTE1, PTE2, PTE4, "sd"); // MOSI, MISO, SCK, CS
MACRUM 0:12d69da08021 11 RawSerial midi(D1, NC);
MACRUM 0:12d69da08021 12 InterruptIn btn(PTA4);
MACRUM 0:12d69da08021 13
MACRUM 0:12d69da08021 14 #elif defined(TARGET_LPC1114)
MACRUM 0:12d69da08021 15 SDFileSystem sd(dp2, dp1, dp6, dp4, "sd"); // MOSI, MISO, SCK, CS
MACRUM 0:12d69da08021 16 RawSerial midi(dp16, NC);
MACRUM 0:12d69da08021 17 InterruptIn btn(dp9);
MACRUM 0:12d69da08021 18
MACRUM 0:12d69da08021 19 #endif
MACRUM 0:12d69da08021 20
MACRUM 0:12d69da08021 21 #ifdef _DEBUG
MACRUM 0:12d69da08021 22 Serial pc(USBTX, USBRX);
MACRUM 0:12d69da08021 23 #define DEBUG_PRINT(...) { pc.printf(__VA_ARGS__);}
MACRUM 0:12d69da08021 24 #else
MACRUM 0:12d69da08021 25 #define DEBUG_PRINT(...)
MACRUM 0:12d69da08021 26 #endif
MACRUM 0:12d69da08021 27
MACRUM 0:12d69da08021 28 FILE *fp;
MACRUM 0:12d69da08021 29 Timer timer;
MACRUM 0:12d69da08021 30 uint32_t tempo;
MACRUM 0:12d69da08021 31 uint32_t delta_time;
MACRUM 0:12d69da08021 32 uint32_t TIMER;
MACRUM 0:12d69da08021 33 uint32_t STATE;
MACRUM 0:12d69da08021 34
MACRUM 0:12d69da08021 35 #define midi_read() (fgetc(fp))
MACRUM 0:12d69da08021 36
MACRUM 0:12d69da08021 37 void disable_timer(void)
MACRUM 0:12d69da08021 38 {
MACRUM 0:12d69da08021 39 timer.stop();
MACRUM 0:12d69da08021 40 }
MACRUM 0:12d69da08021 41
MACRUM 0:12d69da08021 42 uint32_t delta_time_read(void)
MACRUM 0:12d69da08021 43 {
MACRUM 0:12d69da08021 44 uint32_t r_buf;
MACRUM 0:12d69da08021 45 uint32_t ret = 0;
MACRUM 0:12d69da08021 46
MACRUM 0:12d69da08021 47 while(1) {
MACRUM 0:12d69da08021 48 r_buf = midi_read();
MACRUM 0:12d69da08021 49 ret = (ret <<7) | (r_buf & 0x7f);
MACRUM 0:12d69da08021 50 if ((r_buf & 0x80) == 0)
MACRUM 0:12d69da08021 51 break;
MACRUM 0:12d69da08021 52 }
MACRUM 0:12d69da08021 53
MACRUM 0:12d69da08021 54 TIMER += ((ret * tempo) / delta_time);
MACRUM 0:12d69da08021 55 return ret;
MACRUM 0:12d69da08021 56 }
MACRUM 0:12d69da08021 57
MACRUM 0:12d69da08021 58 void midi_play(void)
MACRUM 0:12d69da08021 59 {
MACRUM 0:12d69da08021 60 int32_t buf[256];
MACRUM 0:12d69da08021 61 uint32_t cnt;
MACRUM 0:12d69da08021 62 uint32_t cmd;
MACRUM 0:12d69da08021 63
MACRUM 0:12d69da08021 64 buf[0] = midi_read();
MACRUM 0:12d69da08021 65 buf[1] = midi_read();
MACRUM 0:12d69da08021 66
MACRUM 0:12d69da08021 67 cmd = (buf[0] & 0xf0);
MACRUM 0:12d69da08021 68 if ((cmd == 0x80) || (cmd == 0x90) || (cmd == 0xA0) || (cmd == 0xB0) || (cmd == 0xE0)) {
MACRUM 0:12d69da08021 69 buf[2] = midi_read();
MACRUM 0:12d69da08021 70 #if defined(_NO_eVocaloid_)
MACRUM 0:12d69da08021 71 if ((buf[0] & 0x0f) == 0x0f) { // CH.16
MACRUM 0:12d69da08021 72 DEBUG_PRINT("*");
MACRUM 0:12d69da08021 73 return;
MACRUM 0:12d69da08021 74 }
MACRUM 0:12d69da08021 75 if ((buf[0] & 0x0f) == 0x00) { // CH.1
MACRUM 0:12d69da08021 76 buf[0] = (buf[0] | 0x0f); // Force change to CH.16
MACRUM 0:12d69da08021 77 }
MACRUM 0:12d69da08021 78 #endif
MACRUM 0:12d69da08021 79 midi.putc(buf[0]);
MACRUM 0:12d69da08021 80 midi.putc(buf[1]);
MACRUM 0:12d69da08021 81 midi.putc(buf[2]);
MACRUM 0:12d69da08021 82 } else if (cmd == 0xC0) {
MACRUM 0:12d69da08021 83 #if defined(_NO_eVocaloid_)
MACRUM 0:12d69da08021 84 if ((buf[0] & 0x0f) == 0x00) { // CH.1
MACRUM 0:12d69da08021 85 buf[0] = (buf[0] | 0x0f); // Force change to CH.16
MACRUM 0:12d69da08021 86 }
MACRUM 0:12d69da08021 87 #endif
MACRUM 0:12d69da08021 88 midi.putc(buf[0]);
MACRUM 0:12d69da08021 89 midi.putc(buf[1]);
MACRUM 0:12d69da08021 90 } else if (cmd == 0xD0) {
MACRUM 0:12d69da08021 91 midi.putc(buf[0]);
MACRUM 0:12d69da08021 92 midi.putc(buf[1]);
MACRUM 0:12d69da08021 93 } else if (cmd == 0xF0) {
MACRUM 0:12d69da08021 94 switch( buf[0] & 0x0F ) {
MACRUM 0:12d69da08021 95 case 0x00 : // SysEx
MACRUM 0:12d69da08021 96 case 0x07 : // SysEx2
MACRUM 0:12d69da08021 97 cnt = buf[1];
MACRUM 0:12d69da08021 98 midi.putc(buf[0]);
MACRUM 0:12d69da08021 99 for(uint32_t i=1; i<cnt+1; i++) {
MACRUM 0:12d69da08021 100 midi.putc(midi_read());
MACRUM 0:12d69da08021 101 }
MACRUM 0:12d69da08021 102 break;
MACRUM 0:12d69da08021 103 case 0x0f : // Meta event
MACRUM 0:12d69da08021 104 switch ( buf[1] ) {
MACRUM 0:12d69da08021 105 case 0x00: // Sequence number
MACRUM 0:12d69da08021 106 midi_read();
MACRUM 0:12d69da08021 107 break;
MACRUM 0:12d69da08021 108 case 0x51: // Set tempo
MACRUM 0:12d69da08021 109 midi_read(); // len (== 3)
MACRUM 0:12d69da08021 110 tempo = midi_read();
MACRUM 0:12d69da08021 111 tempo = (tempo << 8 ) | midi_read();
MACRUM 0:12d69da08021 112 tempo = (tempo << 8 ) | midi_read();
MACRUM 0:12d69da08021 113 tempo = tempo / 1000;
MACRUM 0:12d69da08021 114 DEBUG_PRINT("Set tempo = %d\n", tempo);
MACRUM 0:12d69da08021 115 break;
MACRUM 0:12d69da08021 116 case 0x2f: // End of Track
MACRUM 0:12d69da08021 117 midi_read(); // Read zero
MACRUM 0:12d69da08021 118 disable_timer();
MACRUM 0:12d69da08021 119 STATE = 2;
MACRUM 0:12d69da08021 120 break;
MACRUM 0:12d69da08021 121 default:
MACRUM 0:12d69da08021 122 cnt = midi_read(); // len
MACRUM 0:12d69da08021 123 for(uint32_t i=0; i<cnt; i++)
MACRUM 0:12d69da08021 124 midi_read();
MACRUM 0:12d69da08021 125 break;
MACRUM 0:12d69da08021 126 }
MACRUM 0:12d69da08021 127 break;
MACRUM 0:12d69da08021 128 }
MACRUM 0:12d69da08021 129 }
MACRUM 0:12d69da08021 130 }
MACRUM 0:12d69da08021 131
MACRUM 0:12d69da08021 132
MACRUM 0:12d69da08021 133 void smf_main_loop(void)
MACRUM 0:12d69da08021 134 {
MACRUM 0:12d69da08021 135 if(STATE == 1) {
MACRUM 0:12d69da08021 136 if (TIMER < timer.read_ms()) {
MACRUM 0:12d69da08021 137 midi_play();
MACRUM 0:12d69da08021 138 if (STATE != 2)
MACRUM 0:12d69da08021 139 delta_time_read();
MACRUM 0:12d69da08021 140 }
MACRUM 0:12d69da08021 141 }
MACRUM 0:12d69da08021 142 }
MACRUM 0:12d69da08021 143
MACRUM 0:12d69da08021 144 void smf_init(void)
MACRUM 0:12d69da08021 145 {
MACRUM 0:12d69da08021 146 TIMER = 0;
MACRUM 0:12d69da08021 147 tempo = 500; // default value
MACRUM 0:12d69da08021 148
MACRUM 0:12d69da08021 149 #if defined(_DEBUG)
MACRUM 0:12d69da08021 150 // Skip MIDI header
MACRUM 0:12d69da08021 151 for (uint32_t i=0; i<8; i++) {
MACRUM 0:12d69da08021 152 midi_read();
MACRUM 0:12d69da08021 153 }
MACRUM 0:12d69da08021 154
MACRUM 0:12d69da08021 155 uint32_t format;
MACRUM 0:12d69da08021 156 format = (midi_read() << 8);
MACRUM 0:12d69da08021 157 format |= midi_read();
MACRUM 0:12d69da08021 158
MACRUM 0:12d69da08021 159 if (format != 0)
MACRUM 0:12d69da08021 160 DEBUG_PRINT("This is not MID format 0 file!\n");
MACRUM 0:12d69da08021 161
MACRUM 0:12d69da08021 162 uint32_t track;
MACRUM 0:12d69da08021 163 track = (midi_read() << 8);
MACRUM 0:12d69da08021 164 track |= midi_read();
MACRUM 0:12d69da08021 165
MACRUM 0:12d69da08021 166 if (track != 1)
MACRUM 0:12d69da08021 167 DEBUG_PRINT("Number of tracks should be 1!\n");
MACRUM 0:12d69da08021 168 #else
MACRUM 0:12d69da08021 169 // Skip MIDI header
MACRUM 0:12d69da08021 170 for (uint32_t i=0; i<12; i++) {
MACRUM 0:12d69da08021 171 midi_read();
MACRUM 0:12d69da08021 172 }
MACRUM 0:12d69da08021 173 #endif
MACRUM 0:12d69da08021 174
MACRUM 0:12d69da08021 175 // timebase
MACRUM 0:12d69da08021 176 delta_time = (midi_read() << 8);
MACRUM 0:12d69da08021 177 delta_time |= midi_read();
MACRUM 0:12d69da08021 178 DEBUG_PRINT("tempo = %d, delta_time = %d\n", tempo, delta_time);
MACRUM 0:12d69da08021 179
MACRUM 0:12d69da08021 180 // skip track chunk header
MACRUM 0:12d69da08021 181 for (uint32_t i=0; i<0x8; i++)
MACRUM 0:12d69da08021 182 midi_read();
MACRUM 0:12d69da08021 183
MACRUM 0:12d69da08021 184 TIMER = (delta_time_read() * tempo) / delta_time ;
MACRUM 0:12d69da08021 185 DEBUG_PRINT("TIMER = %d\n", TIMER);
MACRUM 0:12d69da08021 186 STATE = 1;
MACRUM 0:12d69da08021 187 }
MACRUM 0:12d69da08021 188
MACRUM 0:12d69da08021 189 void skip()
MACRUM 0:12d69da08021 190 {
MACRUM 0:12d69da08021 191 STATE = 2;
MACRUM 0:12d69da08021 192 }
MACRUM 0:12d69da08021 193
MACRUM 0:12d69da08021 194 int main()
MACRUM 0:12d69da08021 195 {
MACRUM 0:12d69da08021 196 DEBUG_PRINT("Initializing...\n");
MACRUM 0:12d69da08021 197
MACRUM 0:12d69da08021 198 btn.fall(&skip);
MACRUM 0:12d69da08021 199 midi.baud(31250);
MACRUM 0:12d69da08021 200
MACRUM 0:12d69da08021 201 wait(3.5); // Wait few seconds for booting eVY1-Shleld.
MACRUM 0:12d69da08021 202
MACRUM 0:12d69da08021 203 #if !defined(_NO_eVocaloid_)
MACRUM 0:12d69da08021 204 const uint8_t aMsg[] = "\xF0\x43\x79\x09\x00\x50\x10" "4 a\0" "\xF7";
MACRUM 0:12d69da08021 205 for (uint32_t i = 0; i < sizeof(aMsg)-1; midi.putc(aMsg[i++]));
MACRUM 0:12d69da08021 206 #endif
MACRUM 0:12d69da08021 207
MACRUM 0:12d69da08021 208 DEBUG_PRINT("Initialized.\n");
MACRUM 0:12d69da08021 209
MACRUM 0:12d69da08021 210 char buf[50];
MACRUM 0:12d69da08021 211
MACRUM 0:12d69da08021 212 #if defined(USE_DIRECTORY_LIST)
MACRUM 0:12d69da08021 213 DirectoryList dir("/sd");
MACRUM 0:12d69da08021 214 if ( dir.error_check() ) {
MACRUM 0:12d69da08021 215 DEBUG_PRINT("directory could not be opened\r\n");
MACRUM 0:12d69da08021 216 return -1;
MACRUM 0:12d69da08021 217 }
MACRUM 0:12d69da08021 218
MACRUM 0:12d69da08021 219 for ( int i = 0; i < dir.size(); i++ ) {
MACRUM 0:12d69da08021 220 sprintf(buf, "/sd/%s", dir[ i ].c_str() );
MACRUM 0:12d69da08021 221 #else
MACRUM 0:12d69da08021 222 for ( uint32_t i = 0; i < 10; i++ ) {
MACRUM 0:12d69da08021 223 sprintf(buf, "/sd/%d.mid", i);
MACRUM 0:12d69da08021 224 #endif
MACRUM 0:12d69da08021 225
MACRUM 0:12d69da08021 226 fp = fopen(buf, "r");
MACRUM 0:12d69da08021 227 if (fp == NULL) {
MACRUM 0:12d69da08021 228 DEBUG_PRINT("Unable to read the file \n");
MACRUM 0:12d69da08021 229 } else {
MACRUM 0:12d69da08021 230 timer.reset();
MACRUM 0:12d69da08021 231 timer.start();
MACRUM 0:12d69da08021 232 smf_init();
MACRUM 0:12d69da08021 233 DEBUG_PRINT("Now, playing (%s)... \n", buf);
MACRUM 0:12d69da08021 234 while (1) {
MACRUM 0:12d69da08021 235 smf_main_loop();
MACRUM 0:12d69da08021 236 if (STATE == 2) {
MACRUM 0:12d69da08021 237 break;
MACRUM 0:12d69da08021 238 }
MACRUM 0:12d69da08021 239 }
MACRUM 0:12d69da08021 240 fclose(fp);
MACRUM 0:12d69da08021 241 #if defined(__MICROLIB) && defined(__ARMCC_VERSION) // with microlib and ARM compiler
MACRUM 0:12d69da08021 242 free(fp);
MACRUM 0:12d69da08021 243 #endif
MACRUM 0:12d69da08021 244 DEBUG_PRINT("End.\n");
MACRUM 0:12d69da08021 245 }
MACRUM 0:12d69da08021 246 }
MACRUM 0:12d69da08021 247 }