Standard MIDI file player for the eVY1 shield and analog joy stick
Dependencies: DirectoryList SDFileSystem mbed
Fork of eVY1_SMF_player by
main.cpp
00001 /** 00002 * Standard MIDI file player for the eVY1 shield 00003 * 00004 * @author Toyomasa Watarai 00005 * @version 0.1 00006 * @date July-2015 00007 * 00008 * This program parse MIDI format 0 files on SDCard 00009 * and plays the data using eVY1 shield 00010 * 00011 * Ported by Arduino example code of the SWITCHSCIENCE, Thanks! 00012 * https://github.com/SWITCHSCIENCE/eVY1_Shield 00013 * 00014 */ 00015 00016 #include "mbed.h" 00017 #include "SDFileSystem.h" 00018 #include "DirectoryList.h" 00019 00020 #define _DEBUG 00021 #define _NO_eVocaloid_ 00022 00023 #if defined(TARGET_K64F) 00024 #define USE_DIRECTORY_LIST 00025 SDFileSystem sd(PTE3, PTE1, PTE2, PTE4, "sd"); // MOSI, MISO, SCK, CS 00026 RawSerial midi(D1, NC); 00027 InterruptIn btn(PTA4); 00028 AnalogIn ax(A0); 00029 AnalogIn ay(A1); 00030 Ticker click; 00031 float x, y; 00032 00033 #elif defined(TARGET_LPC1114) 00034 SDFileSystem sd(dp2, dp1, dp6, dp4, "sd"); // MOSI, MISO, SCK, CS 00035 RawSerial midi(dp16, NC); 00036 InterruptIn btn(dp9); 00037 #if defined(_DEBUG) 00038 #undef _DEBUG 00039 #endif 00040 00041 #elif defined(TARGET_WIZWIKI_W7500P) 00042 SDFileSystem sd(PB_3, PB_2, PB_1, PB_0, "sd"); // MOSI, MISO, SCK, CS 00043 RawSerial midi(D1, NC); 00044 InterruptIn btn(PC_6); 00045 #if defined(_DEBUG) 00046 #undef _DEBUG 00047 #endif 00048 00049 #endif 00050 00051 #ifdef _DEBUG 00052 Serial pc(USBTX, USBRX); 00053 #define DEBUG_PRINT(...) { pc.printf(__VA_ARGS__);} 00054 #else 00055 #define DEBUG_PRINT(...) 00056 void error(const char* format, ...) {} 00057 #endif 00058 00059 FILE *fp; 00060 Timer timer; 00061 uint32_t tempo, org_tempo; 00062 uint32_t delta_time; 00063 uint32_t TIMER; 00064 uint32_t STATE; 00065 uint32_t pitch_update = 0; 00066 00067 #define midi_read() (fgetc(fp)) 00068 00069 void get_val(void) 00070 { 00071 x = ax.read(); 00072 y = ay.read(); 00073 tempo = org_tempo + ((ax - 0.5f) * 400); 00074 pitch_update = 1; 00075 } 00076 00077 void disable_timer(void) 00078 { 00079 timer.stop(); 00080 } 00081 00082 uint32_t delta_time_read(void) 00083 { 00084 uint32_t r_buf; 00085 uint32_t ret = 0; 00086 00087 while(1) { 00088 r_buf = midi_read(); 00089 ret = (ret <<7) | (r_buf & 0x7f); 00090 if ((r_buf & 0x80) == 0) 00091 break; 00092 } 00093 00094 TIMER += ((ret * tempo) / delta_time); 00095 return ret; 00096 } 00097 00098 void midi_play(void) 00099 { 00100 int32_t buf[256]; 00101 uint32_t cnt; 00102 uint32_t cmd; 00103 00104 if (pitch_update) { 00105 uint32_t pitch; 00106 pitch = 0x4000 + ((y - 0.5f) * 2000); 00107 for(uint32_t i=0; i<16; i++) { 00108 midi.putc(0xE0 | i); 00109 midi.putc(pitch & 0x7F); 00110 midi.putc((pitch >> 8) & 0x7F); 00111 } 00112 pitch_update = 0; 00113 } 00114 buf[0] = midi_read(); 00115 buf[1] = midi_read(); 00116 00117 cmd = (buf[0] & 0xf0); 00118 if ((cmd == 0x80) || (cmd == 0x90) || (cmd == 0xA0) || (cmd == 0xB0) || (cmd == 0xE0)) { 00119 buf[2] = midi_read(); 00120 #if defined(_NO_eVocaloid_) 00121 if ((buf[0] & 0x0f) == 0x0f) { // CH.16 00122 return; 00123 } 00124 if ((buf[0] & 0x0f) == 0x00) { // CH.1 00125 buf[0] = (buf[0] | 0x0f); // Force change to CH.16 00126 } 00127 #endif 00128 midi.putc(buf[0]); 00129 midi.putc(buf[1]); 00130 midi.putc(buf[2]); 00131 } else if (cmd == 0xC0) { 00132 #if defined(_NO_eVocaloid_) 00133 if ((buf[0] & 0x0f) == 0x00) { // CH.1 00134 buf[0] = (buf[0] | 0x0f); // Force change to CH.16 00135 } 00136 #endif 00137 midi.putc(buf[0]); 00138 midi.putc(buf[1]); 00139 } else if (cmd == 0xD0) { 00140 midi.putc(buf[0]); 00141 midi.putc(buf[1]); 00142 } else if (cmd == 0xF0) { 00143 switch( buf[0] & 0x0F ) { 00144 case 0x00 : // SysEx 00145 case 0x07 : // SysEx2 00146 cnt = buf[1]; 00147 midi.putc(buf[0]); 00148 for(uint32_t i=1; i<cnt+1; i++) { 00149 midi.putc(midi_read()); 00150 } 00151 break; 00152 case 0x0f : // Meta event 00153 switch ( buf[1] ) { 00154 case 0x00: // Sequence number 00155 midi_read(); 00156 break; 00157 case 0x51: // Set tempo 00158 midi_read(); // len (== 3) 00159 tempo = midi_read(); 00160 tempo = (tempo << 8 ) | midi_read(); 00161 tempo = (tempo << 8 ) | midi_read(); 00162 tempo = tempo / 1000; 00163 org_tempo = tempo; 00164 //tempo += (ax * 10); 00165 DEBUG_PRINT("Set tempo = %d\n", tempo); 00166 break; 00167 case 0x2f: // End of Track 00168 midi_read(); // Read zero 00169 disable_timer(); 00170 STATE = 2; 00171 break; 00172 case 0x01: 00173 case 0x02: 00174 case 0x03: 00175 case 0x04: 00176 case 0x05: 00177 cnt = midi_read(); // len 00178 for(uint32_t i=0; i<cnt; i++) 00179 DEBUG_PRINT("%c", midi_read()); 00180 DEBUG_PRINT("\n"); 00181 break; 00182 default: 00183 cnt = midi_read(); // len 00184 for(uint32_t i=0; i<cnt; i++) 00185 midi_read(); 00186 break; 00187 } 00188 break; 00189 } 00190 } 00191 } 00192 00193 00194 void smf_main_loop(void) 00195 { 00196 if(STATE == 1) { 00197 if (TIMER < timer.read_ms()) { 00198 midi_play(); 00199 if (STATE != 2) 00200 delta_time_read(); 00201 } 00202 } 00203 } 00204 00205 void smf_init(void) 00206 { 00207 TIMER = 0; 00208 tempo = 500; // default value 00209 00210 uint32_t ch; 00211 for (ch=0; ch<16; ch++) { 00212 midi.putc(0xB0|ch); 00213 midi.putc(0x78); 00214 midi.putc(0x00); 00215 midi.putc(0xB0|ch); 00216 midi.putc(0x79); 00217 midi.putc(0x00); 00218 } 00219 00220 // Skip MIDI header 00221 for (uint32_t i=0; i<8; i++) { 00222 midi_read(); 00223 } 00224 00225 uint32_t format; 00226 format = (midi_read() << 8); 00227 format |= midi_read(); 00228 00229 if ( format > 1) { 00230 DEBUG_PRINT("This is not a MIDI format 0 file!\n", format); 00231 STATE = 2; 00232 return; 00233 } 00234 00235 uint32_t track; 00236 track = (midi_read() << 8); 00237 track |= midi_read(); 00238 00239 DEBUG_PRINT("Number of tracks : %d\n", track); 00240 00241 // timebase 00242 delta_time = (midi_read() << 8); 00243 delta_time |= midi_read(); 00244 DEBUG_PRINT("tempo = %d, delta_time = %d\n", tempo, delta_time); 00245 00246 // skip track chunk header 00247 for (uint32_t i=0; i<0x8; i++) 00248 midi_read(); 00249 00250 TIMER = (delta_time_read() * tempo) / delta_time ; 00251 DEBUG_PRINT("TIMER = %d\n", TIMER); 00252 STATE = 1; 00253 } 00254 00255 void skip() 00256 { 00257 STATE = 2; 00258 } 00259 00260 int main() 00261 { 00262 DEBUG_PRINT("Initializing...\n"); 00263 00264 btn.mode(PullUp); 00265 btn.fall(&skip); 00266 midi.baud(31250); 00267 00268 click.attach(&get_val, 0.2); 00269 00270 wait(3.5); // Wait few seconds for booting eVY1-Shleld. 00271 00272 #if !defined(_NO_eVocaloid_) 00273 const uint8_t aMsg[] = "\xF0\x43\x79\x09\x00\x50\x10" "4 a\0" "\xF7"; 00274 for (uint32_t i = 0; i < sizeof(aMsg)-1; midi.putc(aMsg[i++])); 00275 #endif 00276 00277 DEBUG_PRINT("Initialized.\n"); 00278 00279 char buf[50]; 00280 00281 #if defined(USE_DIRECTORY_LIST) 00282 DirectoryList dir("/sd"); 00283 if ( dir.error_check() ) { 00284 DEBUG_PRINT("directory could not be opened\r\n"); 00285 return -1; 00286 } 00287 00288 for ( int i = 0; i < dir.size(); i++ ) { 00289 sprintf(buf, "/sd/%s", dir[ i ].c_str() ); 00290 #else 00291 for ( uint32_t i = 0; i < 10; i++ ) { 00292 sprintf(buf, "/sd/%d.mid", i); 00293 #endif 00294 00295 fp = fopen(buf, "r"); 00296 if (fp == NULL) { 00297 DEBUG_PRINT("Unable to read the file \n"); 00298 } else { 00299 timer.reset(); 00300 timer.start(); 00301 smf_init(); 00302 if ( STATE == 2 ) { 00303 fclose(fp); 00304 #if defined(__MICROLIB) && defined(__ARMCC_VERSION) // with microlib and ARM compiler 00305 free(fp); 00306 #endif 00307 continue; 00308 } 00309 00310 DEBUG_PRINT("Now, playing (%s)... \n", buf); 00311 while (1) { 00312 smf_main_loop(); 00313 if (STATE == 2) { 00314 break; 00315 } 00316 } 00317 fclose(fp); 00318 #if defined(__MICROLIB) && defined(__ARMCC_VERSION) // with microlib and ARM compiler 00319 free(fp); 00320 #endif 00321 DEBUG_PRINT("End.\n"); 00322 } 00323 } 00324 }
Generated on Tue Jul 12 2022 18:49:53 by 1.7.2