Standard MIDI file player for the eVY1 shield

Dependencies:   DirectoryList SDFileSystem mbed

MicroSDカードからSMF(スタンダードMIDIファイル)を読み込み、データをシリアルでeVY1シールドに転送して再生します。 MIDIファイル形式は、Format 0のみ対応しています。

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

eVY1でシリアルポートを有効にするには、シールドの端子側から+5V入力が必要なので、mbed LPC1114FN28を一部改造しています(JP2 9pinに+5V出力を接続しています)。 FRDM-K64Fの場合は、eVY1シールドをそのまま刺して使用できます(オンボードのMicroSDスロットを使います)。

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

Committer:
MACRUM
Date:
Fri Jan 06 10:58:07 2017 +0000
Revision:
3:2a58b7f4b0cb
Parent:
2:4bcf9c18896b
Add dummy error function

Who changed what in which revision?

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