Tempo Sync


#1

I'm trying to get a sample to trigger on the beat. 

When I hit play, from 1:1 in AU Lab, with the following code the first beat fails to play. 



   if (pstore.value[p::master_autoplay] == 1.0f) {

        AudioPlayHead::CurrentPositionInfo cpi;

        playhead->getCurrentPosition(cpi);

        // Get the current position information from the playhead.

        

        // Calcuate how many samples per beat, divide the current time in samples

        // by the samplesPerBeat.

        

        // This gets us the number of samples we are past the last beat. 

        

        // In the processing loop, later, we increment

        // offsetFromLastBeat as we process the sample.

        // And, if it reaches samplesPerBeat return to 0

        // And, if it's zero play a beat.

        

        if (cpi.isPlaying || cpi.isRecording) {

            samplesPerBeat = sr * (60.0 / cpi.bpm); // BREAKPOINT

            if (samplesPerBeat != 0.0) {

                offsetFromLastBeat = cpi.timeInSamples % samplesPerBeat;

            }

        } else {

            offsetFromLastBeat = -1; // do not auto play if sequencer stopped

        }

    }

When I hit play in AU Lab with a breakpoint set at BREAKPOINT the value of timeInSamples is already above 0.  So my first beat fails to trigger.  I presume that's because it's already processing a block.

Now I can hack this to work by looking for when the playback has started half way through an existing sample block and playing a beat fractionally late.   But is this the best way of tackling it at all?  

I'm presuming that as the documentation states: "getCurrentPosition(...): Fills-in the given structure with details about the transport's position at the start of the current processing block." there's no point in calling getCurrentPosition continuously for an update!

It works fine in Ableton. I presume that only starts playing at the beginning of a block.  

thoughts?   Are all other sequencers as well behaved as Ableton and is AU Lab an unfair test? 

 

 


#2

Replying to my own point, but should I not expect CurrentPositionInfo::timeInSamples to increment in a nice fashion?

} timeInSamples jumped (expected95878 but got 95884

} timeInSamples jumped (expected96908 but got 96904

} timeInSamples jumped (expected97416 but got 97417

} timeInSamples jumped (expected97929 but got 97928

} timeInSamples jumped (expected98440 but got 98439

} timeInSamples jumped (expected98951 but got 98954

Sometimes it goes backwards!  Wondered why I was getting the odd double beat!

I'll keep digging...


#3

 

could be a simple rounding error.  It's always off by one .... are you perhaps using an int where you should have a float in the calculation?


#4

I've written a little utility to measure the quality of data being passed.  AULab _averages_ an error of about 2 samples, Ableton is much better but still not 100%.   The error varies, so I don't think it's an off by one error in my code. And to the extent that I can follow the depths of Jule's library I don't think the problem is there either. 

To get the sequencer working reliably with everything I'm just tracking the last note played and sometimes sending notes a couple of samples late.  It's annoying through - this stuff should be accurate to the sample, no?

Is anyone else doing this stuff?


#5

Amazingly the error goes in both directions. Sometimes I get blocks that appear to overlap in 'timeInSamples' and other times there's a gap between them!


#6

Did you ever resolve this? I’m observing the same thing (timeInSamples jitter) and I’m trying to figure out the best way to work around it to achieve accurate DAW sync.

Jamie


#7

I did a savage hack trying to spot and ignore the duff data and avoiding duplicate notes…but it wasn’t a good quality solution…


#8

Thanks. I think I’m going to have to do something similar.