Midi Timecode


#1

Hi all,

might be not the right place to put but I desperately need a plugin that can convert the hosts
information to provide Midi Timecode to a Midi output?

I know, it’s the wrong way round but would like to sync Cubase to Ableton Live.

Thank you!

Jörg


#2

Why do u need a plugin for that you can easily do that with any sort of loopback midi driver (midi yoke).


#3

Hi atom,

not really as Cubase runs on a PC and Ableton on Mac. Also, Cuase can only sync to Midi Timecode,
not Midi Clock what Ableton provides.

Actually I could write such a plugin myself using juce but the still unclear point that keeps me
away is the missing math to send Midi events from the processblock to a Midi output on time.
I remember you posted the same issue here and somebody else as well
(http://www.rawmaterialsoftware.com/viewtopic.php?f=2&t=8499). Did you find the math to do that and
if yes, would you share the code?

Thank you!
Joerg


#4

No i never got the math to do it. I found i flag in the VST specs samplesToNextClock witch is a member of the VstTimeInfo structure that indicates when should the next midi clock occur

MIDI Clock Resolution (24 Per Quarter Note), can be negative (nearest clock). 

that would really help doing what you are trying to achieve, but this structure member is not included in the JUCE wrapper and i wasn’t able to access it without changing the VST wrapper code, so i just left it.

Also if you want to connect OSX and Windows via network/MIDI try http://www.tobias-erichsen.de/rtpMIDI.html it should work with the native OSX midi driver and link you to your windows machine.


#5

Thanks for the info.
Do you think that flag would help to fire hosts Midi events to Midi output on time? If yes,
shouldn’t we poke Jules to make this flag accessible.
I had some emails back and force with Urs from U-HE systems (Zebra softsynth) and his
friend/colleague Clemens and both don’t have a “just do that” solution for the problem…
They rather see this as a complicated task. But I heard that MidiQuest editors can be
used as VST and they are also working with Midi outputs. Can’t confirm as I don’t have
Midiquest installed.

BTW: I am already using rptMidi. Nice tool as long as you have a separate network running.
But the sync problem still exist as Ableton can only generate Midiclock and Cubase can only
read Midi TC.

Joerg


#6

Well my theory is that this flag indicates when a midi clock event (0xF8) should occur (and it points to a time in samples so it’s sample accurate witch is what we need). You can send MIDI START and prepareToPlay() and MIDI CONTINUE at the start of the first processBlock(), the problem is to keep up with the clock of the host.

However i think that even that flag might not be accurate enough for sending out through other MIDI Devices (other then the host has opened). Cause it’s the host that does all the processing and it has it’s own queue of messages.

So i really don’t know how good of a solution this is, but it’s the best i can think of.


#7

Looks like someone has already done that, and with JUCE even: http://code.google.com/p/pizmidi/source/browse/pizjuce/midiOut/src/midiOut.cpp


#8

Funny,

found the same a week ago and have to admit that diving into all this ppq stuff is really worth doing it.
Unfortunately pizMidi just seems to be a approach (it’s not working properly MTC wise) but I could manage to pull the needed information out of it.
The most important useful thing was to understand the way to send midi events on time and juce gives you everything you need to do so!
I am now able to generate Midi clock as well as MTC using the host time info, yeah! But now I am struggling to find the best math to
get around the rounding problems when syncing two devices at 44100 samplerate :frowning:

If you still need help, just tell me.

Cheers,
Joerg


#9

Well i’d love to implement the math in my own plugin so if you have anything working or that needs testing i have some synths around and i can test with, if you are willing to share ofcourse.


#10

Hi,

in regards to the above discussion, the below code snipped shows the way I
calculate the insert position for MTC quarter messages in the MidiBuffer.
I have shorten it down a bit to make it more understandable e.g. I skipped
all of the time calculations to create the proper quarter messages in this
example. I will provide the “ready to use” class later one once the problem
I have with the below code is solved.
The problem is that with this way of calculating the insert position I occasionally
hit the buffersize of the Midibuffer which triggers an assertion in juce_VST_Wrapper line 570.
In my humble understanding that should never happen but it does. I guess it has
something to do with rounding problems so I played arround with roundToInt
or roundDoubleToInt or at least the normal round function for the integer
but without success. the only way I could get it to work is to use a quite nasty
hack.

Overall, with the hack it works quite well and Cubase sticks to Ableton like a charme but
I don’t like this hack!

Could someone have a look what could cause the problem?

Thank you,
Joerg

void JK_MidiSync::generateMidiSync(AudioPlayHead::CurrentPositionInfo &lastPosInfo,
                                   const int pluginSendsSync,
                                   MidiBuffer &bufferToInject,
                                   const int bufferSize,    //Size of the AudioSampleBuffer, provided by processBlock, in this case it is 80
                                   const double sampleRate) //provided by processBlock, in this case it is 44100.0
{
	if (lastPosInfo.isPlaying || lastPosInfo.isRecording)
	{						
		const double frameRate = 24.0;
		
		const double ppqPerSample = 1.0 / (sampleRate / (lastPosInfo.bpm / 60.0)); 
		
		const double bufferSizeInPPQ = (double)(bufferSize) * ppqPerSample;
				   
		const int quarterMsgDistanceInSamples = roundToInt(sampleRate / (4.0 * frameRate));
				
		//Run through the Midi buffer to inject timecode messages on certain positions                  
		for (double i = lastPosInfo.ppqPosition; i < lastPosInfo.ppqPosition + bufferSizeInPPQ; i += ppqPerSample) 
		{                	
			//send MTC
			if ((pluginSendsSync & 0x1) == 1)
			{                       			                                     
				//get the virtual position in samples and the sample position of the 
				//start of the processblock to calculate the inject position in the buffer
				const int virtualSamplePos = (int)((i * 60.0 / lastPosInfo.bpm) * sampleRate);
				const int currentSamplePos = (int)((lastPosInfo.ppqPosition * 60.0 / lastPosInfo.bpm) * sampleRate);
				
				//Inject quarter messages 
				if (virtualSamplePos % quarterMsgDistanceInSamples == 0)
				{		
					int insertPos = virtualSamplePos - currentSamplePos;
					
					//nasty hack
               if (insertPos >= bufferSize)
                   insertPos = bufferSize - 1;
					
					//do the inject in the MidiBuffer here... 
				}
			}                
		}
	}
}

#11

Seems that line numbers have changed in vst wrapper. It’s line 579 that throws the assertion…

Joerg