From: Andrew D. <and...@gm...> - 2014-11-15 08:37:47
|
Hi, guys! Recently I found out why dexed synth is initialized with volume control set to zero in lv2host and how to deal with this. Here is the steps I've taken: 1. After examining ttl files used by plugin it became clear that default value for volume control is zero. So plugin was initialized right in MusE. 2. But, in ardour and jalv volume was initizlized to 1 (maximum value). I started to search for a reason. 3. Dexed is built on the base of juce. Juce uses it's own cache of controls and on each run() checks this cache and current control values. If the cache value differs, juce sets plugin value to current supplied host value: curValue = *portControls[i]; if (lastControlValues[i] != curValue) { filter->setParameter (i, curValue); lastControlValues.setUnchecked (i, curValue); } Here portControls is array of pointers to controls (of type float) that were connected by lv2 host via connect_port() calls. It was clear, that current volume control is not set to zero upon plugin instantiation. 4. Than I found that class member PluginFx fx holds member `float uiGain` that is the current volume level. But PluginFx has no default constructor, so uiGain may be left uninitialized. C++ standard says that this default value should be zero. But it seams that gcc ignores this standard or implements it in a different way. The result is that member float variable in that case was initialized to 4.59163468e-41. It's very close to zero, but expression (0 == 4.59163468e-41) whatever gives false (and it's right). 5. Than, while checking dexed activate() method I found that uiGain was initialized to 1 (maximum value). But: juce already cached wrong value of uiGain = 4.59163468e-41 during plugin construction. And on the first call of run() current value (1, set by activate()) is reset to zero (current host value) by the above code because 0 != 4.59163468e-41. And as a result we have no output from the plugin. 6. But anyway it was very interesting why in ardour, qtractor and jalv dexed does not reset it volume level though the lv2 code of all these hosts sets volume control by to default value (zero from ttl files) - I checked it. And now it's time for the very interesting finding. Somehow gcc makes this equation (0 == 4.59163468e-41) return true in these hosts. But how? I've checked various flags and found the one that makes it: -funsafe-math-optimizations Yes, that's it. This flags makes assumption that values too close to zero == 0, so in this case (0 == 4.59163468e-41) is always be true is this flag is set. That's why juce doesn't reset volume to zero and uses cached control. But in the same time host holds current volume level == 0. So there are 3 values are there: 4.59163468e-41 (cached by juce), 0 (host value) and 1 (current plugin value). This flag is a part of -ffast-math gcc option, so, when MusE is built in release mode (0 == 4.59163468e-41) will always return true. So the summary is: 1. This bug is completely releted to Dexed. 2. Hosts, that compiled with -funsafe-math-optimizations set in any way will respect this bug. 3. Only the lack of this option in MusE debug build helped me to find out the reason, so I leaved debug build flags as is. That's all, quest is solved :) P.S. I've also made some optimizations to lv2 host code recently to get rig of warnings and support new lv2 lib api in atom forge.h. Changes are in master now. Regards, Andrew |