Getting accurate time location of DAW's quarter notes

I wrote a VST that displays a timeline of midi events as they are played back. the VST just receives Midi events from a track in the DAW host and draws them in its window on a timeline as they are played back.

I’d also like to be able to display the quarter note locations that the DAW is using. I can simulate what I want by adding midi notes to the track at the quarter note locations. However, I would like to figure out how to do this without midi. Seems the way to approach it is to sense when the host has crossed a quarter note location inside of processBlock. I tried monitoring the AudioPlayHead CurrentPositionInfo for when the quarter note location changes. This works but is only as accurate as the size of the audio buffer.

Has anyone figured out a way to get sample accurate locations of the host’s beat locations?

thanks,
Gord

Not 100% sure this would work, but in the AudioPlayHead::CurrentPositionInfo, you can get the ppqPosition, and even the ppqPositionOfLastBar (although not universal). Of course you will get this info only at each buffer start. But if you see that between the buffer N-1 and buffer N you crossed a quarter note, I guess you can do a linear interpolation to know at which sample it was located.

EDIT: I’m not sure what your goal is, but you could decide yourself where the quarter note are and place the received notes accordingly. For example, draw a grid with each line separated by N pixels. These are your quarter notes. Then when you receive a MIDI event, compute it’s position in PPQ by using the AudioPlayHead ppqPosition + the MIDI event sample position converted to PPQ. This gives you the exact PPQ position of the event (sample accurate) that you can now put on your grid

For more accurate position info I calculate a ppqPerSample so I’m able to increment the ppqPosition for a certain sample number in the current buffer. Here is a snippet of my code.

const auto quartersPerBar = 4.0 * _posInfo.timeSigNumerator / _posInfo.timeSigDenominator;
_ppqPerSample = 1.0 / (_sr / quartersPerBar);

Thanks for the replies dimbouche and gustav-scholda. I really appreciate you taking the time to understand my question and post a solution!

After posting my question, I realized it would be possible to calculate the sample position of the last quarter note similar to the way the last two posters suggest.

Here are the basics of the approach:

In processBlock:

  • calculate samples/quarter note rate using the size of sample buffer passed in and the current ppqPosition and the previous value of ppqPosition.
  • if ppqPosition has increased to a new quarter note position since the previous ppqPosition then use samples/quarter note to interpolate the exact sample time of the new quarter note location.