Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make Parameter class accessible by both Plugin and UI #150

Open
jpcima opened this issue Jul 5, 2019 · 6 comments
Open

Make Parameter class accessible by both Plugin and UI #150

jpcima opened this issue Jul 5, 2019 · 6 comments

Comments

@jpcima
Copy link
Collaborator

jpcima commented Jul 5, 2019

In a LV2 UI, the bypass value received in parameterChanged is the inverse of the DSP value.

DSP sets parameter 0: 0.000000
UI receives parameter 0: 1.000000

But in VST, it's fine.

DSP sets parameter 0: 0.000000
UI receives parameter 0: 0.000000

DistrhoUILV2 should invert a parameter with the bypass designation before sending.
Problem: the parameter metadata is not accessible from a separated UI, so it's unknown which parameter is a bypass.

@jpcima
Copy link
Collaborator Author

jpcima commented Aug 23, 2019

To this problem, I have in mind some solutions, none of which are particularly ideal.

  1. to also have the UI able to invoke initParameter from a shared code file; then, it's known which one is the bypass, and it can handle accordingly. Since initParameter must move outside of Plugin, the solution doesn't preserve compatibility.

  2. to have the UI build the whole FILES_UI + FILES_DSP. Then, Plugin is instantiable from UI, and initParameter is invocable. It maintains compatiblity.

  3. the DSP communicates to UI, by messaging, the identity of the bypass parameter. this hack increases complication on framework side, but doesn't require change.
    It has to consider carefully the lifecycles of these actors.

  4. the UI is asked to implement a method getParameterDesignation, from which bypass can be identified. example:

class MyUI : UI {
    ParameterDesignation getParameterDesignation(uint32_t index) {
        return (index == 0) ? kParameterDesignationBypass : kParameterDesignationNull;
    }
};

@jpcima
Copy link
Collaborator Author

jpcima commented Nov 26, 2019

It was proposed on IRC discussion to favor a macro such as DISTRHO_PLUGIN_WANT_BYPASS.
At the same time, plugins may be allowed to implement a pair of virtual methods: run, and runBypassed.

It's some first thoughts on the matter:

  • Method pair suggests to operate as binary on/off, but I don't think it should

I would favor the implementation practice where bypass will be smoothed as a gain between 0-1, avoiding the clicky transition. The bypass will act more as a tri-state: Off ↔ Transition ↔ On
(for example: on Bypass clicked, fade gradually the volume, and engage a True-Bypass once attenuation fades below a -80dB threshold)

It's why I think preferable for the plugin implementer to decide when bypass engages, instead of the framework to decide so. I would think the pair of methods discourages the best practices.

If I were to implement the bypass in a way driven as I want, it's a more awkward formulation.
For an example of what I mean:

Plugin::run() {
  myDsp.fBypassSwitch = 0;
  myDsp.run();
}
Plugin::runBypassed() {
  myDsp.fBypassSwitch = 1;
  myDsp.run();
}
  • About changes on UI-side

If bypass stops to be represented as instance of Parameter, UI needs a replacement way to access it read/write, and receive the notification.

  • Abount UI and Parameters

The issue is related directly to this limitation: that UI is unable to access directly the array of parameters.

In my opinion, it's a shame that Parameters are not accessible in the framework, for reasons that exceed the simple one of bypass, and it's beneficial long-term if we can have them.
(the solution which I meant as point 1. of the previous post)

In UI development, I was many times fighting against a DPF "way of things", that wants parameter as Plugin-Only. It opens a possibility to formulate such things as:

  • calibrate this Slider according to settings of Parameter N.
    (eg: set min and max bounds, set a middle click default value, set logscale, and so on)

This helps application of D.R.Y. principles.

@falkTX
Copy link
Contributor

falkTX commented Nov 26, 2019

I fully agree that making the Parameter class accessible by both Plugin and UI class would be really helpful.
We can go into this route first, and then see how that works.
BUT, and this is a big but, we need to ensure it works as static constructor (this is where I failed last time).
To be clear, we need to allow to have something like this:

static const Parameter kMyPluginParameters[] = {
/* param1 here */,
/* param2 here */,
/* etc */
};

I really want to avoid the situation of having to define the same parameter data on DSP and UI side.
Also, we should do our best to make it easy for developers to avoid instance-access.
With those 2 things in mind, we can see how to proceed.

@falkTX
Copy link
Contributor

falkTX commented Nov 26, 2019

Now about the bypass, I see the issues about a new function for such processing yes, but it is important to remember that the plugin is not supposed to make any sound in this mode, so the run function is supposed to be different by design.
The MIDI event arguments are removed from the function (maybe the inputs as well?). We can pass a simple bool on it to indicate that the bypass has just started, so the plugin can setup some kind of fade-out mode.

Why do you think the UI needs to know if the DSP is bypassed or not? Does it make any difference?

@jpcima
Copy link
Collaborator Author

jpcima commented Nov 27, 2019

BUT, and this is a big but, we need to ensure it works as static constructor

I think of static const variables as a downgrade regarding the readability.

You can obtain a global, non-duplicated parameter array by using a function-scope static-local variable. It would do automatically the thing wanted, regardless of using separate binaries, or instance-access. (instanciate once-only, + is thread-synchronized)

const ParameterList& getGlobalParameters()
{
  static const ParameterList params = initTheParameters();
  return params;
}

I refer you to a pattern how I make this usually.

but it is important to remember that the plugin is not supposed to make any sound in this mode

The LV2 documentation seems to not really agree, judging from what I read from the property lv2:enabled. In reality, it mandates ("must") that plugin must smooth the transition.

See http://lv2plug.in/ns/lv2core/#enabled.

I think, operation like the current parameter is fine actually, just provide the value 0-1 that plugin feeds into a lowpass.

The MIDI event arguments are removed from the function (maybe the inputs as well?).

Inputs must stay, because sound has to compute during a transition period.

Why cut the MIDI? does a part of specification say something about it?

Why do you think the UI needs to know if the DSP is bypassed or not? Does it make any difference?

It needs it, in case UI indicated bypass status by check button or LED.
Some pedal designs have one of these or both.

@falkTX falkTX added this to the next-release milestone Apr 19, 2020
@falkTX falkTX added this to Needs triage in Bug Fixing via automation May 20, 2021
@falkTX falkTX moved this from Needs triage to High priority in Bug Fixing May 24, 2021
falkTX added a commit that referenced this issue Jul 4, 2021
@falkTX
Copy link
Contributor

falkTX commented Jul 4, 2021

The issue with bypass inverted was fixed in e889c58
This ticket has some conversation that it is useful to maintain, I dont want to close it, so I will rename the ticket.

@falkTX falkTX changed the title Bypass parameter is inverted in LV2 ui Make Parameter class accessible by both Plugin and UI Jul 4, 2021
@falkTX falkTX removed this from High priority in Bug Fixing Jul 4, 2021
@falkTX falkTX modified the milestones: next-release, long-term (or PR) Jul 4, 2021
@falkTX falkTX added this to To do in Feature Requests v2 Sep 18, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Development

No branches or pull requests

2 participants