PPQ and AudioPlayHead

Hey guys,
Can you take a look at my process block. I think thanks to Eyal I finally have AudioPlayHead working. Is there anything that I should do differently?

 void processBlock (AudioBuffer<float>& buffer, MidiBuffer& midiMessages)
{
    ScopedNoDenormals noDenormals;
    auto totalNumInputChannels  = getTotalNumInputChannels();
    auto totalNumOutputChannels = getTotalNumOutputChannels();

    for (auto i = totalNumInputChannels; i < totalNumOutputChannels; ++i)
        buffer.clear (i, 0, buffer.getNumSamples());

    getPlayHead()->getCurrentPosition(currentPositionInfo);
    float BPM = currentPositionInfo.bpm;                    
    beatNum = currentPositionInfo.ppqPosition -      
currentPositionInfo.ppqPositionOfLastBarStart;
    float numSampsPerBeat = 60.0f / BPM * mSampleRate;     
    float beatsPerSample = BPM / mSampleRate * 60.0f;
    
    float beatNumInSamps = beatNum * numSampsPerBeat;
    int numSamps = buffer.getNumSamples();

    float* leftChannel  = buffer.getWritePointer(0);
    float* rightChannel = buffer.getWritePointer(1);
    
    for (int sample = 0; sample < numSamps; sample++)
    {
        float targetSample = beatNum + beatsPerSample;
        DBG(targetSample);      
        
        if (targetSample > 2.0f){
            leftChannel[sample]  *= 0;
            rightChannel[sample] *= 0;
        } else {
            leftChannel[sample]  *= 1.0f;
            rightChannel[sample] *= 1.0f;
        }
    }
}

N.B. you can add three back ticks before and after the block of code, so it will be formatted and indented correctly

```
Your code here
```

And you can edit the original post, no need to post again :wink: Just click the pen

sorry I forgot

No worries :wink:

1st: DBG is a blocking command (it needs to lock until it is allowed to write to the console), so never call DBG from the audio thread (i.e. in processBlock()). Sometimes it is useful if you have no idea what’s going on, but expect the audio to be distorted then.

2nd: float targetSample = beatNum + beatsPerSample; never changes, so there is no point calculating it every time in the sample loop

3rd: leftChannel[sample] *= 0; is the same like setting it to zero, so why multiplying?

4th: leftChannel[sample] *= 1.0f; multiplying with 1.0f is a NOP, why doing it at all?

5th: float beatsPerSample = BPM / mSampleRate * 60.0f; careful with the order of * and /, they are not interchangeable. Better use brackets to make it clear, I as reader wouldn’t know by heart if it goes left to right or right to left without reading it up, so even if it’s correct, better write it explicitly

About the ppq, does it deliver what you expect? TBH, I haven’t played with that part yet, seems like I should check it out

Thanks Daniel
The thing I’m concerned with is figuring out what is the exact sample the sequenced event needs to be on.

Eyal told me the PPQ happens every process block, so I need to calculate it every sample, that’s why I have

float beatsPerSample = BPM / mSampleRate * 60.0f

in this post they are saying in order to calculate the PPQ every sample, you need to add the beatsPerSample to PPQ every sample.

could you take a look at it?

would this be correct?

void processBlock (AudioBuffer<float>& buffer, MidiBuffer& midiMessages)
{
    ScopedNoDenormals noDenormals;
    auto totalNumInputChannels  = getTotalNumInputChannels();
    auto totalNumOutputChannels = getTotalNumOutputChannels();

    for (auto i = totalNumInputChannels; i < totalNumOutputChannels; ++i)
        buffer.clear (i, 0, buffer.getNumSamples());

    getPlayHead()->getCurrentPosition(currentPositionInfo);
    float BPM = currentPositionInfo.bpm;                  
    beatNum = currentPositionInfo.ppqPosition - currentPositionInfo.ppqPositionOfLastBarStart;
    float numSampsPerBeat = (60.0f / BPM) * mSampleRate;     
    float beatsPerSample = BPM / (mSampleRate * 60.0f);
    
    float beatNumInSamps = beatNum * numSampsPerBeat;
    
    int numSamps = buffer.getNumSamples();

    float* leftChannel  = buffer.getWritePointer(0);
    float* rightChannel = buffer.getWritePointer(1);
    
    float targetSample = beatNum;
    
    for (int sample = 0; sample < numSamps; sample++)
    {
        targetSample += beatsPerSample;
        
        
        if (targetSample > 2.0f){
            leftChannel[sample]  = 0;
            rightChannel[sample] = 0;
        } 
    }
}

I don’t know, what you plan to do.
If you want to create a metronome, you want to fill the space starting at a full beat with sound for n samples, vs. your code simply set’s zeroes… so I doubt you will hear anything here…

1 Like

I have a four voice resonator. I’m trying to have different delay times(notes) per steps. here I was just trying to figure out the sequencing part.