Go Down

Topic: MIDI latency during TX/RX (Read 948 times) previous topic - next topic

deseipel

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

https://github.com/deseipel/Arduino/blob/master/6.6.14.build

johnwasser

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.
Send Bitcoin tips to: 1L3CTDoTgrXNA5WyF77uWqt4gUdye9mezN
Send Litecoin tips to : LVtpaq6JgJAZwvnVq3ftVeHafWkcpmuR1e

deseipel

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).


Code: [Select]
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) {
   SMF.setFilename(nameFiles[filePOS]);
   tft.setTextColor(GREEN);
    tft.setCursor(5, 100);
      tft.println(nameFiles[filePOS]);
      tft.println(P);
}
else  //the next file differs from the one just played.
{
   SMF.setFilename(nameFiles[P]);
  oldP = P;
  filePOS= P;
  draw_menu();
     tft.setCursor(5, 120);
     tft.setTextColor(RED);
      tft.println(nameFiles[filePOS]);
      tft.println(P);
      tft.setCursor(10, 120);
      tft.print(oldP);
     
}
///////////////////////////////////////////////////////////////////////////////////////////////
   err = SMF.load();
  //////////////////////////////////////////////////////////////////////////////////////////////
  if (err != -1)
    {
      tft.setCursor(5, 140);
      tft.print("MIDI File Load Error");
      break;
  }
  else
  {
    SMF.setTempo(bpm); //should only have to set this once.
    // play/loop the file
    while (!SMF.isEOF())
    {
      if (SMF.getNextEvent())
        Sync();
      CheckMIDI();
     // SMF.setTempo(bpm);       
    }
  // SMF.close();
     SMF.restart();
   }
   ///////////////////////////////////////////////////////////////////
   draw_menu();
  } //while S == 1 closing bracket
}

deseipel

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. 

Code: [Select]
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

Code: [Select]
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;
Serial.write(0xF8);
}
}

Go Up