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

Dependencies:   DirectoryList SDFileSystem mbed

Fork of eVY1_SMF_player by Toyomasa Watarai

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

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 }