free-audio / clap-wrapper

Wrappers for using CLAP in other plugin environments
MIT License
124 stars 20 forks source link

off by one error in value conversion #301

Closed defiantnerd closed 2 months ago

defiantnerd commented 2 months ago

@baconpaul this is a fix for issue https://github.com/free-audio/clap-wrapper/issues/300

I wonder if the function below inline double asVst3Value(double clapvalue) const the +1 needs to be removed, too.

baconpaul commented 2 months ago

So step count "1" means to positions one gap. So the function below for a 0..1 value would give a VST3 value of 0...0.5 because of the +1 So I agree with you that other +1 has to go

defiantnerd commented 2 months ago

ok, checked out the documentation here: https://steinbergmedia.github.io/vst3_dev_portal/pages/Technical+Documentation/Parameters+Automation/Index.html#conversion-of-normalized-values

Discrete Value => Normalize double normalized = discreteValue / (double)stepCount;

Normalize => Discrete Value (Denormalize) int discreteValue = min (stepCount, normalized *(stepCount + 1));

I'll take a look if that is properly converted here.

baconpaul commented 2 months ago

Doesn't that mean Discrete(Normalize(val)) != val? since it is discrete/stepcount * (stepcount+1)

lewloiwc commented 2 months ago

I was also curious about the Discrete(Normalize(val)) != val issue, so I tried to organize it in a diagram. (I apologize for it being extremely difficult to read.) image At first, I also thought that Discrete(Normalize(val)) != val would be true, but it seems that the rounding that occurs due to "int discreteValue = x" was important. Therefore, I think this error can probably be fixed by removing the +1 from both asClapValue and asVst3Value. When I actually created a VST3 with the version where I removed these, it seems to be working correctly so far.


I looked into it further. When using the formula from the VST 3 Developer Portal directly in asVst3Value, it likely results in an incorrect modification.

I made comparisons using the following: ↓A slightly modified CLAP based on clap-c99-distortion

clap_c99_distortion_plug
-   int32_t mode;
+   float mode;

c99dist_process_event
-   plug->mode = (int)(ev->value);
+   plug->mode = ev->value;

c99dist_process
-   switch (plug->mode) {...}
+   tr = tl = sin(6.28*(i/48000.0*1000.0*plug->mode));

↓A VST3 with probably correct modifications to the parameter.h of clap-wrapper

asClapValue
-   return (vst3value * info.stepCount + 1) + min_value;
+   return (vst3value * info.stepCount) + min_value;

asVst3Value
-   return (clapvalue - min_value) / float(info.stepCount + 1);
+   return (clapvalue - min_value) / float(info.stepCount);

↓A VST3 with likely incorrect modifications using the formula from the VST 3 Developer Portal

asClapValue
-   return (vst3value * info.stepCount + 1) + min_value;
+   return int32_t(min(info.stepCount,vst3value * (info.stepCount + 1))) + min_value;

asVst3Value
-   return (clapvalue - min_value) / float(info.stepCount + 1);
+   return (clapvalue - min_value) / float(info.stepCount);

CLAP → https://youtu.be/SNNye0PwH68 It can obtain continuous values during automation.

VST3 (probably correct) → https://youtu.be/fGazHOll7TI It can obtain continuous values during automation.

VST3 (probably incorrect) → https://youtu.be/hqCUFtvZibY Since rounded values are sent to CLAP, discrete values are obtained.