Dedicated Midi-Clock Sync - Module idea - Programmer needed

It is unavoidable to use a queue (MIDI messages have to be serialized and you can’t send two or more messages the same time) and have some latency (MIDI has a much lower „transmission rate“ than audio, 31250 bits per second, without overhead you get 3125 bytes per second and most MIDI messages are 3 bytes long, so about 1000 messages per second).

2 Likes

If you want you can contact me about that privately. I have been working too on a collection of MIDI modules but nothing ready for release yet.

4 Likes

Like I said, this thread is for gathering ideas, plus my coding skills are … well lets say, when I learned programming there was a company called SUN that did JAVA and PHP was called Private HomePage tool and was not object-oriented at all :joy::joy:

yes, therefor the idea of a separate module, cause as far I unterstand it 0xF-Mesages are only 1 byte long, so this module could ignore all messages bigger than one byte, maybe (big maybe) this gives enhancement:

 if (message->size() != 1)
    return;

and I found this:

// RtMidiIn constructor
    midiin = new RtMidiIn();
....... 
// Set our callback function.  This should be done immediately after
// opening the port to avoid having incoming messages written to the
// queue instead of sent to the callback function.
    midiin->setCallback( &mycallback, &clock_count );

in https://github.com/thestk/rtmidi/blob/master/tests/midiclock.cpp

and then maybe directly push the prefilterd messages it into the function that calls dsp::PulseGenerator

 unsigned int msg = message->at(0);
  if (msg == 0xFA)
    dsp::PulseGenerator.trigger(1e-3);
  if (msg == 0xFB)
    dsp::PulseGenerator.trigger(1e-3);
  if (msg == 0xFC)
    dsp::PulseGenerator.trigger(1e-3);
  if (msg == 0xF8) {
#something to include 24 PPQN and maybe others
 dsp::PulseGenerator.trigger(1e-3);
....

But that is as far as my skills take me :D :D
1 Like

This might work. You just need to call PluseGenerator::process in Module::process and output 10V if it returns true.

1 Like

And on the sending part of this module (so to say, as master), no calc’s on IF this message is a system-message, but directly sending to the rtmidi output

if(bool starttrigger)
  message.push_back( 0xFA );
if(bool stopTrigger)
  message.pushback( 0xFC );
if(bool clkTrigger)
  message.pushback( 0xF8 );

message.clear();  
midiout->sendMessage( &message );

or something like this

btw. here i noticed, that Renoise f.e. starts sending the 0xF8 directly and all the time, even if no Track is running or recording, so that other clock receivers can already adjust to the BPM. This, paired with a dedicated Midi-Channel in the setup (Midi-system messages only on Midi-Channel 1) might be a nice idea too.

If we then can set the BPM in sync24 (24 PPQN) as deltatime in this module it could

if (mode == clockMaster)
  message.pushback( 0xF8 ) 
 midiout->sendMessage(&message) 'til the end of the universe and back in deltatime;

Ofc the other midi system-messages (Start /stop / continue) have higher priority over clock and can override this message IF 2 of the trigggers occur at the same time because the compensation of this is the up to the other software.

Haven’t read this whole thread, but my guess of what you’re experiencing is that the Rack MIDI driver doesn’t attempt to synchronize MIDI timestamps with audio. The midi::Message struct has no timestamp field. Therefore, MIDI messages are consumed as soon as they enter the queue of MIDI-CC etc, regardless of when they happened relative to the audio buffer.

Please note that I don’t support “virtual” audio/MIDI devices, only real hardware. However, this is an issue with hardware that sends MIDI timeclocks.

2 Likes

Thanks @Vortico for your feedback.

and yes, this module (or code) is only intended regarding the Midi-System Message issues wich real hardware (or other software) have when sending and receiveing Midi-System Messages.

To explain my intension a bit: I came up with this idea cause I tend to use VCV more and more as my main DAW with my other synths and DIY Modular (yes, even my Midibox Seq V4 gets dusty :smiley: :smiley: ). The correct timing on start (0xFA) could open a new way of composing for me, where VCV is the Master and I can use Ardour’s (or Cakewalk’s or …) recording features that also offer overdub or layering of tracks. I can then also use features like “location markers” or “punch recording” I can then sequence and record my HW-Synth in seperate sessions, … to be continued

1 Like

slightly OT, but I wouldn’t use Beatstep as a benchmark for stable Midi clock. I sold mine partly because it drifted so much (i was lucky also to be able to get a Cirklon without having to wait for 2 yrs…). I’d vouch for the ERM, which is decent and useful for all sorts of things (swing / offset).

ps. ymmv, Arturia drivers may have got better, but for me it was poor.

There is a 50% swing defaulted on a Beatstep there is no way to change it to 0. Not sure if the Pro has that ability.

haha that is kinda hilarious! I had the Beatstep pro for a while but it was too long ago for me to remember the features exactly. I think it had swing… but defo remember the timing jitter was considerable.

I never noticed that swing on my beatstep.

Hi all,

still wrapping my noob mind over this and have no clue if @stoermelder and @23volts are also wrapping their minds over this.

Am I correct, that, on VCV startup the midi structures are initiated and all incoming Midi-messages are written to the InputQueue :: Input (in Midi.hpp) with a size of

int queueMaxSize = 8192; ??

All midi Modules I see always call

midi::InputQueue midiInput;

to process the midimessages?

And also in midi.hpp

struct Message {
	uint8_t size = 3;

assumes that all midimessages are 3 byte long? Wich works perfect on Midimessages, except SytemMessages.

So, there are 2 option:

  1. create a new virtual Midiinterface that includes rtmidi directly, wich is, correctly, not supported by @Vortico or
  2. rework the existing core-files with an inputswitch, that,
if (message->size == 1) => Don't write to queue
else size = 3;

and add a new struct that can be called only for the special case of the SystemMessages?

Or is this over the top? Can I already access the midi::message directly and filter, if messages are size == 1 and process thse and skip all the rest?

Would the second option be worth as a request on github?

1 Like
4 Likes

Aha! Andrew:

Sure, just use Input instead of InputQueue

Would be interesting if that makes a difference for MIDI-clock, if it’s not already implemented that way in the Core MIDI module.

Tried it yesterday … but I am a shitty c++ programmer so my first Module did ABSOLUTELLY NOTHING.

Well at least it did build :joy::joy::joy:

1 Like

No, has nothing to do with it. The issue you’re describing is because midi::Message does not contain a timestamp, so MIDI modules do not attempt to correlate MIDI timestamps with the engine frame number.

1 Like

@Vortico sorry to bother again, but …

is this on rtmidi.cpp side or generally? Or is this regarding the midi::message from vcv?

Would it be possible (or would it be of interrest) to include or set a TIMESTAMP in the midi::message for the special case of 0xF message in Rack v2.x.x.?

Ooohhh, now all we need is a module for sending (and receiving maybe also) MIDI program change :wink:

I don’t address feature requests on this forum. See the forum rules.

Sorry … moved to https://github.com/VCVRack/Rack/issues/1654