// Play a file from the SD card in looping mode, from the SD card. // Example program to demonstrate the use of the MIDFile library // // Hardware required: // SD card interface - change SD_SELECT for SPI comms #include #include #define DEBUG_ON 1 // set to 1 for MIDI output, 0 for debug output #define GENERATE_TICKS 1 #define DEBUGS(s) Serial.print(s) #define DEBUG(s, x) { Serial.print(F(s)); Serial.print(x); } #define DEBUGX(s, x) { Serial.print(F(s)); Serial.print(x, HEX); } #define SERIAL_RATE 115200 int pin_out[6] = {7, 6, 5, 4, 3, 2}; // SD chip select pin for SPI comms. // Arduino Ethernet shield, pin 4. // Default SD chip select is the SPI SS pin (10). // Other hardware will be different as documented for that hardware. #define SD_SELECT 10 #define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0])) // The files in the tune list should be located on the SD card // or an error will occur opening the file and the next in the // list will be opened (skips errors). const char *loopfile = "sample_5.mid"; // simple and short file #if GENERATE_TICKS //uint32_t lclBPM = 135; uint32_t lclBPM = 60; #endif SdFat SD; MD_MIDIFile SMF; byte state_ = 0; byte channel_ = 0; byte intensity_ = 0; void midiCallback(midi_event *pev) // Called by the MIDIFile library when a file event needs to be processed // thru the midi communications interface. // This callback is set up in the setup() function. { #if DEBUG_ON DEBUG("M T", pev->track); DEBUG(": Ch ", pev->channel+1); DEBUGS(" Data"); #endif state_ = pev->data[0]; channel_ = pev->data[1]; intensity_ = pev->data[2]; #if DEBUG_ON DEBUGX(" ", state_); DEBUGX(" ", channel_); DEBUGX(" ", intensity_); Serial.print(" "); Serial.print((channel_), HEX); Serial.print(" "); Serial.print(pin_out[channel_-0x24]); #endif if (intensity_>0) { digitalWrite(pin_out[channel_-0x24], HIGH); #if DEBUG_ON Serial.println(" Solenoide ON"); #endif } else if (intensity_==0) { digitalWrite(pin_out[channel_-0x24], LOW); #if DEBUG_ON Serial.println(" Solenoide OFF"); #endif } } #if GENERATE_TICKS uint16_t tickClock(void) // Check if enough time has passed for a MIDI tick and work out how many! { static uint32_t lastTickCheckTime, lastTickError; uint8_t ticks = 0; uint32_t elapsedTime = lastTickError + micros() - lastTickCheckTime; uint32_t tickTime = (60 * 1000000L) / (lclBPM * SMF.getTicksPerQuarterNote()); // microseconds per tick tickTime = (tickTime * 4) / (SMF.getTimeSignature() & 0xf); // Adjusted for time signature if (elapsedTime >= tickTime) { ticks = elapsedTime/tickTime; lastTickError = elapsedTime - (tickTime * ticks); lastTickCheckTime = micros(); // save for next round of checks } return(ticks); } #endif void setup(void) { int err; Serial.begin(SERIAL_RATE); delay(4000); Serial.println("Hola"); for(int i=0; i<6; i++) { pinMode(pin_out[i], OUTPUT); digitalWrite(pin_out[i], LOW); } DEBUGS("\n[MidiFile Looper]"); // Initialize SD if (!SD.begin(SD_SELECT, SPI_FULL_SPEED)) { DEBUGS("\nSD init fail!"); while (true) ; } // Initialize MIDIFile SMF.begin(&SD); SMF.setMidiHandler(midiCallback); SMF.looping(true); // use the next file name and play it DEBUG("\nFile: ", loopfile); SMF.setFilename(loopfile); err = SMF.load(); if (err != -1) { DEBUG("\nSMF load Error ", err); while (true); } } void loop(void) { #if GENERATE_TICKS static bool fBeat = false; static uint16_t sumTicks = 0; uint32_t ticks = tickClock(); if (ticks > 0) { //LCDBeat(fBeat); SMF.processEvents(ticks); SMF.isEOF(); // side effect to cause restart at EOF if looping //LCDbpm(); sumTicks += ticks; if (sumTicks >= SMF.getTicksPerQuarterNote()) { sumTicks = 0; fBeat = !fBeat; } } #else // play the file if (!SMF.isEOF()) { SMF.getNextEvent(); } #endif }