# Possible bug in juce\_VST3\_Wrapper.cpp processParameterChanges

**URL:** <https://forum.juce.com/t/possible-bug-in-juce-vst3-wrapper-cpp-processparameterchanges/34053>\
**Category:** General JUCE discussion\
**Created:** [June 23, 2019, 6:01pm UTC](https://forum.juce.com/t/possible-bug-in-juce-vst3-wrapper-cpp-processparameterchanges/34053 "2019-06-23T18:01:59Z")\
**Posts on this page:** 16\
**Page:** 1

<div class="post-metadata">

**Author:** ![swar](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/swar/32/12935_2.png) [@swar](https://forum.juce.com/u/swar)\
**Post date:** [June 23, 2019, 6:01pm UTC](https://forum.juce.com/t/possible-bug-in-juce-vst3-wrapper-cpp-processparameterchanges/34053/1 "2019-06-23T18:01:59Z")

</div>

I am facing a problem when selecting a specific program in a VST3 plugin, from the host. It seems to randomly select the previous program.

While debugging, I came to this:

```
            if (vstParamID == JuceAudioProcessor::paramPreset)
            {
                auto numPrograms = pluginInstance->getNumPrograms();
                auto programValue = roundToInt (value * (jmax (0, numPrograms - 1)));

                if (numPrograms > 1 && isPositiveAndBelow (programValue, numPrograms)
                     && programValue != pluginInstance->getCurrentProgram())
                    pluginInstance->setCurrentProgram (programValue);
            }

```

Could it be because you remove 1 to numPrograms in roundToInt (value \* (jmax (0, numPrograms - 1)))?

Please check and let me know if I should look elsewhere.

Thanks.

Mariano

---

<div class="post-metadata">

**Author:** ![swar](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/swar/32/12935_2.png) [@swar](https://forum.juce.com/u/swar)\
**Post date:** [June 24, 2019, 5:55am UTC](https://forum.juce.com/t/possible-bug-in-juce-vst3-wrapper-cpp-processparameterchanges/34053/2 "2019-06-24T05:55:37Z")

</div>

Yes, there seems to be a mismatch when normalising vs denormalising. Here in setCurrentProgram:

```
void setCurrentProgram (int program) override
{
    if (programNames.size() > 0 && editController != nullptr)
    {
        auto value = static_cast<Vst::ParamValue> (program) / static_cast<Vst::ParamValue> (programNames.size());

        editController->setParamNormalized (programParameterID, value);
        Steinberg::int32 index;
        inputParameterChanges->addParameterData (programParameterID, index)->addPoint (0, value, index);
    }
}
```

---

<div class="post-metadata">

**Author:** ![swar](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/swar/32/12935_2.png) [@swar](https://forum.juce.com/u/swar)\
**Post date:** [June 25, 2019, 11:53am UTC](https://forum.juce.com/t/possible-bug-in-juce-vst3-wrapper-cpp-processparameterchanges/34053/3 "2019-06-25T11:53:35Z")

</div>

It goes even further than that. The syncProgramNames method fills the programNames StringArray with some duplicates and skips some program names.

Could you please look into this and let me know if you get the same behaviour at your end? It looks like the normalisation/denormalisation of program nr is flawed.

---

<div class="post-metadata">

**Author:** ![swar](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/swar/32/12935_2.png) [@swar](https://forum.juce.com/u/swar)\
**Post date:** [June 26, 2019, 12:55pm UTC](https://forum.juce.com/t/possible-bug-in-juce-vst3-wrapper-cpp-processparameterchanges/34053/4 "2019-06-26T12:55:11Z")

</div>

Ok, hopefully someone starts paying attention to this. I can’t do “fuzzy” voice selection;-)

In syncProgramNames, the issue seems to arise out of floating point truncation here:

```
void toString (Vst::ParamValue value, Vst::String128 result) const override
{
    toString128 (result, owner.getProgramName (static_cast<int> (value * info.stepCount)));
}

```

info.stepCount equals 93 in my case, and value is the program index divided by as much.

Index 12 and 13 are both evaluated as 12.

---

<div class="post-metadata">

**Author:** ![ed95](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/ed95/32/7635_2.png) [@ed95](https://forum.juce.com/u/ed95)\
**Post date:** [June 27, 2019, 8:59am UTC](https://forum.juce.com/t/possible-bug-in-juce-vst3-wrapper-cpp-processparameterchanges/34053/5 "2019-06-27T08:59:58Z")

</div>

Are you using the JUCE plug-in host? I’ve tried reproducing this with the following code but I’m not seeing any issues:

```auto
/ *******************************************************************************
 The block below describes the properties of this PIP. A PIP is a short snippet
 of code that can be read by the Projucer and used to generate a JUCE project.

 BEGIN_JUCE_PIP_METADATA

  name: VST3Programs

  dependencies: juce_audio_basics, juce_audio_devices, juce_audio_formats, juce_audio_plugin_client, 
                    juce_audio_processors, juce_audio_utils, juce_core, juce_data_structures, juce_events, 
                    juce_graphics, juce_gui_basics, juce_gui_extra
  exporters: xcode_mac

  moduleFlags: JUCE_STRICT_REFCOUNTEDPOINTER=1

  type: AudioProcessor
  mainClass: MyPlugin

 END_JUCE_PIP_METADATA

******************************************************************************* /

#pragma once

//==============================================================================
class MyPlugin : public AudioProcessor
{
public:
    //==============================================================================
    MyPlugin()
        : AudioProcessor (BusesProperties().withInput ("Input", AudioChannelSet::stereo())
                                           .withOutput ("Output", AudioChannelSet::stereo()))
    {
    }

    ~MyPlugin()
    {
    }

    //==============================================================================
    void prepareToPlay (double, int) override
    {
        // Use this method as the place to do any pre-playback
        // initialisation that you need..
    }

    void releaseResources() override
    {
        // When playback stops, you can use this as an opportunity to free up any
        // spare memory, etc.
    }

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

        // In case we have more outputs than inputs, this code clears any output
        // channels that didn't contain input data, (because these aren't
        // guaranteed to be empty - they may contain garbage).
        // This is here to avoid people getting screaming feedback
        // when they first compile a plugin, but obviously you don't need to keep
        // this code if your algorithm always overwrites all the output channels.
        for (auto i = totalNumInputChannels; i < totalNumOutputChannels; ++i)
            buffer.clear (i, 0, buffer.getNumSamples());

        // This is the place where you'd normally do the guts of your plugin's
        // audio processing...
        // Make sure to reset the state if your inner loop is processing
        // the samples and the outer loop is handling the channels.
        // Alternatively, you can process the samples with the channels
        // interleaved by keeping the same state.
        for (int channel = 0; channel < totalNumInputChannels; ++channel)
        {
            auto* channelData = buffer.getWritePointer (channel);

            // ..do something to the data...
        }
    }

    //==============================================================================
    AudioProcessorEditor* createEditor() override { return nullptr; }
    bool hasEditor() const override { return false; }

    //==============================================================================
    const String getName() const override { return "VST3Programs"; }
    bool acceptsMidi() const override { return false; }
    bool producesMidi() const override { return false; }
    double getTailLengthSeconds() const override { return 0; }

    //==============================================================================
    int getNumPrograms() override { return programs.size(); }
    int getCurrentProgram() override { return selected; }
    void setCurrentProgram (int index) override { selected = index; DBG ("PROGRAM SELECTED: " + programs[selected]); }
    const String getProgramName (int index) override { return programs[index]; }
    void changeProgramName (int, const String&) override {}

    //==============================================================================
    void getStateInformation (MemoryBlock& destData) override
    {
        // You should use this method to store your parameters in the memory block.
        // You could do that either as raw data, or use the XML or ValueTree classes
        // as intermediaries to make it easy to save and load complex data.
    }

    void setStateInformation (const void* data, int sizeInBytes) override
    {
        // You should use this method to restore your parameters from this memory block,
        // whose contents will have been created by the getStateInformation() call.
    }

    //==============================================================================
    bool isBusesLayoutSupported (const BusesLayout& layouts) const override
    {
        // This is the place where you check if the layout is supported.
        // In this template code we only support mono or stereo.
        if (layouts.getMainOutputChannelSet() != AudioChannelSet::mono()
            && layouts.getMainOutputChannelSet() != AudioChannelSet::stereo())
            return false;

        // This checks if the input layout matches the output layout
        if (layouts.getMainOutputChannelSet() != layouts.getMainInputChannelSet())
            return false;

        return true;
    }

private:
    int selected = 0;
    StringArray programs { "Program 1", "Program 2", "Program 3", "Program 4", "Program 5",
                           "Program 6", "Program 7", "Program 8", "Program 9", "Program 10",
                           "Program 11", "Program 12", "Program 13", "Program 14", "Program 15",
                           "Program 16", "Program 17", "Program 18", "Program 19", "Program 20" };
    
    //==============================================================================
    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MyPlugin)
};

```

What do your plug-in’s `get/setCurrentProgram()` methods look like?

---

<div class="post-metadata">

**Author:** ![swar](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/swar/32/12935_2.png) [@swar](https://forum.juce.com/u/swar)\
**Post date:** [June 27, 2019, 9:31am UTC](https://forum.juce.com/t/possible-bug-in-juce-vst3-wrapper-cpp-processparameterchanges/34053/6 "2019-06-27T09:31:10Z")

</div>

Thanks for looking into this. Could I ask you to try with 93 programs? It seems to be a truncation issue, so 20 items may not do the trick.

My get/setCurrentProgram are pretty the same: getting/setting an instrument from a table.

---

<div class="post-metadata">

**Author:** ![ed95](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/ed95/32/7635_2.png) [@ed95](https://forum.juce.com/u/ed95)\
**Post date:** [June 27, 2019, 9:38am UTC](https://forum.juce.com/t/possible-bug-in-juce-vst3-wrapper-cpp-processparameterchanges/34053/7 "2019-06-27T09:38:32Z")

</div>

```auto
/ *******************************************************************************
 The block below describes the properties of this PIP. A PIP is a short snippet
 of code that can be read by the Projucer and used to generate a JUCE project.

 BEGIN_JUCE_PIP_METADATA

  name: VST3Programs

  dependencies: juce_audio_basics, juce_audio_devices, juce_audio_formats, juce_audio_plugin_client, 
                    juce_audio_processors, juce_audio_utils, juce_core, juce_data_structures, juce_events, 
                    juce_graphics, juce_gui_basics, juce_gui_extra
  exporters: xcode_mac

  moduleFlags: JUCE_STRICT_REFCOUNTEDPOINTER=1

  type: AudioProcessor
  mainClass: MyPlugin

 END_JUCE_PIP_METADATA

******************************************************************************* /

#pragma once

//==============================================================================
class MyPlugin : public AudioProcessor
{
public:
    //==============================================================================
    MyPlugin()
        : AudioProcessor (BusesProperties().withInput ("Input", AudioChannelSet::stereo())
                                           .withOutput ("Output", AudioChannelSet::stereo()))
    {
        for (int i = 0; i < 93; ++i)
            programs.add ("Program" + String (i));
    }

    ~MyPlugin()
    {
    }

    //==============================================================================
    void prepareToPlay (double, int) override
    {
        // Use this method as the place to do any pre-playback
        // initialisation that you need..
    }

    void releaseResources() override
    {
        // When playback stops, you can use this as an opportunity to free up any
        // spare memory, etc.
    }

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

        // In case we have more outputs than inputs, this code clears any output
        // channels that didn't contain input data, (because these aren't
        // guaranteed to be empty - they may contain garbage).
        // This is here to avoid people getting screaming feedback
        // when they first compile a plugin, but obviously you don't need to keep
        // this code if your algorithm always overwrites all the output channels.
        for (auto i = totalNumInputChannels; i < totalNumOutputChannels; ++i)
            buffer.clear (i, 0, buffer.getNumSamples());

        // This is the place where you'd normally do the guts of your plugin's
        // audio processing...
        // Make sure to reset the state if your inner loop is processing
        // the samples and the outer loop is handling the channels.
        // Alternatively, you can process the samples with the channels
        // interleaved by keeping the same state.
        for (int channel = 0; channel < totalNumInputChannels; ++channel)
        {
            auto* channelData = buffer.getWritePointer (channel);

            // ..do something to the data...
        }
    }

    //==============================================================================
    AudioProcessorEditor* createEditor() override { return nullptr; }
    bool hasEditor() const override { return false; }

    //==============================================================================
    const String getName() const override { return "VST3Programs"; }
    bool acceptsMidi() const override { return false; }
    bool producesMidi() const override { return false; }
    double getTailLengthSeconds() const override { return 0; }

    //==============================================================================
    int getNumPrograms() override { return programs.size(); }
    int getCurrentProgram() override { return selected; }
    void setCurrentProgram (int index) override { selected = index; DBG ("PROGRAM SELECTED: " + programs[selected]); }
    const String getProgramName (int index) override { return programs[index]; }
    void changeProgramName (int, const String&) override {}

    //==============================================================================
    void getStateInformation (MemoryBlock& destData) override
    {
        // You should use this method to store your parameters in the memory block.
        // You could do that either as raw data, or use the XML or ValueTree classes
        // as intermediaries to make it easy to save and load complex data.
    }

    void setStateInformation (const void* data, int sizeInBytes) override
    {
        // You should use this method to restore your parameters from this memory block,
        // whose contents will have been created by the getStateInformation() call.
    }

    //==============================================================================
    bool isBusesLayoutSupported (const BusesLayout& layouts) const override
    {
        // This is the place where you check if the layout is supported.
        // In this template code we only support mono or stereo.
        if (layouts.getMainOutputChannelSet() != AudioChannelSet::mono()
            && layouts.getMainOutputChannelSet() != AudioChannelSet::stereo())
            return false;

        // This checks if the input layout matches the output layout
        if (layouts.getMainOutputChannelSet() != layouts.getMainInputChannelSet())
            return false;

        return true;
    }

private:
    int selected = 0;
    StringArray programs;
    
    //==============================================================================
    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MyPlugin)
};

```

This is working fine for me.

---

<div class="post-metadata">

**Author:** ![swar](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/swar/32/12935_2.png) [@swar](https://forum.juce.com/u/swar)\
**Post date:** [June 27, 2019, 9:43am UTC](https://forum.juce.com/t/possible-bug-in-juce-vst3-wrapper-cpp-processparameterchanges/34053/8 "2019-06-27T09:43:50Z")

</div>

My issue was in getProgramName, when called from VST3EditController::toString. Can you debug that part as well with your sample?

---

<div class="post-metadata">

**Author:** ![ed95](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/ed95/32/7635_2.png) [@ed95](https://forum.juce.com/u/ed95)\
**Post date:** [June 27, 2019, 10:42am UTC](https://forum.juce.com/t/possible-bug-in-juce-vst3-wrapper-cpp-processparameterchanges/34053/9 "2019-06-27T10:42:44Z")

</div>

OK, I’ve pushed a fix here:

> <https://github.com/WeAreROLI/JUCE/commit/da0401f1247106fc1b7e40c18308098b18a292ca>

Does this solve the issue?

---

<div class="post-metadata">

**Author:** ![swar](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/swar/32/12935_2.png) [@swar](https://forum.juce.com/u/swar)\
**Post date:** [June 27, 2019, 11:09am UTC](https://forum.juce.com/t/possible-bug-in-juce-vst3-wrapper-cpp-processparameterchanges/34053/10 "2019-06-27T11:09:48Z")

</div>

Seems to have fixed the issue for duplicate program names, thanks!

Though setCurrentProgram still often selects the program nr below. As you didn’t find any issue with that, I need to delve deeper in my code to see if the bug is at my end.

But in the meantime could you confirm that dividing by numPrograms (see above) and then multiplying by numPrograms - 1 is what was intended?

---

<div class="post-metadata">

**Author:** ![ed95](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/ed95/32/7635_2.png) [@ed95](https://forum.juce.com/u/ed95)\
**Post date:** [June 27, 2019, 2:38pm UTC](https://forum.juce.com/t/possible-bug-in-juce-vst3-wrapper-cpp-processparameterchanges/34053/11 "2019-06-27T14:38:31Z")

</div>

No, I don’t think that was intentional. I’ve pushed a fix here:

> <https://github.com/WeAreROLI/JUCE/commit/19cebf89279c1b926049aa238c6d2e746ee7d1f6>

Thanks for reporting!

---

<div class="post-metadata">

**Author:** ![swar](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/swar/32/12935_2.png) [@swar](https://forum.juce.com/u/swar)\
**Post date:** [June 27, 2019, 2:47pm UTC](https://forum.juce.com/t/possible-bug-in-juce-vst3-wrapper-cpp-processparameterchanges/34053/12 "2019-06-27T14:47:01Z")

</div>

Awesome! Seems to work fine now.

Thanks for the fix!

---

<div class="post-metadata">

**Author:** ![swar](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/swar/32/12935_2.png) [@swar](https://forum.juce.com/u/swar)\
**Post date:** [March 14, 2020, 12:48pm UTC](https://forum.juce.com/t/possible-bug-in-juce-vst3-wrapper-cpp-processparameterchanges/34053/13 "2020-03-14T12:48:25Z")

</div>

I think there’s another issue with the getCurrentProgram in the same file. Current code is:

` int getCurrentProgram() override { return jmax (0, (int) editController->getParamNormalized (programParameterID) * (programNames.size() - 1)); }`

Seems the float returned by getParamNormalized is casted to an int before it can define the program in the list. Can you please check?

---

<div class="post-metadata">

**Author:** ![ed95](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/ed95/32/7635_2.png) [@ed95](https://forum.juce.com/u/ed95)\
**Post date:** [March 17, 2020, 10:28am UTC](https://forum.juce.com/t/possible-bug-in-juce-vst3-wrapper-cpp-processparameterchanges/34053/14 "2020-03-17T10:28:10Z")

</div>

Thanks, this should now be fixed in [722a140](https://github.com/WeAreROLI/JUCE/commit/722a1403af7d3f92139115f2b93250291d871abb).

---

<div class="post-metadata">

**Author:** ![swar](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/swar/32/12935_2.png) [@swar](https://forum.juce.com/u/swar)\
**Post date:** [March 21, 2020, 3:06pm UTC](https://forum.juce.com/t/possible-bug-in-juce-vst3-wrapper-cpp-processparameterchanges/34053/15 "2020-03-21T15:06:18Z")

</div>

Great, thanks.

I have another issue I am facing, and maybe this is something you can check as well. In my DAW, when I want to bounce my track(s), I temporarily disconnect my Audiograph by using DeviceManager::removeAudioCallback, then reconnect it with DeviceManager::addAudioCallback once my bouncing is done. I don’t know if this is kosher, but it works just fine.

Only problem I am facing is when there are VST3 plugins in the tracks (AU and VST2 work fine). When the graph is reconnected, the VST3 don’t receive MIDI events anymore. I was able to track it to this:

When the VST3 is loaded:

initialise -\> setupIO -\> setStateForAllInputBusEnabled(true)

Then when disconnecting:

removeAudioCallback -\> releaseResources -\>setStateForAllInputBusEnabled(false)

But then when reconnecting, addAudioCallback does not call for setStateForAllInputBusEnabled(true) in any way.

The whole VST3 implementation is very complex, so maybe this is the way it’s supposed to work, but could you please have a look at it and possibly fix that issue?

Thanks a lot.

---

<div class="post-metadata">

**Author:** ![swar](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.juce.com/swar/32/12935_2.png) [@swar](https://forum.juce.com/u/swar)\
**Post date:** [June 18, 2020, 7:03am UTC](https://forum.juce.com/t/possible-bug-in-juce-vst3-wrapper-cpp-processparameterchanges/34053/16 "2020-06-18T07:03:52Z")

</div>

bump
