Hi All, I've been converting my old VST plugins over to LADSPA and have come across something in the api which I really miss - the inability separate the algorithmic to the displayed value of a parameter. I'm finding this inability is leading to non-ideal programming habits.
Let me show what I mean with a few examples. I have a control that represents a gain knob (say -12dB -> 12dB): What's best for the run function is a value that represents the ratio which I can simply multiply the audio by as it it keeps the maths simple (0.25 -> 4). What's best for display is decibels (as that is way gain is understood). I can't do this with LADSPA - so as I programmer I'm left with a lose-lose choice. * I either choose a parameter range of -12 -> 12 (dB) and convert that to a ratio every time the run function is called: fGain = pow(10, *(psMyPlugin->m_pfControlGain) /20); Which is an unnecessary use of cpu. (and as someone who has mixed many albums on computers you need every scap of cpu you can get) * Or I choose to use 0.25 -> 4 as my range. Now users are faced with a parameter they don't intuitively understand (it is contrary to every other bit of audio gear they have ever used) - most people cannot do 20*Log10(Gain) in their heads to work out the equivalent value in dB. Of the two choices I choose the first, better to eat up too much cpu than to have an interface that is unintuitive, but this is not ideal. This gets worse when you have a control for something like 'warmth'. The user does not need to know the range of values required to apply warmth in an efficient manner (it won't mean anything to them), they just need to know how much (0%-100%). Another example - presets I have a control that allows an operator to chose one of fifty presets (say a reverb with small room, medium room, large room, hall etc). I don't have a choice this time. Internally using an integer to represent the different presets is fine, it's exactly all I need. However even though I know what the preset is, I cannot display it's name back to the user, so our user is left with a set of meaningless numbers which they must resolve into names by some other means (print the doco out and stick it on the wall?) What I'd find useful in the api is an optional 'get_display' function which allows the host app to get a human interpretation of a parameter for display. It would only need to be called when a plugin windows is opened or when a parameter is changed. Since the host has to convert the parameter to a string in order to display it anyway, this is not a extra step overall. We are just bringing it into the realm of the plugin. /* pseudo code */ void GetMyDisplay(char *stDisplay, int Size, unsigned long Port) { stTemp[LADSPA_MAX_EVER_DISPLAY_SIZE); switch(Port) { case MY_GAINCONTROL: sprintf(stTemp,"%4.1f dB",20*log10(PortValue)); stTemp[Size-1]='\0'; /* truncate it to what the host wants*/ strncopy(stDisplay,stTemp,Size); break; case MY_WARMTHCONTROL: sprintf(stTemp,"%4.1f %%",some_complex_function(PortValue)); stTemp[Size-1]='\0'; /* truncate it to what the host wants*/ strncopy(stDisplay,stTemp,Size); break; } } Now for a wish. GUI - under OSX or windows this isn't such a big drama, there's only one GUI environment to deal with. under Linux it's a different matter. I sometimes think the best thing to do is to provide enough hints to the host so it can render a more comprehensive gui, if it desires, rather than the plugin drawing the gui as is traditionally done. This would entail a few things. 1) Utilize ports of type: LADSPA_PORT_OUTPUT | LADSPA_PORT_CONTROL what is that? -> it's a meter, a light, etc We'd just need some hints defined and the rest is up to the host (most host apps already have their own audio specific widgets. we just need to tell them which ones we want to use). These all need to be bounded as any other control would be. /* a peak meter, expects a ratio not a dB value */ LADSPA_HINT_METER_PEAK /* a vu meter, expects a ratio not a dB value */ LADSPA_HINT_METER_VU /* Some meters like gain reduction meters in a compressor meter backwards, ie illuminated from max value downwards rather than minimum value upwards */ LADSPA_HINT_METER_REVERSED /* a simple on/off light */ LADSPA_HINT_LIGHT_ONOFF /* a light which has intesity */ LADSPA_HINT_LIGHT_INTENSITY 2) Add control layout to the port definitions Could be done as by defining arbitrary bounding boxes. /* * +----------+------+ * | gain | | * +----------+ meter| * | warmth | | * +----------+------+ */ PortLayoutHints[MY_GAIN].top=0; PortLayoutHints[MY_GAIN].bot=1; PortLayoutHints[MY_GAIN].left=0; PortLayoutHints[MY_GAIN].right=3; PortLayoutHints[MY_WARMTH].top=1; PortLayoutHints[MY_WARMTH].bot=2; PortLayoutHints[MY_WARMTH].left=0; PortLayoutHints[MY_WARMTH].right=3; PortLayoutHints[MY_METER].top=0; PortLayoutHints[MY_METER].bot=2; PortLayoutHints[MY_METER].left=3; PortLayoutHints[MY_METER].right=5; 3) Customization - control colours in the layout hints - background & logo images in the descriptor etc This would all be optional for the host Thanks for taking the time to read though all this, turned out to be longer than I anticipated! regards, Fraser