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 Jan 07 06:40:26 2017 +0000
Revision:
4:4dcc1464c89e
Parent:
3:2a58b7f4b0cb
Add analog joy stick

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