MPESynthesiser Extension Issue

Hi all. I’m (still) trying to implement the DSP tutorial from scratch to understand how everything links together (thanks for all the help so far!!). I’m running into this issue where my code doesn’t recognize the MPESynthesiserBase method RenderNextBlock() (at least I think that’s my issue). I’ve created an AudioEngine class extending MPESynthesiser as was done in the tutorial but for some reason I’m getting an error when calling AudioEngine.renderNextBlock(…). I figure that extending MPESynthesiser will also extend MPESynthesiserBase since that’s the base class of MPESynthesiser, but assume I’m missing something. I appreciate any guidance here, thank you!

My header file implementation of AudioEngine


class AudioEngine  : public juce::MPESynthesiser
{
public:
    static constexpr auto maxNumVoices = 4;
    
    //==============================================================================
    AudioEngine();
    
    //==============================================================================
    void prepare (const juce::dsp::ProcessSpec& spec) noexcept;
    
private:
    //==============================================================================
    void renderNextSubBlock (juce::AudioBuffer<float>& outputAudio, int startSample, int numSamples) override
    {
        MPESynthesiser::renderNextSubBlock (outputAudio, startSample, numSamples);
        
        auto block = juce::dsp::AudioBlock<float> (outputAudio);
        auto blockToUse = block.getSubBlock ((size_t) startSample, (size_t) numSamples);
        auto contextToUse = juce::dsp::ProcessContextReplacing<float> (blockToUse);
        fxChain.process (contextToUse);
    }
    
    enum
    {
        reverbIndex
    };
    
    juce::dsp::ProcessorChain<juce::dsp::Reverb> fxChain;
};

My source file implementation of AudioEngine

#include "AudioEngine.h"

AudioEngine::AudioEngine()
{
    for (auto i = 0; i < maxNumVoices; ++i)
        addVoice (new Voice);
    
    setVoiceStealingEnabled (true);
}

void AudioEngine::prepare (const juce::dsp::ProcessSpec& spec) noexcept
{
    setCurrentPlaybackSampleRate (spec.sampleRate);
    
    for (auto* v : voices)
        dynamic_cast<Voice*> (v)->prepare (spec);
    
    fxChain.prepare (spec);
}

The error when I call AudioEngine.renderNextBlock()

Xcode will give you more information about the error if you click on the error list button in the left-hand sidebar (see this post/screenshot);

In this case, renderNextBlock takes a const MidiBuffer& argument, but you’re passing a MidiBuffer**. You probably meant to pass *midiMessages instead of &midiMessages.

On a different topic, it’s probably a bad idea to allocate a new juce::MidiBuffer on each block. Instead, have a MidiBuffer class member with reserved capacity that you clear at the beginning of each block, to avoid allocations on the audio thread.

1 Like

Super helpful, thank you! That solved my issue (:

Okay checking in again. I’m trying to add the MidiBuffer as a class member but running into issues with the initialization. I’ve added it as a public member as I was having EXC_BAD_ACCESS issues when it was private, but I’m still confused how to initialize it.

Explicitly defining midiMessages in the MainComponent constructor (wondering if I should initialize it with a value, but unsure what that value should be)

Clearing midiMessages before each processing. This also gives me a bad access code (assuming because I’m clearing the buffer before there’s anything in it)

void MainComponent::getNextAudioBlock (const juce::AudioSourceChannelInfo& bufferToFill)
{
    midiMessages.clear();
... // process
}

I also tried using the below in the MainComponent constructor to preallocate memory, but this also threw an error.

midiMessages.ensureSize(2048);

Any idea what I’m missing here? All the error types are somewhat related to null pointer errors which is why I’m thinking it’s an initialization issue (just not sure how to fix it).