MIDI latency during TX/RX

Hi guys,

I have a Mega, a MIDI shield and a 1.8 TFT w/joystick. I'm sending MIDI data to a synth and at the same time monitoring the input for notes (from a different source than the synth). The MIDI data I'm 'Playing' is very small, one track, 12 bar MIDI files. I've noticed that when I send notes to my device, that it jitters a little and throws the timing off, ever so slightly.

Im' using Marco's MIDIfile library to play the MIDI files from SD cards. Code is at this url. If you have any general advice about MIDI in/out and if a MEGA can send/receive without much trouble, let me know. I have a feeling that my Check MIDI function is working but it may be slowing down the playing of the midi file. thanks


I would suspect the delay is in reading from the SD card. Perhaps there is a way to buffer the data from the SD card and use a timer to send the notes out on time.

thanks for the comments

here is the code I run when a Play command is issued. I’m still relatively new, so there may be a better workflow. But basically, this checks to see if the current file name has changed and then loads & plays the file, restarts it, etc. Basically attempts to loop the file and queue up a new file if that’s occurred.

This works aside from the latency of loading the files (I believe that may be the issue). there are two areas I’m intersted in:

  1. I shouldn’t have to reload the file if I don’t queue up a different filename, it should just loop.
  2. Is there a way to preload the queued up file (the one that I choose while the existing one is playing). ?

Again, I’m looking to loop a file unless I queue up another. The files are very small (1 track MIDI files, 12 bars long).

void Play(){
  //play the currently selected midi file *********************************************************
while (S == 1)  //while the playback has started
  int  err = -1;
  //  for (uint8_t i=0; i<ARRAY_SIZE(tuneList); i++)
  // reset LEDs
  // use the next file name and play it
  //    SMF.setFilename(tuneList[i]);
 // SMF.setFilename(nameFiles[filePOS]);  ///do not move this
 if (P == oldP) {
    tft.setCursor(5, 100);
 else  //the next file differs from the one just played.
  oldP = P;
  filePOS= P;
     tft.setCursor(5, 120);
      tft.setCursor(10, 120);
   err = SMF.load();
  if (err != -1)
      tft.setCursor(5, 140);
      tft.print("MIDI File Load Error");
    SMF.setTempo(bpm); //should only have to set this once.
    // play/loop the file
    while (!SMF.isEOF())
      if (SMF.getNextEvent())
     // SMF.setTempo(bpm);       
  // SMF.close();
  } //while S == 1 closing bracket

I've done quite a bit of tinkering and for the life of me, I can't figure out what's wrong. I was able to send a more reliable clock msg by switching to micros() however. MIDI OX recieves the bpm that I send more accurately using micros().

I'm playing a MIDI file from the sd card (to a synth) and also sending MIDI clock msgs (start/stop, clock sync) to a sequencer. What I'm looking for is for the file to play in sync with the sequencer. But it seems like it drifts by the 4th bar. Either the sequencer is slow or the MIDI file player is too fast.

Yesterday I thought a timer/interrupt would help, but today I'm not so sure. The MIDI player code seems correct.

void MIDIFile::calcMicrosecondDelta(void) 
// 1 tick = microseconds per beat / ticks per Q note
// The variable "microseconds per beat" is specified by a MIDI event carrying 
// the set tempo meta message. If it is not specified then it is 500,000 microseconds 
// by default, which is equivalent to 120 beats per minute. 
// If the MIDI time division is 60 ticks per beat and if the microseconds per beat 
// is 500,000, then 1 tick = 500,000 / 60 = 8333.33 microseconds.
    if ((_tempo != 0) && (_ticksPerQuarterNote != 0))
        _microsecondDelta = (60 * 1000000L) / _tempo;   // microseconds per beat
        _microsecondDelta = _microsecondDelta / _ticksPerQuarterNote;   // microseconds per tick

My code to check if to send clock is

void MIDIFile::sendClock(void)
uint32_t currentMicros = micros();

uint16_t bpm = getTempo();
uint32_t interval = (60000000/(24 * bpm)); 

  if((currentMicros - prevmicros >= interval) && (setClock == true)) {
    // save the last time.
        prevmicros = currentMicros;