// 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 true // set to 1 for MIDI output, 0 for debug output #define GENERATE_TICKS 1 #define DEBUGS(s) uart.print(s) #define DEBUG(s, x) { uart.print(F(s)); uart.print(x); } #define DEBUGX(s, x) { uart.print(F(s)); uart.print(x, HEX); } #define uart_RATE 115200 #if defined(ARDUINO_ARCH_SAMD) #define SD_SELECT 4 int pin_out[6] = {13, 11, 10, 9, 6, 5}; #else #define SD_SELECT 4 int pin_out[6] = {13, 27, 33, 15, 32, 14}; #endif #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 = "Music1.mid"; // simple and short file #if GENERATE_TICKS //uint32_t lclBPM = 135; #define _lclBPM 90 uint32_t lclBPM = _lclBPM; #endif SdFat SD; MD_MIDIFile SMF; #if defined(ARDUINO_ARCH_SAMD) #define uart SerialUSB #endif 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_); uart.print(" "); uart.print((channel_), HEX); uart.print(" "); uart.print(pin_out[channel_-0x24]); #endif if (intensity_>0) { digitalWrite(pin_out[channel_-0x24], HIGH); #if DEBUG_ON uart.println(" Solenoide ON"); #endif } else if (intensity_==0) { digitalWrite(pin_out[channel_-0x24], LOW); #if DEBUG_ON uart.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; #if DEBUG_ON uart.begin(uart_RATE); #endif delay(4000); #if defined(ARDUINO_ARCH_SAMD) analogReadResolution(12); #endif 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_HALF_SPEED)) { DEBUGS("\nSD init fail!"); while (true) ; } // Initialize MIDIFile SMF.begin(&SD); SMF.setMidiHandler(midiCallback); SMF.looping(false); // use the next file name and play it DEBUG("\nFile: ", loopfile); SMF.setFilename(loopfile); err = SMF.load(loopfile); if (err != MD_MIDIFile::E_OK) { DEBUG("\nSMF load Error ", err); while (true); } } void loop(void) { //uart.println(analogRead(A0)); #if GENERATE_TICKS static bool fBeat = false; static uint16_t sumTicks = 0; uint32_t ticks = tickClock(); lclBPM = map(analogRead(A0), 0, 4095, -(_lclBPM - 30), (_lclBPM - 30)) + _lclBPM; #if DEBUG_ON //uart.println(lclBPM); #endif if (ticks > 0) { SMF.processEvents(ticks); // SMF.isEOF(); // side effect to cause restart at EOF if looping // sumTicks += ticks; // if (sumTicks >= SMF.getTicksPerQuarterNote()) // { // sumTicks = 0; // fBeat = !fBeat; // } if(!SMF.isEOF()){ // side effect to cause restart at EOF if looping sumTicks += ticks; if (sumTicks >= SMF.getTicksPerQuarterNote()) { sumTicks = 0; fBeat = !fBeat; }} } #else // play the file if (!SMF.isEOF()) { SMF.getNextEvent(); } #endif*/ }