giada icon indicating copy to clipboard operation
giada copied to clipboard

Broken MIDI sync

Open monocasual opened this issue 8 years ago • 4 comments
trafficstars

https://giadamusic.com/forum/viewtopic.php?f=8&t=1444

monocasual avatar Jun 28 '17 19:06 monocasual

I sniffed the MIDI output of Giada in MTC mode and compared it with that of Ardour. First thing first, Giada seems to use 24 fps, while Ardour uses 30. Shouldn't there be an option to pick the frame rate? Hmm.. Only quarter-frame messages are being sent. Ardour also sends full time codes at each start, stop and jump. Perhaps lack of full time codes made OP's gear confused. Let's not forget that MTC CANNOT be used for sensing changes in tempo and while using MTC, the tempo must be set manually on each device. This is why I feel that MTC should be treated as a separate output.

I think I'll manage to clean up the situation with Midi clocking, heck, maybe I'll even try and handle MIDI clock inputs.

tomek-szczesny avatar Jan 26 '19 15:01 tomek-szczesny

@tomek-szczesny thanks for the investigation! Yes, many options are dumbly hardcoded in the MIDI sync code. The original implementation was little more than a proof of concept. That's why a complete overhaul would be welcome.

monocasual avatar Jan 26 '19 15:01 monocasual

I took a peek at this issue today and indeed something very strange is going on. I did some research and found out that MTC can work with 24, 25 or 30fps (ignoring the obscure 29.97 fps for now). This, however, is also encoded within the message itself, and so it happens that Giada sets responsible bits to zero, hence unwillingly choosing 24fps.

However today when I tried sniffing Giada's MTC output, I got quarter frames each 80ms - at 24fps it should be around 10.5ms regardless of bpm.

conf.midiTCfps inside giada.conf is set to 25 for whatever reason. I don't think this should sit in config file anyway.

clock::init() computes a midiTCrate_ value that represents how many frames shall pass before sending another quarter frame. midiTCrate_ = (sampleRate / midiTCfps) * G_MAX_IO_CHANS; // stereo values It does something that frankly I do not understand. Why multiplying by G_MAX_IO_CHANS? Seems totally unrelated, but I'd rather ask before I start deleting stuff.

The following condition probably should be ">=" instead. if (midiTCframes_ > conf::conf.midiTCfps)

Summing up, I think that the following needs to be done:

  • Define what exactly do we want to send in MTC, a time position on the seq that hops back to 0 on each loop, or a time since sequence started playing,
  • Separate MIDI clocking into midiClock.cpp
  • Convert into user-selectable 24/25/30fps MTC (arguably 30fps is the most common these days, also 44100 isn't divisible by 24)
  • Remove consts from conf file, And for the future:
  • Make dedicated MTC and MIDI Clock outputs But I think this can wait for the legendary connection matrix to come around..

tomek-szczesny avatar Jul 25 '20 17:07 tomek-szczesny

So yeah, I did even more reading and now it's clear to me what went wrong.

Quarter frames are expected to be sent every quarter of the MTC clock frame, that is about 8.3 - 10.5ms depending on the setting. Right now Giada sends four quarters at once on every MTC frame.

I did some spying on Ardour's behavior and found out that if playback speed is altered in any way, it sends full frames only. Come to think of it, that's the only reasonable way if we stretch time.


Anyway, I started implementing stuff, and some problems might arise in the process. I noticed that not only 44100 isn't divisible by 24, but (30*4) as well. Still the product is in order of hundreds of frames, so I think this will work, but MTC quarter-frame jitter below 1% is to be expected in some circumstances. Also, stuff will break whenever loop lenght is not a multiple of (1/12)s, unless MTC keeps track of frames on its own.

tomek-szczesny avatar Jul 25 '20 21:07 tomek-szczesny

Done in 0.24, to be released soon. Closing.

gvnnz avatar Mar 08 '23 21:03 gvnnz