damiensellier / CtrlrX

CtlrX is an alternative fork of Roman Kubiak's Ctrlr. This project is ONLY aimed at delivering updates, a wiki, documentations, tutorials or anything that the community cannot share on the original Ctrlr github due to credential restrictions.
BSD 3-Clause "New" or "Revised" License
16 stars 3 forks source link

uiSlider max value mapping is not working. (ie: min -99 max 99 have values -99 to +98) #24

Closed damiensellier closed 1 week ago

damiensellier commented 2 weeks ago

uiSlider max value mapping is not working. (ie: min -99 max 99 have values -99 to +98).

https://github.com/RomanKubiak/ctrlr/issues/650

damiensellier commented 2 weeks ago

NOTE : here is a lead to the problem. mapped values are not rounded in Ctrlr 5.6.26+

5.3.198 Capture d’écran, le 2024-06-15 à 22 15 47

5.6.30 Capture d’écran, le 2024-06-15 à 22 14 45

damiensellier commented 2 weeks ago

in Xcode search for : modulatorMin

damiensellier commented 1 week ago

See : minValue = newMinValue;

damiensellier commented 1 week ago

class CtrlrModulatorProcessor : public AsyncUpdater, public Expression::Scope, public CtrlrMidiMessageOwner { public: CtrlrModulatorProcessor(CtrlrModulator &_owner); ~CtrlrModulatorProcessor();

    String getScopeUID() const;
    Expression getSymbolValue (const String& symbol) const;
    void visitRelativeScope (const String &scopeName, Visitor &visitor) const;
    void visit (const Scope &scope);
    void setForwardExpression (const String &forwardExpressionString);
    void setReverseExpression (const String &reverseExpressionString);
    void setModulatorMaxValue (const int newMaxValue);
    void setModulatorMinValue (const int newMinValue);
    void setValueChangedCallback (const String &methodName);
    void setGetValueFromMidiCallback (const String &methodName);
    void setGetValueForMidiCallback (const String &methodName);
    int getValue() const;
    int getValueMapped() const;
    int getMax() const;
    int getMin() const;

    /** Used for evaluating expressions when getting the midi value from the modulator (forward evaluation)

        A list of constants that can be used:
        - modulatorValue : the current linear value of the modulator
        - modulatorMappedValue : the current mapped value in case of components that have mappings
        - modulatorMax : the maximum value the modulator can have (non mapped)
        - modulatorMin : the minimum value the modulator can have (non mapped)
        - vstIndex : the VST/AU index of the paramter as seen by the host program
        - midiValue : the current value stored in the MIDI MESSAGE assosiated with the modulator
        - midiNumber : the number of the MIDI MESSAGE controller if applicable
    */
    int evaluateForward(const int inValue);

    /** Used for evaluating expressions when getting the modulator value from the incomming midi message

        A list of constants that can be used:
        - modulatorValue : the current linear value of the modulator
        - modulatorMappedValue : the current mapped value in case of components that have mappings
        - modulatorMax : the maximum value the modulator can have (non mapped)
        - modulatorMin : the minimum value the modulator can have (non mapped)
        - modulatorMappedMax : the maximum value the modulator can have (mapped)
        - modulatorMappedMin : the maximum value the modulator can have (mapped)
        - vstIndex : the VST/AU index of the paramter as seen by the host program
        - midiValue : the value of the incomming midi message
        - midiNumber : the number of the MIDI MESSAGE controller if applicable
    */
    int evaluateReverse(const int inValue);

    /** When evaluating expression in either direction a couple of utility functions can be used, the notation is the same as in C
        for example to get the absolute value of the modulator you'd type: "abs(modulatorValue)" as the expression

        A list of constants that can be used:
        - ceil : Returns the smallest integral value of the parameter
        - abs : Returns the absolute value of the parameter
        - floor : Returns the largest integral value that is not greater than the parameter
        - mod : divides two numbers and returns the result of the MODULO operation "%" in C 10 % 3 = 1, 0 % 5 = 0; 30 % 6 = 0; 32 % 5 = 2
        - fmod : Returns the floating-point remainder of the two parameters passed in
        - pow : Returns the first parameter raised to the power of the second (dunno what that could be used for but it's there)
        - gte : Return the larger or equal of the two passed parameters (a >= b), gte (modulatorValue, 0, modulatorValue, 128 - modulatorValue)
                will return modulatorValue if modulatorValue is greater then 0 and (128 - modulatorValue) if it is less then zero
        - gt : same as gte but greater then without the equal sign (a > b)
        - max : returns the bigger of two parameters
        - min : returns the smaller of two parameters
        - getBitRangeAsInt (value, startBit, numBits)
        - setBitRangeAsInt (value, startBit, numBits, valueToSet)
        - clearBit (value, bitToClear)
        - isBitSet (value, bitPosition)
        - setBit (value, bitToSet)
        - setGlobal (globalIndex, newValueToSet)
    */
damiensellier commented 1 week ago

min, max and interval values property sliders are always absolute in v5.6.30. min, max and interval values property sliders can have decimals in v5.2.198.

exemple for min -99.5 : Capture d’écran, le 2024-06-26 à 20 00 39

damiensellier commented 1 week ago

see : modulatorMax modulatorMin

