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:
Mon Jul 20 09:06:05 2015 +0000
Revision:
1:c536df09d2e8
Parent:
0:12d69da08021
Child:
2:4bcf9c18896b
Support LPC1114 target.  Bug fixes.

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 0:12d69da08021 37 #endif
MACRUM 0:12d69da08021 38
MACRUM 0:12d69da08021 39 #ifdef _DEBUG
MACRUM 0:12d69da08021 40 Serial pc(USBTX, USBRX);
MACRUM 0:12d69da08021 41 #define DEBUG_PRINT(...) { pc.printf(__VA_ARGS__);}
MACRUM 0:12d69da08021 42 #else
MACRUM 0:12d69da08021 43 #define DEBUG_PRINT(...)
MACRUM 0:12d69da08021 44 #endif
MACRUM 0:12d69da08021 45
MACRUM 0:12d69da08021 46 FILE *fp;
MACRUM 0:12d69da08021 47 Timer timer;
MACRUM 0:12d69da08021 48 uint32_t tempo;
MACRUM 0:12d69da08021 49 uint32_t delta_time;
MACRUM 0:12d69da08021 50 uint32_t TIMER;
MACRUM 0:12d69da08021 51 uint32_t STATE;
MACRUM 0:12d69da08021 52
MACRUM 0:12d69da08021 53 #define midi_read() (fgetc(fp))
MACRUM 0:12d69da08021 54
MACRUM 0:12d69da08021 55 void disable_timer(void)
MACRUM 0:12d69da08021 56 {
MACRUM 0:12d69da08021 57 timer.stop();
MACRUM 0:12d69da08021 58 }
MACRUM 0:12d69da08021 59
MACRUM 0:12d69da08021 60 uint32_t delta_time_read(void)
MACRUM 0:12d69da08021 61 {
MACRUM 0:12d69da08021 62 uint32_t r_buf;
MACRUM 0:12d69da08021 63 uint32_t ret = 0;
MACRUM 0:12d69da08021 64
MACRUM 0:12d69da08021 65 while(1) {
MACRUM 0:12d69da08021 66 r_buf = midi_read();
MACRUM 0:12d69da08021 67 ret = (ret <<7) | (r_buf & 0x7f);
MACRUM 0:12d69da08021 68 if ((r_buf & 0x80) == 0)
MACRUM 0:12d69da08021 69 break;
MACRUM 0:12d69da08021 70 }
MACRUM 0:12d69da08021 71
MACRUM 0:12d69da08021 72 TIMER += ((ret * tempo) / delta_time);
MACRUM 0:12d69da08021 73 return ret;
MACRUM 0:12d69da08021 74 }
MACRUM 0:12d69da08021 75
MACRUM 0:12d69da08021 76 void midi_play(void)
MACRUM 0:12d69da08021 77 {
MACRUM 0:12d69da08021 78 int32_t buf[256];
MACRUM 0:12d69da08021 79 uint32_t cnt;
MACRUM 0:12d69da08021 80 uint32_t cmd;
MACRUM 0:12d69da08021 81
MACRUM 0:12d69da08021 82 buf[0] = midi_read();
MACRUM 0:12d69da08021 83 buf[1] = midi_read();
MACRUM 0:12d69da08021 84
MACRUM 0:12d69da08021 85 cmd = (buf[0] & 0xf0);
MACRUM 0:12d69da08021 86 if ((cmd == 0x80) || (cmd == 0x90) || (cmd == 0xA0) || (cmd == 0xB0) || (cmd == 0xE0)) {
MACRUM 0:12d69da08021 87 buf[2] = midi_read();
MACRUM 0:12d69da08021 88 #if defined(_NO_eVocaloid_)
MACRUM 0:12d69da08021 89 if ((buf[0] & 0x0f) == 0x0f) { // CH.16
MACRUM 0:12d69da08021 90 return;
MACRUM 0:12d69da08021 91 }
MACRUM 0:12d69da08021 92 if ((buf[0] & 0x0f) == 0x00) { // CH.1
MACRUM 0:12d69da08021 93 buf[0] = (buf[0] | 0x0f); // Force change to CH.16
MACRUM 0:12d69da08021 94 }
MACRUM 0:12d69da08021 95 #endif
MACRUM 0:12d69da08021 96 midi.putc(buf[0]);
MACRUM 0:12d69da08021 97 midi.putc(buf[1]);
MACRUM 0:12d69da08021 98 midi.putc(buf[2]);
MACRUM 0:12d69da08021 99 } else if (cmd == 0xC0) {
MACRUM 0:12d69da08021 100 #if defined(_NO_eVocaloid_)
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 } else if (cmd == 0xD0) {
MACRUM 0:12d69da08021 108 midi.putc(buf[0]);
MACRUM 0:12d69da08021 109 midi.putc(buf[1]);
MACRUM 0:12d69da08021 110 } else if (cmd == 0xF0) {
MACRUM 0:12d69da08021 111 switch( buf[0] & 0x0F ) {
MACRUM 0:12d69da08021 112 case 0x00 : // SysEx
MACRUM 0:12d69da08021 113 case 0x07 : // SysEx2
MACRUM 0:12d69da08021 114 cnt = buf[1];
MACRUM 0:12d69da08021 115 midi.putc(buf[0]);
MACRUM 0:12d69da08021 116 for(uint32_t i=1; i<cnt+1; i++) {
MACRUM 0:12d69da08021 117 midi.putc(midi_read());
MACRUM 0:12d69da08021 118 }
MACRUM 0:12d69da08021 119 break;
MACRUM 0:12d69da08021 120 case 0x0f : // Meta event
MACRUM 0:12d69da08021 121 switch ( buf[1] ) {
MACRUM 0:12d69da08021 122 case 0x00: // Sequence number
MACRUM 0:12d69da08021 123 midi_read();
MACRUM 0:12d69da08021 124 break;
MACRUM 0:12d69da08021 125 case 0x51: // Set tempo
MACRUM 0:12d69da08021 126 midi_read(); // len (== 3)
MACRUM 0:12d69da08021 127 tempo = midi_read();
MACRUM 0:12d69da08021 128 tempo = (tempo << 8 ) | midi_read();
MACRUM 0:12d69da08021 129 tempo = (tempo << 8 ) | midi_read();
MACRUM 0:12d69da08021 130 tempo = tempo / 1000;
MACRUM 0:12d69da08021 131 DEBUG_PRINT("Set tempo = %d\n", tempo);
MACRUM 0:12d69da08021 132 break;
MACRUM 0:12d69da08021 133 case 0x2f: // End of Track
MACRUM 0:12d69da08021 134 midi_read(); // Read zero
MACRUM 0:12d69da08021 135 disable_timer();
MACRUM 0:12d69da08021 136 STATE = 2;
MACRUM 0:12d69da08021 137 break;
MACRUM 1:c536df09d2e8 138 case 0x01:
MACRUM 1:c536df09d2e8 139 case 0x02:
MACRUM 1:c536df09d2e8 140 cnt = midi_read(); // len
MACRUM 1:c536df09d2e8 141 for(uint32_t i=0; i<cnt; i++)
MACRUM 1:c536df09d2e8 142 DEBUG_PRINT("%c", midi_read());
MACRUM 1:c536df09d2e8 143 DEBUG_PRINT("\n");
MACRUM 1:c536df09d2e8 144 break;
MACRUM 0:12d69da08021 145 default:
MACRUM 0:12d69da08021 146 cnt = midi_read(); // len
MACRUM 0:12d69da08021 147 for(uint32_t i=0; i<cnt; i++)
MACRUM 0:12d69da08021 148 midi_read();
MACRUM 0:12d69da08021 149 break;
MACRUM 0:12d69da08021 150 }
MACRUM 0:12d69da08021 151 break;
MACRUM 0:12d69da08021 152 }
MACRUM 0:12d69da08021 153 }
MACRUM 0:12d69da08021 154 }
MACRUM 0:12d69da08021 155
MACRUM 0:12d69da08021 156
MACRUM 0:12d69da08021 157 void smf_main_loop(void)
MACRUM 0:12d69da08021 158 {
MACRUM 0:12d69da08021 159 if(STATE == 1) {
MACRUM 0:12d69da08021 160 if (TIMER < timer.read_ms()) {
MACRUM 0:12d69da08021 161 midi_play();
MACRUM 0:12d69da08021 162 if (STATE != 2)
MACRUM 0:12d69da08021 163 delta_time_read();
MACRUM 0:12d69da08021 164 }
MACRUM 0:12d69da08021 165 }
MACRUM 0:12d69da08021 166 }
MACRUM 0:12d69da08021 167
MACRUM 0:12d69da08021 168 void smf_init(void)
MACRUM 0:12d69da08021 169 {
MACRUM 0:12d69da08021 170 TIMER = 0;
MACRUM 0:12d69da08021 171 tempo = 500; // default value
MACRUM 0:12d69da08021 172
MACRUM 0:12d69da08021 173 // Skip MIDI header
MACRUM 0:12d69da08021 174 for (uint32_t i=0; i<8; i++) {
MACRUM 0:12d69da08021 175 midi_read();
MACRUM 0:12d69da08021 176 }
MACRUM 0:12d69da08021 177
MACRUM 0:12d69da08021 178 uint32_t format;
MACRUM 0:12d69da08021 179 format = (midi_read() << 8);
MACRUM 0:12d69da08021 180 format |= midi_read();
MACRUM 0:12d69da08021 181
MACRUM 1:c536df09d2e8 182 if ( format > 2) {
MACRUM 1:c536df09d2e8 183 DEBUG_PRINT("This is not a MIDI format file!\n", format);
MACRUM 1:c536df09d2e8 184 STATE = 2;
MACRUM 1:c536df09d2e8 185 return;
MACRUM 1:c536df09d2e8 186 } else {
MACRUM 1:c536df09d2e8 187 DEBUG_PRINT("MIDI format : %d\n", format);
MACRUM 1:c536df09d2e8 188 }
MACRUM 0:12d69da08021 189
MACRUM 0:12d69da08021 190 uint32_t track;
MACRUM 0:12d69da08021 191 track = (midi_read() << 8);
MACRUM 0:12d69da08021 192 track |= midi_read();
MACRUM 0:12d69da08021 193
MACRUM 1:c536df09d2e8 194 DEBUG_PRINT("Number of tracks : %d\n", track);
MACRUM 0:12d69da08021 195
MACRUM 0:12d69da08021 196 // timebase
MACRUM 0:12d69da08021 197 delta_time = (midi_read() << 8);
MACRUM 0:12d69da08021 198 delta_time |= midi_read();
MACRUM 0:12d69da08021 199 DEBUG_PRINT("tempo = %d, delta_time = %d\n", tempo, delta_time);
MACRUM 0:12d69da08021 200
MACRUM 0:12d69da08021 201 // skip track chunk header
MACRUM 0:12d69da08021 202 for (uint32_t i=0; i<0x8; i++)
MACRUM 0:12d69da08021 203 midi_read();
MACRUM 0:12d69da08021 204
MACRUM 0:12d69da08021 205 TIMER = (delta_time_read() * tempo) / delta_time ;
MACRUM 0:12d69da08021 206 DEBUG_PRINT("TIMER = %d\n", TIMER);
MACRUM 0:12d69da08021 207 STATE = 1;
MACRUM 0:12d69da08021 208 }
MACRUM 0:12d69da08021 209
MACRUM 0:12d69da08021 210 void skip()
MACRUM 0:12d69da08021 211 {
MACRUM 0:12d69da08021 212 STATE = 2;
MACRUM 0:12d69da08021 213 }
MACRUM 1:c536df09d2e8 214
MACRUM 0:12d69da08021 215 int main()
MACRUM 0:12d69da08021 216 {
MACRUM 0:12d69da08021 217 DEBUG_PRINT("Initializing...\n");
MACRUM 0:12d69da08021 218
MACRUM 1:c536df09d2e8 219 btn.mode(PullUp);
MACRUM 0:12d69da08021 220 btn.fall(&skip);
MACRUM 0:12d69da08021 221 midi.baud(31250);
MACRUM 0:12d69da08021 222
MACRUM 0:12d69da08021 223 wait(3.5); // Wait few seconds for booting eVY1-Shleld.
MACRUM 0:12d69da08021 224
MACRUM 0:12d69da08021 225 #if !defined(_NO_eVocaloid_)
MACRUM 0:12d69da08021 226 const uint8_t aMsg[] = "\xF0\x43\x79\x09\x00\x50\x10" "4 a\0" "\xF7";
MACRUM 0:12d69da08021 227 for (uint32_t i = 0; i < sizeof(aMsg)-1; midi.putc(aMsg[i++]));
MACRUM 0:12d69da08021 228 #endif
MACRUM 0:12d69da08021 229
MACRUM 0:12d69da08021 230 DEBUG_PRINT("Initialized.\n");
MACRUM 0:12d69da08021 231
MACRUM 0:12d69da08021 232 char buf[50];
MACRUM 0:12d69da08021 233
MACRUM 0:12d69da08021 234 #if defined(USE_DIRECTORY_LIST)
MACRUM 0:12d69da08021 235 DirectoryList dir("/sd");
MACRUM 0:12d69da08021 236 if ( dir.error_check() ) {
MACRUM 0:12d69da08021 237 DEBUG_PRINT("directory could not be opened\r\n");
MACRUM 0:12d69da08021 238 return -1;
MACRUM 0:12d69da08021 239 }
MACRUM 1:c536df09d2e8 240
MACRUM 0:12d69da08021 241 for ( int i = 0; i < dir.size(); i++ ) {
MACRUM 0:12d69da08021 242 sprintf(buf, "/sd/%s", dir[ i ].c_str() );
MACRUM 0:12d69da08021 243 #else
MACRUM 1:c536df09d2e8 244 for ( uint32_t i = 0; i < 10; i++ ) {
MACRUM 0:12d69da08021 245 sprintf(buf, "/sd/%d.mid", i);
MACRUM 0:12d69da08021 246 #endif
MACRUM 0:12d69da08021 247
MACRUM 0:12d69da08021 248 fp = fopen(buf, "r");
MACRUM 0:12d69da08021 249 if (fp == NULL) {
MACRUM 0:12d69da08021 250 DEBUG_PRINT("Unable to read the file \n");
MACRUM 0:12d69da08021 251 } else {
MACRUM 0:12d69da08021 252 timer.reset();
MACRUM 0:12d69da08021 253 timer.start();
MACRUM 0:12d69da08021 254 smf_init();
MACRUM 1:c536df09d2e8 255 if ( STATE == 2 ) {
MACRUM 1:c536df09d2e8 256 fclose(fp);
MACRUM 1:c536df09d2e8 257 #if defined(__MICROLIB) && defined(__ARMCC_VERSION) // with microlib and ARM compiler
MACRUM 1:c536df09d2e8 258 free(fp);
MACRUM 1:c536df09d2e8 259 #endif
MACRUM 1:c536df09d2e8 260 continue;
MACRUM 1:c536df09d2e8 261 }
MACRUM 1:c536df09d2e8 262
MACRUM 0:12d69da08021 263 DEBUG_PRINT("Now, playing (%s)... \n", buf);
MACRUM 0:12d69da08021 264 while (1) {
MACRUM 0:12d69da08021 265 smf_main_loop();
MACRUM 0:12d69da08021 266 if (STATE == 2) {
MACRUM 0:12d69da08021 267 break;
MACRUM 0:12d69da08021 268 }
MACRUM 0:12d69da08021 269 }
MACRUM 0:12d69da08021 270 fclose(fp);
MACRUM 0:12d69da08021 271 #if defined(__MICROLIB) && defined(__ARMCC_VERSION) // with microlib and ARM compiler
MACRUM 0:12d69da08021 272 free(fp);
MACRUM 0:12d69da08021 273 #endif
MACRUM 0:12d69da08021 274 DEBUG_PRINT("End.\n");
MACRUM 0:12d69da08021 275 }
MACRUM 0:12d69da08021 276 }
MACRUM 0:12d69da08021 277 }