PDA

View Full Version : midi timing in cubase vs reaper


olilarkin
03-16-2010, 02:13 PM
i am making a small midi triggered looper plugin and it seems that the MIDI timing works in reaper but not cubase. I have uploaded a video to demonstrate + code. Has anyone experienced this or know what it might be? I did a similar thing with just the VST sdk and got good timing in cubase.

The plugin should loop the last beat's worth of audio when a midi note is received.
GetSamplesPerBeat() seems to return the same on each host, but with Cubase the timing is all over the place. I find it very hard to debug these kinds of issues. Any tips would be much appreciated.

oli



http://www.olilarkin.co.uk/temp/midiproblem/


void Looper::ProcessDoubleReplacing(double** inputs, double** outputs, int nFrames)
{
// Mutex is already locked for us.

double* in1 = inputs[0];
double* in2 = inputs[1];
double* out1 = outputs[0];
double* out2 = outputs[1];
int samplesPerLoop = floor(GetSamplesPerBeat());

for (int offset = 0; offset < nFrames; ++offset, ++in1, ++in2, ++out1, ++out2)
{

while (!mMidiQueue.Empty())
{
IMidiMsg* pMsg = mMidiQueue.Peek();
if (pMsg->mOffset > offset) break;

// Handle the MIDI message.
int status = pMsg->StatusMsg();
switch (status)
{
case IMidiMsg::kNoteOn:
case IMidiMsg::kNoteOff:
int velocity = pMsg->Velocity();

//Note On
if (status == IMidiMsg::kNoteOn && velocity)
{
//mGain = 1.;
mNote = true;

}
//Note Off
else
{
mNote = false;
//mGain = 0.;
}
break;
default:
break;
}

mMidiQueue.Remove();
}

if(mNote)
{

*out1 = mBuffer[mCount2++];

mCount2 %= samplesPerLoop;

}
else
{
mCount2 = 0;

mBuffer[mCount++] = *in1;

mCount %= samplesPerLoop;

*out1 = *in1;
}

*out2 = *out1;
}

mMidiQueue.Flush(nFrames);

}

void Looper::Reset()
{
TRACE;
IMutexLock lock(this);
mMidiQueue.Resize(GetBlockSize());

mSampleRate = GetSampleRate();
mSamplePeriod = 1./mSampleRate;
mCount = 0;
}

cc_
03-24-2010, 03:47 AM
Did you ever get to the bottom of this? The only thing I found different between Reaper and Cubase4 was the way looping of the transport worked, did you have that turned on in your testing?

olilarkin
03-24-2010, 01:29 PM
>did you have that turned on in your testing?

yep... what did you find out about it. I didn't get any further with this yet

oli

cc_
03-25-2010, 01:33 AM
It was a while ago, so (Reaper at least) may have changed, but what I saw is that when Reaper looped back it always reported the time for that first frame as exactly the time of the start loop marker. That's not correct usually as the loop point usually happens part way through a frame.

Cubase4 on the other hand did report the looping back frame correctly - the start of the frame being near the end of the loop, but then for the next 1 or two frames it would report the musical position incorrectly as being after the end of loop. So, say the loop start = start of bar 1 and loop end = start of bar 2. In 4/4 time that corresponds to musical positions 4 and 8, cubase would report something like:
7.96 7.99 8.02 8.05 4.08
Instead of:
7.96 7.99 4.02 4.05 4.08

The other thing I found was that the standard IPlug time functions weren't sufficient to handle the looping case correctly, so I added my own GetTime() function which returns all the data you need to work out whether the time is going to loop in the middle of the current frame.

BTW the way I debug this kind of stuff on OSX is just to stick printf's in (pretty old school I know!). Then the prints come through in the console window in xcode (or just run your sequencer from a terminal). I know you're not meant to print from the inside of your real time processing loop, but in practice it seems to work fine.

On Windows there are TRACE builds in the IPlug projects but I have never used them.

dub3000
03-25-2010, 01:45 AM
doesn't reaper send shorter frames when it's at the end of a loop? (and wasn't this what was crashing some dodgy plugins a while back?)

It was a while ago, so (Reaper at least) may have changed, but what I saw is that when Reaper looped back it always reported the time for that first frame as exactly the time of the start loop marker. That's not correct usually as the loop point usually happens part way through a frame.

Cubase4 on the other hand did report the looping back frame correctly - the start of the frame being near the end of the loop, but then for the next 1 or two frames it would report the musical position incorrectly as being after the end of loop. So, say the loop start = start of bar 1 and loop end = start of bar 2. In 4/4 time that corresponds to musical positions 4 and 8, cubase would report something like:
7.96 7.99 8.02 8.05 4.08
Instead of:
7.96 7.99 4.02 4.05 4.08

The other thing I found was that the standard IPlug time functions weren't sufficient to handle the looping case correctly, so I added my own GetTime() function which returns all the data you need to work out whether the time is going to loop in the middle of the current frame.

BTW the way I debug this kind of stuff on OSX is just to stick printf's in (pretty old school I know!). Then the prints come through in the console window in xcode (or just run your sequencer from a terminal). I know you're not meant to print from the inside of your real time processing loop, but in practice it seems to work fine.

On Windows there are TRACE builds in the IPlug projects but I have never used them.

cc_
03-25-2010, 03:06 AM
I never saw that, I was getting my start of bar code triggered twice, once in the middle of the last frame and once at the start of the start of loop frame. But I do remember at some point it did change from clicking every time it looped to not clicking... can't remember if that was before or after I was having my start of bar problems.