Gen Code Export & APVTS – Memo –

gen~

Simple Gain

exportcode

JUCE

New Project

PluginProcessor.h

#pragma once

#include <JuceHeader.h>
#include "gen_exported.h"
class TestGenAudioProcessor  : public juce::AudioProcessor, public juce::AudioProcessorValueTreeState::Listener
{
public:
・・・
    juce::AudioProcessorValueTreeState::ParameterLayout createParameterLayout();
            
    juce::AudioProcessorValueTreeState apvts { *this, nullptr, "Parameters", createParameterLayout() };
    
    void parameterChanged (const juce::String& parameterID, float newValue) override;

protected:
    void assureBufferSize (long bufferSize); 

private:
    CommonState* m_C74PluginState;    
    long m_CurrentBufferSize;    
    t_sample** m_InputBuffers;    
    t_sample** m_OutputBuffers;
    
    //==============================================================================
    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TestGenAudioProcessor)
};
    

PluginProcessor.cpp

GenPluginExportAudioProcessor::GenPluginExportAudioProcessor()
    : m_CurrentBufferSize(0)
{
    m_C74PluginState = (CommonState*) gen_exported::create (44100, 64);
    gen_exported::reset (m_C74PluginState);
    
    m_InputBuffers = new t_sample *[gen_exported::num_inputs()];
    m_OutputBuffers = new t_sample *[gen_exported::num_outputs()];
    
    for (int i = 0; i < gen_exported::num_params(); ++i)
    {
        auto name = juce::String(gen_exported::getparametername (m_C74PluginState, i));
        apvts.addParameterListener (name, this);
    }
        
    for (int i = 0; i < gen_exported::num_inputs(); i++)
    {
        m_InputBuffers[i] = NULL;
    }
    
    for (int i = 0; i < gen_exported::num_outputs(); i++)
    {
        m_OutputBuffers[i] = NULL;
    }
}
void GenPluginExportAudioProcessor::processBlock (juce::AudioBuffer<float>& buffer, juce::MidiBuffer& midiMessages)
{
    assureBufferSize (buffer.getNumSamples());
        
    for (int i = 0; i < gen_exported::num_inputs(); i++)
    {
        if (i < getTotalNumInputChannels())
        {
            for (int j = 0; j < m_CurrentBufferSize; j++)
            {
                m_InputBuffers[i][j] = buffer.getReadPointer (i)[j];
            }
        }
        else
        {
            memset (m_InputBuffers[i], 0, m_CurrentBufferSize *  sizeof (double));
        }
    }
    
    gen_exported::perform(m_C74PluginState,
                          m_InputBuffers,
                          gen_exported::num_inputs(),
                          m_OutputBuffers,
                          gen_exported::num_outputs(),
                          buffer.getNumSamples());
    
    for (int i = 0; i < getTotalNumOutputChannels(); i++)
    {
        if (i < gen_exported::num_outputs())
        {
            for (int j = 0; j < buffer.getNumSamples(); j++)
            {
                buffer.getWritePointer (i)[j] = m_OutputBuffers[i][j];
            }
        }
        else
        {
            buffer.clear (i, 0, buffer.getNumSamples());
        }
    }
}
void GenPluginExportAudioProcessor::getStateInformation (juce::MemoryBlock& destData)
{
    char *state;
    size_t statesize = gen_exported::getstatesize (m_C74PluginState);
    state = (char*) malloc (sizeof (char) * statesize);

    gen_exported::getstate (m_C74PluginState, state);
    destData.replaceWith (state, sizeof (char) * statesize);

    if (state) free (state);
}

void GenPluginExportAudioProcessor::setStateInformation (const void* data, int sizeInBytes)
{
    gen_exported::setstate (m_C74PluginState, (const char*)data);
}
void GenPluginExportAudioProcessor::assureBufferSize (long bufferSize)
{
    if (bufferSize > m_CurrentBufferSize)
    {
        for (int i = 0; i < gen_exported::num_inputs(); i++)
        {
            if (m_InputBuffers[i]) 
                delete m_InputBuffers[i];

            m_InputBuffers[i] = new t_sample[bufferSize];
        }
        
        for (int i = 0; i < gen_exported::num_outputs(); i++)
        {
            if (m_OutputBuffers[i]) 
                delete m_OutputBuffers[i];

            m_OutputBuffers[i] = new t_sample[bufferSize];
        }
        
        m_CurrentBufferSize = bufferSize;
    }
}
void GenPluginExportAudioProcessor::parameterChanged (const juce::String ¶meterID, float newValue)
{
    for (int i = 0; i < gen_exported::num_params(); i++)
    {
        if (parameterID == juce::String (gen_exported::getparametername (m_C74PluginState, i)))
        {
            t_param min = gen_exported::getparametermin (m_C74PluginState, i);
            t_param range = fabs (gen_exported::getparametermax (m_C74PluginState, i) - min);
            t_param value = newValue * range + min;
            gen_exported::setparameter (m_C74PluginState, i, value, NULL);
            return;
        }
    }
}
juce::AudioProcessorValueTreeState::ParameterLayout GenPluginExporterAudioProcessor::createParameterLayout()
{
    m_C74PluginState = (CommonState*) gen_exported::create (44100, 64);
    gen_exported::reset (m_C74PluginState);
    
    juce::AudioProcessorValueTreeState::ParameterLayout layout;
    
    for (int i = 0; i < gen_exported::num_params(); ++i)
    {
        auto name = juce::String(gen_exported::getparametername (m_C74PluginState, i));
        t_param min = gen_exported::getparametermin (m_C74PluginState, i);
        t_param max = gen_exported::getparametermax (m_C74PluginState, i);
        t_param defaultValue = m_C74PluginState->params[i].defaultvalue;
    
        layout.add (std::make_unique<juce::AudioParameterFloat> (name, name,
                                                                 juce::NormalisableRange<float> (min, max, 0.01f, 1.f),
                                                                 defaultValue,
                                                                 juce::String(),
                                                                 juce::AudioProcessorParameter::genericParameter,
                                                                 nullptr,
                                                                 nullptr));
    }
                        
    return layout;
}

References

Comments

  1. momentum says:

    Just one small thing I would change in the exported code is the use of dual array lookup modifiers which are a bit slower then doing it like so:

    (this is from the processBlock() function)

    for (int i = 0; i < getTotalNumOutputChannels(); i++)
    {
    if (i < gen_exported::num_outputs())
    {
    auto write_pointer_ = buffer.getWritePointer(i)

    for (int j = 0; j < buffer.getNumSamples(); j++)
    {
    write_pointer_[j] = m_OutputBuffer[j];
    }
    }
    else
    {
    buffer.clear (i, 0, buffer.getNumSamples());
    }
    }

    From what I understand looking up a 2D array like array[x][y] is slower than declaring a variable for the first dimension and then looking up the second dimension as you need it, because two lookups for each sample in the block are slower than one.

Copied title and URL