I've been using the MIDI library to 'map' certain notes to program changes and also send MIDI clock. But recently, I wanted to play MIDI files from an SD card, which is proving to be quite a challenge. I'm not sure why my code isn't working. Either the MIDI library functions work or the MIDIfile library functions work. But not both.
Note: the MIDIfile library is something I found that plays MIDI files from and SD card. It works, I know that. But not in my code with the MIDI library code:
#include <MIDIFile.h>
#include <MIDI.h>
#include <SdFat.h>
int MIDI_ENABLE = 19;
/*
8/9/13:
Things this sketch does:
------------------------------------
1. Program change up/down
a. note 60 is up, note 62 is down
2. "Mute" parts 1-7b (sets the volume to zero)
a. note 64 is part 1
b. note 66 is part 2
c. note 68 is part 3
d. note 70 is part 4
e. note 72 is part 5
f. note 74 is part 6
g. note 76 is part 6a
h. note 78 is part 6b
i. note 79 is part 7a
j. note 80 is part 7b
2. Can send a hard coded MIDI master clock signal.
TO DO:
----------------------------
Play a MIDI file from SD card, in sync with Master clock.
*/
//SoftwareSerial SSerial(2, 3);
#define DEBUG(x) Serial.print(x)
#define DEBUGX(x) Serial.print(x, HEX)
int led = 13;
const int chipSelect = 10;
//SD2Card SD;
SdFat SD;
MIDIFile SMF;
/* this is the MIDIfile section that handles playing of the MIDI files on the SD card*/
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 ((pev->data[0] >= 0x80) && (pev->data[0] <= 0xe0))
{
Serial.write(pev->data[0] | pev->channel);
Serial.write(&pev->data[1], pev->size-1);
}
else
Serial.write(pev->data, pev->size);
}
void sysexCallback(sysex_event *pev)
// Called by the MIDIFile library when a system Exclusive (sysex) file event needs
// to be processed thru the midi communications interface. MOst sysex events cannot
// really be processed, so we just ignore it here.
// This callback is set up in the setup() function
{
DEBUG("\nS T");
DEBUG(pev->track);
DEBUG(": Data ");
for (uint8_t i=0; i<pev->size; i++)
{
DEBUGX(pev->data[i]);
DEBUG(' ');
}
}
void midiSilence(void)
// Turn everything off on every channel.
// Some midi files are badly behaved and leave notes hanging, so between songs turn
// off all the notes and sound
{
midi_event ev;
// All sound off
// When All Sound Off is received all oscillators will turn off, and their volume
// envelopes are set to zero as soon as possible.
ev.size = 0;
ev.data[ev.size++] = 0xb0;
ev.data[ev.size++] = 120;
ev.data[ev.size++] = 0;
for (ev.channel = 0; ev.channel < 16; ev.channel++)
midiCallback(&ev);
}
long bpm = 120;
long tempo = 1000/(bpm/60);
long prevmillis = 0;
long interval = tempo/24; //interval is the number of milliseconds defined by tempo formula.
byte P = 0; //program or patch number
byte M1 = 0; //mute for part 1 off
byte M2 = 0; //mute for part 2 off
byte M3 = 0; //mute for part 3 off
byte M4 = 0; //mute for part 4 off
byte M5 = 0; //mute for part 5 off
byte M6a = 0; //mute for part 6a off
byte M6b = 0; //mute for part 6b off
byte M7a = 0; //mute for part 7a off
byte M7b = 0; //mute for part 7b off
byte S = 0; //stop/start bit