I’m trying to sample a data stream (let’s say a slider’s output) that requires sampling at a varying frequency between 500Hz and 5000Hz.
The only way I can seem to do this is by using a conventional audio stream as the clock and simply omitting the values I don’t want. The amount of samples I omit varies based on how frequently I want to sample the data stream at any given point.
So I’ve been trying to create an audio clock that can achieve this and have just finished watching The Audio Programmer’s very helpful tutorial on creating a metronome. It’s exactly what I was after with one small caveat: the clock isn’t sample accurate and its precision lands anywhere within the user’s buffer size, for me: 480 samples, or 10ms (given a sample rate of 48000Hz).
So, in an attempt to overcome this, I’ve implemented a HighResolutionTimer and set the callback interval to 1 / sampleRate that counts up to each buffer callback / audio block. This should, in theory call back for each new sample between the buffer call backs, right?
It doesn’t. The interval between HighResolutionTimer callbacks is something like 2% as fast as it needs to be.
Here’s the output from my console:
Sample Rate : 48000
Samples Per Block : 480
Total Clock Samples : 1
Total Clock Samples : 2
Total Clock Samples : 3
Total Clock Samples : 4
Total Clock Samples : 5
Total Clock Samples : 6
Total Buffer Samples : 480
Total Clock Samples : 481
Total Clock Samples : 482
Total Clock Samples : 483
Total Clock Samples : 484
Total Clock Samples : 485
Total Clock Samples : 486
Total Clock Samples : 487
Total Clock Samples : 488
Total Clock Samples : 489
Total Clock Samples : 490
Total Buffer Samples : 960
‘Clock Samples’ are callbacks from the HighResolution timer and Buffer Samples are callbacks from the getNextAudioBlock. As you can probably guess, the clock samples should count up to the buffer samples before it resets for the next audio callback.
Anyway, here’s the code that renders that output (Metronome.cpp):
void Metronome::prepareToPlay(int samplesPerBlock, double sampleRate)
mSampleRate = sampleRate;
DBG("Sample Rate : " << sampleRate);
DBG("Samples Per Block : " << samplesPerBlock);
int mInterval = 1 / sampleRate;
void Metronome::countSamples(int bufferSize)
mTotalBufferSamples += bufferSize;
DBG("Total Buffer Samples : " << mTotalBufferSamples);
mTotalClockSamples = mTotalBufferSamples;
mTotalBufferSamples = 0;
mTotalClockSamples = 0;
DBG("Total Clock Samples : " << mTotalClockSamples);
So, is there any way to achieve a sample accurate clock?