# Bug: VST3 Program parameter does not record automation

**URL:** <https://forum.juce.com/t/bug-vst3-program-parameter-does-not-record-automation/43254>\
**Category:** Audio Plugins\
**Created:** [December 15, 2020, 10:42am UTC](https://forum.juce.com/t/bug-vst3-program-parameter-does-not-record-automation/43254 "2020-12-15T10:42:29Z")\
**Posts on this page:** 17\
**Page:** 1

<div class="post-metadata">

**Author:** ![sparklingRhubarb](https://avatars.discourse-cdn.com/v4/letter/s/8dc957/32.png) [@sparklingRhubarb](https://forum.juce.com/u/sparklingRhubarb)\
**Post date:** [December 15, 2020, 10:42am UTC](https://forum.juce.com/t/bug-vst3-program-parameter-does-not-record-automation/43254/1 "2020-12-15T10:42:29Z")

</div>

Setup:

- using the VST3 Program parameter, as provided by the JUCE VST3 wrapper
- when loading a preset from the plugin GUI, we call `updateHostDisplay()` to trigger an update to the VST3 Program parameter. (Side note: This worked fine in the past but is currently broken - [see pull request here](https://forum.juce.com/t/vst3-program-parameter-is-not-updated-when-the-loaded-program-changed-and-updatehostdisplay-is-called/43253)).

Problem:

When the VST3 Program parameter is updated in `juce_VST3_Wrapper.cpp:910 - audioProcessorChanged()` there is no `beginParameterChanged()` or `endParameterChanged()` message sent to the host. This leads to hosts not recording this change in their automation data.

Is there a solution to work around this?

---

<div class="post-metadata">

**Author:** ![sparklingRhubarb](https://avatars.discourse-cdn.com/v4/letter/s/8dc957/32.png) [@sparklingRhubarb](https://forum.juce.com/u/sparklingRhubarb)\
**Post date:** [January 4, 2021, 7:57am UTC](https://forum.juce.com/t/bug-vst3-program-parameter-does-not-record-automation/43254/2 "2021-01-04T07:57:01Z")

</div>

Bump

---

<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:** [January 6, 2021, 5:54pm UTC](https://forum.juce.com/t/bug-vst3-program-parameter-does-not-record-automation/43254/3 "2021-01-06T17:54:32Z")

</div>

Wrapping the program parameter update in `beginEdit()` and `endEdit()` calls should ensure that automation data gets recorded correctly in hosts (I noticed that some hosts were recording it correctly without this, but not all). We’ve added this to `develop` here:

> <https://github.com/juce-framework/JUCE/commit/0715b7ebdddcbe480f45a07b2bdb9ff3b107dfb0>

---

<div class="post-metadata">

**Author:** ![sparklingRhubarb](https://avatars.discourse-cdn.com/v4/letter/s/8dc957/32.png) [@sparklingRhubarb](https://forum.juce.com/u/sparklingRhubarb)\
**Post date:** [January 7, 2021, 8:36am UTC](https://forum.juce.com/t/bug-vst3-program-parameter-does-not-record-automation/43254/4 "2021-01-07T08:36:22Z")

</div>

My experience in the past was that “beginEdit() - change Value - endEdit()” would not record anything in some DAWs because the value gets set to the new value, then reset back to the old value immediately on the same sample position - so DAWs sometimes seem to just ignore the change. This may only apply in some automation record modes (e.g. Touch mode) though.

Our fix for this was to call beginEdit() - then change the value and call endEdit() from a Timer a little later on. So the user at least sees that there is a change in the automation lane for the duration of the Timer period. This gets complicated tough when multiple successive changes are made. In that case you’ll have to “reference count” your beginEdit() / endEdit() calls to make sure that you don’t trigger too many / multiple calls. We added this “reference counting” feature (which also makes multi-touch GUIs much simpler because there you run into nested “change gestures” as well).

---

<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:** [January 7, 2021, 8:46am UTC](https://forum.juce.com/t/bug-vst3-program-parameter-does-not-record-automation/43254/5 "2021-01-07T08:46:51Z")

</div>

Which DAWs were you seeing this in? I was testing with Reaper which didn’t record program parameter automation before this change and now does, but if there are DAWs which are still not recording automation after this change then we can take a look.

---

<div class="post-metadata">

**Author:** ![sparklingRhubarb](https://avatars.discourse-cdn.com/v4/letter/s/8dc957/32.png) [@sparklingRhubarb](https://forum.juce.com/u/sparklingRhubarb)\
**Post date:** [January 7, 2021, 8:48am UTC](https://forum.juce.com/t/bug-vst3-program-parameter-does-not-record-automation/43254/6 "2021-01-07T08:48:35Z")

</div>

I was testing this in Reaper earlier. I’ll try it again and report back.

---

<div class="post-metadata">

**Author:** ![sparklingRhubarb](https://avatars.discourse-cdn.com/v4/letter/s/8dc957/32.png) [@sparklingRhubarb](https://forum.juce.com/u/sparklingRhubarb)\
**Post date:** [January 7, 2021, 1:20pm UTC](https://forum.juce.com/t/bug-vst3-program-parameter-does-not-record-automation/43254/7 "2021-01-07T13:20:48Z")

</div>

I quickly tested one of our plugins with [the already mentioned commit](https://github.com/juce-framework/JUCE/commit/0715b7ebdddcbe480f45a07b2bdb9ff3b107dfb0):

- Reaper: It works just fine in latch mode, but the touch mode instantly resets the parameter back to the old value. I guess it is to be expected and something we can live with.
- Bitwig 3.1.2: It writes automation just fine in Latch mode and behaves like Reaper in the Touch mode. However, when reading the automation data, the first change to the plugin program kicks Bitwig out of the Automation read mode (which normally happens when the user touches a control that is currently automated).

Here’s my findings for the Bitwig problem:

1. Setup a plugin, manually add automation for the “Program” parameter: a step function from the initial value of 0 to the value of 1.
2. Start playback
3. When the parameter value changes from 0 to 1, `AudioProcessor::setCurrentProgram()` is called. Our code loads the program and asynchronously triggers a callback that eventually calls `updateHostDisplay()` from the message thread.
4. `updateHostDisplay()` eventually ends up in `juce_VST3_Wrapper.cpp:946` where it correctly calculates the normalized value for the Program parameter to be 1.0.
5. In line 949 when testing if the value has changed, `EditController::getParamNormalized(JuceAudioProcessor::paramPreset))` **incorrectly returns 0.0. It should already be 1.0** , especially since this is executed from the message thread long after the parameter was changed from the host.
6. As the Program parameter appears to have changed, lines 951-955 are executed, where the `beginEdit()` and `endEdit()` make it seem as if the user changed the value so Bitwig correctly stops reading automation and Bitwigs “Restore Automation Control” button next to the time display in the top bar turns green.

Edit: It seems to be a timing issue.

While debugging, I saw that the `JuceVST3EditController::ProgramChangeParameter` gets its value set directly from Bitwig host code, where it eventually ends up in `juce_VST3_Wrapper.cpp:595: ProgramChangeParameter::setNormalized()`. This generally seems to happen after `setCurrentProgram()` is called from the audio thread. Depending on the timing, this may happen before or after our code asynchronically executes `updateHostDisplay()` so the parameter value typically ends up being incorrect.  
I think `updateHostDisplay()` should be able to be called synchronously from inside `setCurrentProgram()`. So it seems to me that `EditController::getParamNormalized (JuceAudioProcessor::paramPreset)` in `juce_VST3_Wrapper.cpp:949` is not the right way to check if the parameter has changed - it should better reference some local variable that is updated BEFORE the call to `setCurrentProgram()`

---

<div class="post-metadata">

**Author:** ![sparklingRhubarb](https://avatars.discourse-cdn.com/v4/letter/s/8dc957/32.png) [@sparklingRhubarb](https://forum.juce.com/u/sparklingRhubarb)\
**Post date:** [January 7, 2021, 2:41pm UTC](https://forum.juce.com/t/bug-vst3-program-parameter-does-not-record-automation/43254/8 "2021-01-07T14:41:01Z")

</div>

[Here’s a quick fix that solves the issue for me](https://github.com/juce-framework/JUCE/pull/824). I added another local variable that tracks the currently loaded program and is updated immediately before the call to `setCurrentProgram()`. This allows the code in `JuceVST3EditController::audioProcessorChanged()` to compare to this local variable instead of the incorrect EditController parameter.

It solves the problem for me but I’m not sure if this really covers all situations. The new variable is a redundant representation of data that is actually stored elsewhere and I don’t know the codebase enough to see if there are other situations where the variable value should be updated.

Edit: Rounding errors ruin the show. I’ll change some things and report back  
Edit2: Fixed it.

---

<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:** [January 7, 2021, 5:18pm UTC](https://forum.juce.com/t/bug-vst3-program-parameter-does-not-record-automation/43254/9 "2021-01-07T17:18:13Z")

</div>

Thanks for investigating. As you say, it looks like the parameter value is out of date and `EditController::getParamNormalized()` is returning the old value. I think this is because we are processing the parameter updates from the host in `processParameterChanges()` and calling `AudioProcessor::setCurrentProgram()` before setting the actual parameter value. The solution should be to go via the edit controller here and move the `setCurrentProgram()` logic to the actual parameter object.

Can you apply this diff and see if it fixes the issue for you? I’ve tested it in Reaper and it seems to be working:

[0001-VST3-Set-program-parameter-via-edit-controller-using.patch](https://forum.juce.com/uploads/short-url/o1VRii4AsrMbGcb6KCUoNIG6hM4.patch) (4.0 KB)

---

<div class="post-metadata">

**Author:** ![sparklingRhubarb](https://avatars.discourse-cdn.com/v4/letter/s/8dc957/32.png) [@sparklingRhubarb](https://forum.juce.com/u/sparklingRhubarb)\
**Post date:** [January 8, 2021, 8:23am UTC](https://forum.juce.com/t/bug-vst3-program-parameter-does-not-record-automation/43254/10 "2021-01-08T08:23:58Z")

</div>

I was thinking about updating the parameter value myself from `processParameterChanges()` but I decided against that as I was seing the host directly updating the parameter itself.

That’s what I’m also seing with your patch. Shortly after `ProgramChangeParameter::setNormalized()` is called from `processParameterChanged()` I see a second call to `ProgramChangeParameter::setNormalized()` that originates directly from Bitwig. This is the stacktrace:

```
> myPlugin.vst3!juce::JuceVST3EditController::ProgramChangeParameter::setNormalized(double v) Line 597
> myPlugin.vst3!Steinberg::Vst::EditController::setParamNormalized(unsigned long tag, double value) Line 186
> BitwigPluginHost64.exe!000000014003eed7()	Unknown
> BitwigPluginHost64.exe!0000000140048cdb()	Unknown

```

It seems to me like it’s coming from the GUI thread.

In your patch, at line 599 you catch that the ProgramChangeParameter already is at the correct value so `setCurrentProgram()` is not called a second time. So in the end it works but admittedly is seems a little unsafe with multiple threads potentially accessing the same stuff concurrently.

Edit: You can install and use the demo version of Bitwig to investigate this for yourself. Maybe this is a special behaviour of Bitwig, idk.

---

<div class="post-metadata">

**Author:** ![sparklingRhubarb](https://avatars.discourse-cdn.com/v4/letter/s/8dc957/32.png) [@sparklingRhubarb](https://forum.juce.com/u/sparklingRhubarb)\
**Post date:** [January 8, 2021, 3:17pm UTC](https://forum.juce.com/t/bug-vst3-program-parameter-does-not-record-automation/43254/11 "2021-01-08T15:17:02Z")

</div>

@ed95 I tested your fix a little more with Ableton Live Lite 10.1.2 and it shows the same problem as I had in Bitwig before your fix: As soon as automation is read, Ableton Live stops reading the automation as if the user manually touched the parameter. **So Ableton Live is also affected.**

I verified that your comparison in `juce_VST3_Wrapper.cpp:953` works - it does. No spurious `beginEdit()` or `endEdit()` is sent from this place. However `processParameterChanges()` in line 2596 calls `paramChanged()` which in line 922 calls `performEdit()`. This in turn calls `componentHandler->performEdit()` which is host code - so I guess this is what ultimately makes Live think the user touched the parameter.

I think it ultimately boils down to the same thing: From all I know, the EditController is supposed to be updated from the Host via the message thread. Using the state of the EditControllers parameters (as it was before your patch) is wrong due to timing issues. Updating the Edit Controllers parameters ourselves (as done in your patch) is also wrong because that is supposed to happen via the host from the message thread.

My PullRequest works in Ableton Live because it doesn’t touch the EditControllers parameters from the audio thread and instead uses its own variables .

---

<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:** [January 11, 2021, 7:00pm UTC](https://forum.juce.com/t/bug-vst3-program-parameter-does-not-record-automation/43254/12 "2021-01-11T19:00:28Z")

</div>

Thanks for the further info and apologies for the delay in getting back to you. You’re correct that going via the `EditController` is wrong as its methods should only be called on the message thread. We’ve pushed a fix to `develop` which uses the existing JUCE AudioParameter infrastructure to propagate the program parameter changes which should avoid these issues, and we’ve made the logic for determining whether the program has changed a bit more robust. I’ve tested this in Live, Reaper and BitWig and no longer see the spurious updates or automation being cancelled. Please let us know if this fixes things for you:

> <https://github.com/juce-framework/JUCE/commit/dd1ec144c4de8551d6c9c3c960de84a53ad9db5c>

---

<div class="post-metadata">

**Author:** ![sparklingRhubarb](https://avatars.discourse-cdn.com/v4/letter/s/8dc957/32.png) [@sparklingRhubarb](https://forum.juce.com/u/sparklingRhubarb)\
**Post date:** [January 12, 2021, 8:58am UTC](https://forum.juce.com/t/bug-vst3-program-parameter-does-not-record-automation/43254/13 "2021-01-12T08:58:03Z")

</div>

Thanks for adding this to develop!  
I’m sorry to report that Ableton doesn’t seem to record Automation anymore. In Bitwig it appears to work. Can you reproduce this behaviour?

Edit: I can see that execution runs through lines 963-968 so `beginEdit()` and `endEdit()` is called. I can also see that Ableton Live switches the “currently visible automation lane” in the arranger view so that it shows the program parameter. So Ableton recognizes that there is a change, but apparently doesn’t record that change. Not sure why, tbh.

---

<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:** [January 12, 2021, 9:10am UTC](https://forum.juce.com/t/bug-vst3-program-parameter-does-not-record-automation/43254/14 "2021-01-12T09:10:22Z")

</div>

> [@sparklingRhubarb](#):
>
> I’m sorry to report that Ableton doesn’t seem to record Automation anymore

I’m not able to reproduce this - I’ve tested in both Live 10 and 11 and both are recording automation fine for the program parameter.

How are you setting this up? The steps I’ve taken are to add the plug-in, unfold the device parameters, right-click on the program parameter and select “Show automation”, then hit record and move the parameter control.

---

<div class="post-metadata">

**Author:** ![sparklingRhubarb](https://avatars.discourse-cdn.com/v4/letter/s/8dc957/32.png) [@sparklingRhubarb](https://forum.juce.com/u/sparklingRhubarb)\
**Post date:** [January 12, 2021, 9:36am UTC](https://forum.juce.com/t/bug-vst3-program-parameter-does-not-record-automation/43254/15 "2021-01-12T09:36:54Z")

</div>

Here’s what I did:

1. Open new project
2. Add plugin to a track
3. switch the arranger view to automation mode (the small button above the track list on the right side of the screen)
4. hit record and touch the preset-selector component in our plugin.

I can see that Ableton colours the entire track slightly red as soon as I load a new preset and the track content switches to the automation lane of the program parameter, however, it doesn’t actually record the changes.

One thing we may be doing differently is how we notify about the changed program. I do it exclusively via `updateHostDisplay()` - that is: Loading a preset via my plugin GUI eventually calls `updateHostDisplay()`. I never actually touch the program parameter itself. I suspect you may be editing the program parameter and that’s why we see a difference.

I noticed that in line 958 the value of `paramValue` never actually changes over the course of my tests (the value I see while debugging stays the same over the entire lifecycle of the plugin instance). It seems to me like line 964 `paramChanged()` never fully updates the value of the parameter. Maybe that’s why Ableton recognizes the beginning of the change gesture but doesn’t actually record the change - it just never sees a change in the parameter value.

I debugged into `paramChanged()` and noticed that the `if (...)` in line 617 makes `ProgramChangeParameter::setNormalized()` abort in line 619 when it is called from `updateHostDisplay()`. That’s why `valueNormalized` is never actually updated which is exactly what I observed.

---

<div class="post-metadata">

**Author:** ![sparklingRhubarb](https://avatars.discourse-cdn.com/v4/letter/s/8dc957/32.png) [@sparklingRhubarb](https://forum.juce.com/u/sparklingRhubarb)\
**Post date:** [January 12, 2021, 10:02am UTC](https://forum.juce.com/t/bug-vst3-program-parameter-does-not-record-automation/43254/16 "2021-01-12T10:02:35Z")

</div>

Can you try this for `ProgramChangeParameter::setNormalized()`? It seems to fix things for me.

```auto
        bool setNormalized (Vst::ParamValue v) override
        {
            auto programValue = roundToInt (toPlain (v));
                        
            if (isPositiveAndBelow(programValue, owner.getNumPrograms())
                && programValue != owner.getCurrentProgram())
                owner.setCurrentProgram(programValue);

            if (valueNormalized == v)
                return false;

            valueNormalized = v;
            changed();

            return true;
        }

```

---

<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:** [January 13, 2021, 10:45am UTC](https://forum.juce.com/t/bug-vst3-program-parameter-does-not-record-automation/43254/17 "2021-01-13T10:45:53Z")

</div>

I can reproduce this now, thanks. We’ve pushed a fix to `develop`:

> <https://github.com/juce-framework/JUCE/commit/2b3d0c05f547638e8626c5c05359ce234c1e3e96>
