Parameter updates get lost between controller and processor using performEdit

Hi,

While developing a VST3 instrument plugin, I’m stuck with a major issue:

When notifying the host from the controller side using performEdit, some messages get lost in the forwarding and don’t reach the processor.
I checked that all parameter changes occur on the controller side. Calls for performEdit are correctly performed every time.
However, on the Processor side, sometimes parameter updates don’t appear in the process() method when parsing data.inputParameterChanges.
This happens in different DAWs, with different VST3 SDK versions.

Do you have any recommendation on how properly debug this, or maybe a simple example ?

I have never experienced this problem. Are you sure you call:

beginEdit(id);

then 

performEdit(id);
performEdit(id);
performEdit(id);
...

then

endEdit(id);

I have encapsulated this sequence in a Editor concept, so that I don’t really have to think about it (beginEdit is done in constructor and endEdit in destructor).


Although now that I look at the code, it seems I also call setParamNormalized (see setValue method) in addition to performEdit.

Yan

Here is the code called from the Controller when setting a parameter from any of my UI widgets (slider, button, …):

// Notify a parameter changed -----
        
if(setParamNormalized(tag, value) != Steinberg::kResultOk) {
    printf("Fail to call set param normalized in Controller::SetParameter\n");
    return false;
}

// Transmit value to host -----

EditController::beginEdit(tag);
Steinberg::tresult result = EditController::performEdit(tag, getParamNormalized(tag));
EditController::endEdit(tag);

if(result != Steinberg::kResultOk) {
    printf("Perform Edit failed, param: %d, value: %f\n", paramId, value);
    return false;
}

From the Processor process() method:

Steinberg::int32 num_params_changed = data.inputParameterChanges->getParameterCount();
            
// Process each param
for(Steinberg::int32 index = 0; index < num_params_changed; ++index) {
    
    Steinberg::Vst::IParamValueQueue* paramQueue = data.inputParameterChanges->getParameterData(index);
    
    if(!paramQueue) {
        continue;
    }
    
    uint32_t param_id = paramQueue->getParameterId();
    Steinberg::int32 num_points = paramQueue->getPointCount();
    
    // Process each param value change
    for(Steinberg::int32 point=0; point < num_points; ++point) {
        
        Steinberg::Vst::ParamValue value = 0.f;
        Steinberg::int32 sampleOffset = 0;
        
        if(paramQueue->getPoint(point, sampleOffset, value) == Steinberg::kResultTrue) {
            if(param_id >= mParamIdToEngineParamIndexTable.size()) {
                printf("ERROR: out of range param id: %d\n", param_id);
                continue;
            }
            
            uint32_t engine_param_idx = mParamIdToEngineParamIndexTable[param_id];
            mAudioEngine->SetParameter(engine_param_idx, static_cast<float>(value));
        }
    }
}

These are directly inspired from the samples included in the VST3 SDK public.sdk section.
Am i doing something wrong here ?

Sorry to dig up this topic, but I’m still facing this issue.

It’s quite random and when I detect that the parameter update has not been forwarded, it’s already too late. Do you have any idea on how I can debug this properly ?

Is there a proper documentation on this topic somewhere ?

Thanks.

Ok, so I spent some time trying to narrow down the issue. The problem seems to be located in my processor’s process() method (see code in a previous comment).

I replaced my audio engine processing code with a basic sine wave generator. With this simple code, everything runs well, all parameter updates (sent from performEdit) seem to arrive properly in the inputParameterChanges queue.

Now, if I make a sleep() call for 5ms after the sinewave generation, the problem occurs very frequently.

Could the inputParameterChanges queue feeding be blocked when the process() method is doing too much work ?

Any idea on what could be the issue otherwise ?

Hi, I am facing the same problem…
I called PerformEdit() in GUIEditor::valueChanged() but sometimes it is not notified to the processor.

I have also called beginEdit(), endEdit() but it does not solve the problem.
I have attached an image displayed by printf().

This

Has the issue been resolved since then??
Thank you.

Unfortunately I’m still having the same issue and I haven’t found any solution to it :confused:

Thanks for the reply.
I’ll try other methods now, will report back if it works!

Thanks.
Does the issue happens more frequently when you add the sleep() call as I mention above ?

I don’t know if it’s worth mentioning but I’m using a VSTGUI::COpenGLView as view, it’s a bit exotic. Do you use a standard view ?

Also I’m using VST3SDK version 3.7.1

1 Like

Hi, I’m Japanese programmer, so sorry if my sentence is wrong, haha…
In my case, Even I don’t call sleep(), the problem occurs…
Yes I don’t use OpenGL, I use the common VSTGUIEditor.

My version is 3.7.5.

The latest version is 3.7.7, So I’ll try it tomorrow !

I have the issue even if I don’t call sleep() as well, that was a way of reproducing the issue easily, because it happens only sometimes.
Thanks for your info.

I’ve updated my VST3SDK to version 3.7.7, I’ll let you know if it solves the issue.

1 Like

Hi, Unfortunately…the latest 3.7.7 also causes the same problem…yeah…

But I’m happy to report that I was able to solve the problem in my way!

In my case, when I turn the Knob, sometimes the notification does not reach the processor.
(This is especially true when I run Knob too fast).

So far, I have been calling performEdit() within a function called valueChanged() in Editor, but that did not work correctly.
(I think this is probably the normal way in most cases.)

But I called performEdit() on every knob dragging frame, It works!

I created a class that inherits from CAnimKnob and coded it to always send a notification while dragging.
To implement this, the CustomKnob class must have an instance of EditorController, which is necessary for notifications, so I register it as an argument when the Knob is initialized.

Then all, we have to do is override onMouseDown, onMouseMoved(), etc., and call performEdit() in them.
This is a bit tedious, but I hope it helps you.

If it’s not a control operation, but some special timing, you could use a timer.

Did my answer help you ??

My source code comment’s is japanese, sorry…

Hey,

In my case it also happens with buttons, not only knobs.
I use a custom based UI framework which does quite the same as the code you show in your image. Anyway, I will investigate more in details when I’ll have more time to assign to this issue.

Thanks a lot for letting me know, and glad you managed to solve it !

Just a point: It is recommended to call beginEdit /endEdit only when the knob will start to move / stop to move, not for every change!

Yes, I’m sorry…
I forgot, yeah, my button also occurs.

Additionally, I needed to improve on my previous code.

I changed the way it as follows. →
1: Keep the control instance from arguments of valuechanged. (CControl*)
2: I provided a timer that notified the processor of the value of 1’s control for about 5 consecutive frames, and that definitely fixed the problem.

I hope the Steinberg developers fix this problem…

1 Like

Thank you for the answer.
OK, but why does this problem occur?
Are there any plans to improve the current VST3 SDK?

1 Like