MaxMsp/Gen Param -> Slider linking

Yes I got that, but the sliders are not connecting automatically to the old setParameter/getParameter. But the Slider connects to a Value object. so you create a Value object, that mirrors the value of your parameter in Cycling/Max.
Now your Slider in the editor can refer to that value, and therefore it will be updated, when the value in the processor is changed from the host e.g. and vice versa

1 Like

This is a bad lovely fix :star:

Just a copule things:

  1. I need to set an initial value for lengthValue “must be an lvalue”, don’t know how to initialize it
  2. is obj.referTo(processor.getLengthValueObject()) alredy passing the value to lengthSlider in some way? If so I’m not getting how

You probably declared a reference to the actual Value. Remove the & operator, so an actual object is created:

class Processor : public AudioProcessor
    // ...
    Value& getLengthValueObject () {
        return lengthValue;
    Value lengthValue;

The moment you call referTo the slider should be updated to the value of the ValueObject in the processor. Note you have to decide, if you want to have the Slider working in the range 0…1 or the actual range of the Cycling parameter…
Either you set it to the value coming from setValue (normalised) or the one mapped in the stub.

1 Like

my bad on the Value& <

So, obj.referTo updates the Slider, right?
and how do I call it just when the value has changed?
I’m already using 0…1 values, it shouldn’t be a problem (i hope)

for now it compiles but crashes the Daw on opening, i placed
auto& obj = lengthSlider.getValueObject();
obj.referTo (processor.getLengthValueObject();
right after setSize(), 3rd line of editor constructor (and probably that’s wrong)

YES! Made it work!
I basically re-did everything off the project and it simply worked!

Thank you a lot @daniel you made my day! (and last three too!)
I own you a dozen beers :heartbeat:

I’m sure I’ll get thousands more problems for here on but you wished me luck so yeah, I’ll be fine! Cheers! :beers:

1 Like

I had a second look, and there is a way to use the AudioProcessorValueTreeState:

1st: Get rid of

  • getNumParameters()
  • getParameter (int index)
  • setParameter (int index, float newValue)
  • getParameterName (int index)
  • getParameterText (int index)

2nd: create your own state and only forward the changes from your state to the Cycling processor, similar to this (untested):

	// use a default samplerate and vector size here, reset it later
	mState = new AudioProcessorValueTreeState(*this, nullptr);

	m_C74PluginState = (CommonState *)C74_GENPLUGIN::create(44100, 64);

    for (int p=0; p<; C74_GENPLUGIN::num_params(); ++p) {
        auto name = String(C74_GENPLUGIN::getparametername(m_C74PluginState, index));
        t_param min = C74_GENPLUGIN::getparametermin(m_C74PluginState, index);
        t_param max = C74_GENPLUGIN::getparametermax(m_C74PluginState, index);

        mState->createAndAddParameter (name, name, name,
                                       NormalisableRange<float> (min, max),
                                       nullptr, nullptr,
                                       false, true, false);
        mState->addParameterListener (name, this);

	m_InputBuffers = new t_sample *[C74_GENPLUGIN::num_inputs()];
	m_OutputBuffers = new t_sample *[C74_GENPLUGIN::num_outputs()];
	for (int i = 0; i < C74_GENPLUGIN::num_inputs(); i++) {
		m_InputBuffers[i] = NULL;
	for (int i = 0; i < C74_GENPLUGIN::num_outputs(); i++) {
		m_OutputBuffers[i] = NULL;


    for (int p=0; p<; C74_GENPLUGIN::num_params(); ++p) {
        auto name = String(C74_GENPLUGIN::getparametername(m_C74PluginState, index));
        mState->removeParameterListener (name, this);


void C74GenAudioProcessor::parameterChanged(const String &parameterID, float newValue)
    for (int p=0; p < C74_GENPLUGIN::num_params(); ++p) {
        if (parameterID == String(C74_GENPLUGIN::getparametername(m_C74PluginState, p)))
            t_param min = C74_GENPLUGIN::getparametermin(m_C74PluginState, index);
            t_param range = fabs(C74_GENPLUGIN::getparametermax(m_C74PluginState, index) - min);
            t_param value = newValue * range + min;

            C74_GENPLUGIN::setparameter(m_C74PluginState, p, value, NULL);

void C74GenAudioProcessor::getStateInformation (MemoryBlock& destData)
    MemoryOutputStream stream(destData, false);
    state->state.writeToStream (stream);

void C74GenAudioProcessor::setStateInformation (const void* data, int sizeInBytes)
    ValueTree tree = ValueTree::readFromData (data, sizeInBytes);
    if (tree.isValid()) {
        state->state = tree;

N.B. maybe you will find better ideas to determine a default value by looking at the generated code, I left that as an exercise… (no, was too lazy in fact :wink: )


1 Like

Well, this method is much more pretty and clean and probably would let me use xml for presets and recalling after saving without many troubles.

Btw it lead to other issues

  1. on opening reaper this appears (but works then)

    on ableton live, when added to a track this appears (and never got it opened)

  2. Those For-loops should add all my parameters from Cycling to my ValueTree right? It seems that only my length (index 0) is automable tho, others don’t seem to move (even if there’s actually no difference between lenght and others)

I just realised a typo, that semicolon sneaked in…
Also maybe add that DBG statement to get more insight, what’s happening:

    for (int p=0; p<C74_GENPLUGIN::num_params(); ++p) {
        auto name = String(C74_GENPLUGIN::getparametername(m_C74PluginState, index));
        DBG ("Adding parameter " << p ,, ": " << name);


yeah, caught that already

I changed “index” with p too because it kept telling me it was undefined (and I thought your index was referring to the for loop one). Maybe that is the issue?

-don’t really know how to use DBG, nothing really changed, i know i should do something but don’t know what actually-

I see… DBG prints text into the console, that is very handy to get information at runtime.
Either you start Logic (or whichever host you use) from the debugger by setting “Select Executable”, and see the output in XCode, or just start the host from the Terminal and see the output there…

Sorry about the many typos in the code, as I said, I didn’t compile it… And I never worked with cycling max/msp…

that’s the only thing I can solve for now, leave them in place please :upside_down_face:

actually on windows, will find out how to do it asap
Now it works with all paramaters without changing anything,
still doesn’t work on Live tho (and that error when launching Reaper)

I hope you are on the latest tip, since there was a Live specific bug just a month ago:

I’m on 5.3.1, I should be fine by that side…