FortySevenEffects / arduino_midi_library

MIDI for Arduino
MIT License
1.62k stars 258 forks source link

sendTimeCodeQuarterFrame() documentation request #113

Open scottc11 opened 5 years ago

scottc11 commented 5 years ago

Would someone mind sharing an example on how to use the sendTimeCodeQuarterFrame() function? It is unclear to me what the DataByte parameter should be equal to.

I assumed just calling this function (with no parameters) would send 24 PPQ's but that isn't an option, so instead I passed the MIDI Clock byte 0xF8 and executed the function 24 times???

void setup() {
  // DIGITAL PIN 3 is used for detecting tempo.
  attachInterrupt(digitalPinToInterrupt(3), sendClockPulse, FALLING); // when input goes low, send pulse
}

void sendClockPulse() {
  step += 1;
  if (step % 4 == 1) {
    for (size_t i = 0; i < 24; i++) {
        MIDI.sendTimeCodeQuarterFrame(0xF8);
    }
  }
}

This is indeed sending the MIDI clock code to my external device, but is far from keeping anything in sync as is rather erratic.

franky47 commented 5 years ago

Here's the part of the MIDI specification that relates to MTC QuarterFrame messages: http://www.somascape.org/midi/tech/spec.html#syscommsgs

If you want to keep things synchronized, you will have to use a timer to keep track of internal time (or use millis), and send either Clock messages or MTC Quarter Frames, depending on whether you just want beat sync or absolute time sync.

alf45tar commented 5 years ago

Here an example for you

https://github.com/alf45tar/PedalinoMini/blob/master/src/MidiTimeCode.cpp

mink99 commented 5 years ago

another Example: based on a timer.... the interesting macros are

#define lo_nibble(b) (byte)(b & 0x0F)
#define hi_nibble(b) (byte)((b & 0xF0) >> 4 )

mtconly.zip

The Basic send is :

void sendMTCQuarterMessage()
{
  byte toSend;
  switch (msgCount)
  {
    case 0:
      toSend = 0x00 | lo_nibble(ff);
      break;
    case 1:
      toSend = 0x10 | hi_nibble(ff);
      break;
    case 2:
      toSend = 0x20 | lo_nibble(ss);
      break;
    case 3:
      toSend = 0x30 | hi_nibble(ss);
      break;
    case 4:
      toSend = 0x40 | lo_nibble(mm);
      break;
    case 5:
      toSend = 0x50 | hi_nibble(mm);
      break;
    case 6:
      toSend = 0x60 | lo_nibble(hh);
      break;
    case 7:
      toSend = 0x72 | hi_nibble(hh);  //defaults to 25 ....
      //toSend = 0x70 | hi_nybble(hh) | 0b00100000;   //would be 24
      break;
  }
  MidiPort.write(0xF1);
  MidiPort.write(toSend);
#ifdef USE_USB
  midiEventPacket_t event = {MIDI_COMMAND_SYSEX_2BYTE, 0xF1, toSend, 0};
  MidiUSB.sendMIDI(event);
  MidiUSB.flush();
#endif

  msgCount++;
  if (msgCount > 7) msgCount = 0;

}

Preroll is a special feature for my beloved Fostex D2424, as it does not "start" at 00:00:00:00 but at 23:59:55:17. so if i'd rewind to 00:00:00:00 it would start playback/record at 00:00:05:00....