  <id name="modulatorMax"                       text="Maximum value the modulator can have, should be set from the UI component" type="ReadOnly" min="-65536" max="65536" int="0.0001" />
  <id name="modulatorMin"                       text="Minimum value the modulator can have, should be set from the UI component" type="ReadOnly" min="-65536" max="65536" int="0.0001" />
damiensellier commented 1 week ago

5.6.30 vs 5.3.198 CtrlrIDs.xml are the same

damiensellier commented 1 week ago

Only difference is the (double) attribute to value in the CtrlrSlider.cpp files and the rounding formula :

Capture d’écran, le 2024-06-26 à 20 30 15

damiensellier commented 1 week ago

CtrlrModulatorProcessor.cpp :

void CtrlrModulatorProcessor::setModulatorMaxValue (const int newMaxValue)
{
    const ScopedWriteLock sl (processorLock);
    maxValue = newMaxValue;
}

void CtrlrModulatorProcessor::setModulatorMinValue (const int newMinValue)
{
    const ScopedWriteLock sl (processorLock);
    minValue = newMinValue;
}

Try to force values to integer (int)

minValue = (int) newMinValue;

maxValue = (int) newMaxValue;
damiensellier commented 1 week ago

https://github.com/RomanKubiak/ctrlr/blob/8aa00d82127acda42ad9ac9b7b479461e9436aa4/Source/UIComponents/CtrlrComponents/Sliders/CtrlrSlider.cpp#L175

Requires (float) type instead of (double) get proper mapping calculation for modulatorMin Value.

I put the commented v5.2.198 code on top of the function in case of, to remember the code we come from :

    else if (property == Ids::uiSliderInterval || property == Ids::uiSliderMax || property == Ids::uiSliderMin)
    {
        // This was the script in v5.2.198
        //ctrlrSlider.setRange ( (float) getProperty (Ids::uiSliderMin), (float) getProperty (Ids::uiSliderMax), (float) getProperty (Ids::uiSliderInterval) ); // Added back from v5.2.198 to v5.6.31 with float instead of double. Note: Float (32bit) is less precise than double (64bit).
        //owner.setProperty (Ids::modulatorMax, ctrlrSlider.getMaximum());
        //owner.setProperty (Ids::modulatorMin, ctrlrSlider.getMinimum());

        // The following script is different since v5.6.26+
        float max = getProperty (Ids::uiSliderMax); // v5.6.31 (float) instead of (double). (double) was giving false values when negative
        float min = getProperty (Ids::uiSliderMin); // v5.6.31 (float) instead of (const double). (const double) was giving false values when negative
        float interval = getProperty (Ids::uiSliderInterval); // v5.6.31 (float) instead of (double). (double) was giving false values when negative
        if (interval == 0)
            interval = std::abs(max-min) + 1;
        // For JUCE MAX must be >= min
        if (max <= min) {
            // samething between 0.5 and 1 times the interval
            // to avoid rounding errors
            max = min + interval * 0.66;
        }
        ctrlrSlider.setRange ( min, max, interval );
        owner.setProperty (Ids::modulatorMax, ctrlrSlider.getMaximum());
        owner.setProperty (Ids::modulatorMin, ctrlrSlider.getMinimum());
    }

Capture d’écran, le 2024-06-26 à 21 45 16 Capture d’écran, le 2024-06-26 à 21 45 53

NOTE : Same problem is happening in CtrlrImageSlider.cpp for uiImageSlider :

https://github.com/damiensellier/CtrlrX/blob/d1052344ce5a9768e9d3ea75e3a15b8203920ce9/Source/UIComponents/CtrlrComponents/Sliders/CtrlrImageSlider.cpp#L173

FIX :

else if (property == Ids::uiSliderInterval || property == Ids::uiSliderMax || property == Ids::uiSliderMin)
    {
        ctrlrSlider->setRange ( (float) getProperty (Ids::uiSliderMin), (float) getProperty (Ids::uiSliderMax), (float) getProperty (Ids::uiSliderInterval) );  // v5.6.31 (float) instead of plain values. plain values and (double) were giving false values when negative.
        owner.setProperty (Ids::modulatorMax, ctrlrSlider->getMaximum());
        owner.setProperty (Ids::modulatorMin, ctrlrSlider->getMinimum());
    }