Getting BPM and Beats

I spent hours trying to figure out how to get BPM and Beats from the host. I looked at the JuceDemoPlugin but I really don't understand how to port that into my plugin.

I just need to get BPM and Beats in my plug-in processBlock, what can I do? I understand that I have to use AudioPlayHead::CurrentPositionInfo but how?

Thanks in advance.

The BPM is given in CurrentPositionInfo::bpm (?)

I used this in PluginProcessor.h

  AudioPlayHead::CurrentPositionInfo playHead;

and in PluginProcessor.cpp (inside processBlock)

DBG(String(playHead.bpm));

and I keep getting 0.

I'm using Logic as DAW.

get a look at the AudioPlayHead documentation.

you got to do something like that  :


AudioPlayHead playHead;
AudioPlayHead::CurrentPositionInfo currentPositionInfo;
playHead.getCurrentPosition (currentPositionInfo);

 

 

 

 

 

I'm trying to understand but I'm still a newbie with C++.

I tried as you said but I got this error on the first line

Field type 'juce::AudioPlayHead' is an abstract class.

 

Could you explain step by step what should I do? Thanks.

oh, yep. ok, so in your class that inherits from AudioProcessor :

- in the .h :

private:
    AudioPlayHead* playHead;
    AudioPlayHead::CurrentPositionInfo currentPositionInfo;

and in .c, in your processBlock method :


playHead = this->getPlayHead();
playHead->getCurrentPosition (currentPositionInfo);
    
just after you can look at currentPositionInfo.bpm
    
 

4 Likes

Great! Thanks a lot!

I noticed that the documentation for AudioPlayHead specifically mentions not storing pointers to the object outside of the processBlock() function, so I would suggest avoiding the above solution and, instead, keeping your declarations inside of the processBlock.

Interestingly, I also note that getCurrentPosition() is deprecated and that getPosition() should instead be used. However, I encountered issues when using the latter, so stuck with the deprecated approach.

In case others find it useful, I was able to retrieve the BPM by placing this code inside of the processBlock() function:

juce::AudioPlayHead* playHead = getPlayHead();

if (playHead != nullptr) {
    // This approach didn't work for me, but leaving here for comparison:
    //juce::Optional<juce::AudioPlayHead::PositionInfo> positionInfo = playHead->getPosition();
    juce::AudioPlayHead::CurrentPositionInfo* info = new juce::AudioPlayHead::CurrentPositionInfo();
    auto isAvailable = playHead->getCurrentPosition(*info);
    
    if (!isAvailable)
        DBG("Not available!");

    // You would assign to a module level variable at this point, for tracking elsewhere
    auto bpm = info->bpm;
    DBG("Host BPM: " << bpm);
}

In fact, the above approach is a bit long-winded nowadays. Instead, you can do the following:

    auto tmp_bpm = getPlayHead()->getPosition()->getBpm();
    
    // NOTE: When you're running standalone, you won't get a value here, as there is no host environment
    if (tmp_bpm.hasValue()) {
        // Set your module level variable to the retrieved value, for use elsewhere
        mHostBPM = (int)*tmp_bpm;
        DBG("Got BPM: " << mHostBPM);
    }
    else {
        // Not supported in host environment?
        DBG("BPM couldn't be retrieved");
    }

One caveat is that this approach yields no BPM when running in Standalone, while the previous approach seems to yield a BPM of 120. Which is interesting.