Hi Michael and Holger,
This is a followup to something originally posted to the user list.
(Re: [Rosegardenuser] Entering values for LADSPA plugins directly)
I've spent some time delving into the mystery you describe below, and
have attached a patch against svn_13007 that fixes the problem (three
problems, actually).
On Sunday, August 26, 2012, D. Michael McIntyre wrote:
> On Saturday, August 25, 2012, Holger Marzen wrote:
>
> > I cannot set the values directly. Setting them with the mouse (turning
> > the knob) works but is way too coarse. Entering the value in the input
> > field or using up and down arrows always leads to the minimum value of
> > 0.25.
>
> Same thing here with the latest development build. You're not crazy.
>
> Using the AM pitch shifter thing as a test bed, the knob that moves in
> integer increments seems to be working just fine. The knob that lets
> you set a floating point value has big problems.
>
> The display appears to be limited to two decimal places of precision,
> but the arrow buttons obviously let you make changes in finer increments
> than that. The result is that you have to click repeatedly in order to
> see a visible change.
>
> Once you've made the change, either by using the arrow buttons or by
> typing a value directly, that change gets corrupted somewhere along the
> way. Try to change to 1.03 and the result is the knob gets set to some
> fantastically wrong number like 1e10.
>
> That kind of wildly nonsensical number is usually an uninitialized
> variable, but it seems like there could definitely be type conversion
> and/or precision issues mixed up in here too. I'm weak on floating
> point math, so this might be a common pattern I don't even recognize.
>
> I spent some time poking around, and only started to get the idea of
> how all of these many intricate little puzzle pieces fit together.
> This would just take more time than I have to sort through and work
> out, but it's probably a really simple and obvious problem.
> 
> D. Michael McIntyre
In long, boring detail, here is what I discovered.
The problem begins in Rotary::mouseDoubleClickEvent
(src/gui/widgets/Rotary.cpp).
When a rotary widget is double clicked, a spinBox is created by
FloatEdit to manipulate the value directly. A rotary widget in the
logarithmic mode works on the logarithms of the actual minimum, maximum,
and position values, so these logarithms must be converted back into
actual values, in order to keep the spinBox happy. Furthermore,
FloatEdit uses the value of "step" to define the number of decimal
places for the spinBox, as well as to set its step. Beginning at
line 436,
minv = powf(10, minv);
maxv = powf(10, maxv);
val = powf(10, val);
correctly reconstitute the original values, but
step = powf(10, step);
does not.
Rather than tampering with the laws of mathematics, I decided to
redefine step initially as
step = (maxv  minv) / 100.0;
This initial value can then be used to pick a final value for step that
will (probably) yield an acceptable number of decimal places in the
spinBox.
if (step > 1.0) {
step = .1;
} else if (step > .1) {
step = .01;
} else {
step = .001;
}
Hopping over to FloatEdit::FloatEdit (src/gui/dialogs/FloatEdit.cpp),
another problem shows up at line 56:
double calDP = log10(step);
int dps = 0;
if (calDP < 0.0)
dps = int( calDP);
looks like it should correctly calculate the number of decimal places,
but it doesn't. step is of type float, but log10() expects type
double. It seems that a very small rounding error is then screwing up
the cast conversion to type int. The following snippets of code
illustrate the problem:
float num = .001;
printf("log10(num): %f", log10(num));
> log10(num): 3.000000 (As expected.)
printf("int(log10(num)): %d", int(log10(num)));
> int(log10(num)): 2 (Huh?)
double inte;
double frac = modf(log10(num), &inte);
printf("integer: %f fraction: %f", inte, frac);
> integer: 2.000000 fraction: 1.000000 (What the ...?????)
printf("3.0  (log10(num)): %e", 3.0  (log10(num)));
> 3.0  (log10(num)): 2.062788e08 (Oh.)
After returning to Rotary::mouseDoubleClickEvent
(src/gui/widgets/Rotary.cpp), another problem appears at line 471:
if (m_position < powf(10, 10)) m_position = 10;
is equivalent to writing
if (m_position < .0000000001) m_position = 10;
which is almost like writing
if (m_position <= 0) m_position = 10;
But since m_position is a logarithm of the actual value here, it must
be allowed to take on some reasonable negative value, if it is to
represent some positive, fractional actual value.
if (m_position < 10) m_position = 10;
is probably what was originally meant here.
Tim
