Jamba C++ API 7.5.0
Loading...
Searching...
No Matches
ParamConverters.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2018-2020 pongasoft
3 *
4 * Licensed under the Apache License, Version 2.0 or the MIT license,
5 * at your option. You may not use this file except in compliance with
6 * one of these licenses. You may obtain copies of the licenses at:
7 *
8 * https://www.apache.org/licenses/LICENSE-2.0
9 * https://opensource.org/licenses/MIT
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14 * License for the specific language governing permissions and limitations under
15 * the License.
16 *
17 * @author Yan Pujante
18 */
19#pragma once
20
22#include <pongasoft/VST/Types.h>
24
25#include <pluginterfaces/vst/vsttypes.h>
26#include <pluginterfaces/vst/ivstparameterchanges.h>
27#include <pluginterfaces/base/ustring.h>
28#include <base/source/fstring.h>
29#include <pluginterfaces/base/ftypes.h>
30
31#include <cmath>
32#include <algorithm>
33#include <memory>
34#include <string>
35#include <array>
36#include <vector>
37#include <map>
38#include <type_traits>
40
41namespace pongasoft::VST {
42
43using namespace Steinberg;
44using namespace Steinberg::Vst;
45
53template<typename T>
55{
56public:
57 using ParamType = T;
58 virtual int32 getStepCount() const { return 0; }
59 virtual ParamValue normalize(ParamType const &iValue) const = 0;
60 virtual ParamType denormalize(ParamValue iNormalizedValue) const = 0;
61 virtual void toString(ParamType const &iValue, String128 iString, int32 iPrecision) const { }
62 virtual std::string toString(ParamType const &iValue, int32 iPrecision) const
63 {
64 String128 s;
65 s[0] = 0;
66 toString(iValue, s, iPrecision);
67 return VstUtils::toUT8String(s);
68 }
69};
70
74class RawParamConverter : public IParamConverter<ParamValue>
75{
76public:
77
78 using IParamConverter<ParamValue>::toString;
79
80 inline ParamValue normalize(ParamValue const &iValue) const override
81 {
82 return Utils::clamp(iValue, 0.0, 1.0);
83 }
84
85 inline ParamValue denormalize(ParamValue iNormalizedValue) const override
86 {
87 return Utils::clamp(iNormalizedValue, 0.0, 1.0);
88 }
89
90 inline void toString(ParamValue const &iValue, String128 oString, int32 iPrecision) const override
91 {
92 staticToString(iValue, oString, iPrecision);
93 }
94
95 static inline void staticToString(ParamValue const &iValue, String128 oString, int32 iPrecision)
96 {
97 Steinberg::UString wrapper(oString, str16BufferSize(String128));
98 if(!wrapper.printFloat(iValue, iPrecision))
99 oString[0] = 0;
100 }
101};
102
109{
110public:
111 using IParamConverter<bool>::toString;
112
113 explicit BooleanParamConverter(VstString16 iFalseString = STR16("Off"),
114 VstString16 iTrueString = STR16("On")) :
115 fFalseString{std::move(iFalseString)},
116 fTrueString{std::move(iTrueString)}
117 {}
118
119 inline int32 getStepCount() const override { return 1; }
120
121 inline ParamValue normalize(bool const &iValue) const override
122 {
123 return iValue ? 1.0 : 0;
124 }
125
126 inline bool denormalize(ParamValue iNormalizedValue) const override
127 {
128 return toBoolean(iNormalizedValue);
129 }
130
131 inline void toString(bool const &iValue, String128 oString, int32 /* iPrecision */) const override
132 {
133 Steinberg::UString wrapper(oString, str16BufferSize(String128));
134 if(iValue)
135 wrapper.assign(fTrueString.c_str());
136 else
137 wrapper.assign(fFalseString.c_str());
138 }
139
143 inline static bool toBoolean(ParamValue iNormalizedValue) { return iNormalizedValue >= 0.5; }
144
145protected:
148};
149
153using Percent = double;
154
160{
161public:
162
164
165 inline ParamValue normalize(double const &iValue) const override
166 {
167 return Utils::clamp(iValue, 0.0, 1.0);
168 }
169
170 inline double denormalize(ParamValue iNormalizedValue) const override
171 {
172 return Utils::clamp(iNormalizedValue, 0.0, 1.0);
173 }
174
175 inline void toString(ParamType const &iValue, String128 oString, int32 iPrecision) const override
176 {
177 Steinberg::UString wrapper(oString, str16BufferSize (String128));
178 wrapper.printFloat(iValue * 100, iPrecision);
179 wrapper.append(STR16("%"));
180 }
181};
182
187static inline ParamValue convertDiscreteValueToNormalizedValue(int32 iStepCount, int32 iDiscreteValue)
188{
189 auto value = Utils::clamp<int32, int32>(iDiscreteValue, 0, iStepCount);
190 if(value == 0)
191 return value;
192 else
193 return value / static_cast<ParamValue>(iStepCount);
194}
195
200static inline int32 convertNormalizedValueToDiscreteValue(int32 iStepCount, ParamValue iNormalizedValue)
201{
202 // ParamValue must remain within its bounds
203 auto value = Utils::clamp(iNormalizedValue, 0.0, 1.0);
204 auto discreteValue = std::floor(std::min(static_cast<ParamValue>(iStepCount), value * (iStepCount + 1)));
205 return static_cast<int32>(discreteValue);
206}
207
218static inline int32 computeNextDiscreteValue(int32 iValue, int32 iStepCount, int32 iIncrement, bool iWrap)
219{
220 // no increment, noop
221 if(iIncrement == 0)
222 return iValue;
223
224 if(iStepCount > 0)
225 {
226 auto discreteValue = iValue + iIncrement;
227
228 // handles wrapping
229 if(iWrap)
230 {
231 if(iIncrement > 0)
232 {
233 while(discreteValue > iStepCount)
234 discreteValue -= iStepCount + 1;
235 }
236 else
237 {
238 while(discreteValue < 0)
239 discreteValue += iStepCount + 1;
240 }
241 }
242 else
243 {
244 // no wrapping => simply clamp the value to the range
245 discreteValue = Utils::clamp(discreteValue, Utils::ZERO_INT32, iStepCount);
246 }
247
248 return discreteValue;
249 }
250 else
251 {
252 return iValue;
253 }
254}
255
261template<int32 StepCount, typename IntType = int32>
263{
264public:
265 using ParamType = IntType;
266
267 using IParamConverter<IntType>::toString;
268
271 using ConstructorType = std::array<VstString16, StepCount + 1> const &;
272
273 // Constructor - you can provide an offset for the toString conversion (ex: counting from 1 instead of 0)
274 explicit DiscreteValueParamConverter(IntType iToStringOffset = 0) : fToStringOffset{iToStringOffset} {}
275
276 // Constructor with printf style format where the parameter (%d) will be (value + offset)
277 explicit DiscreteValueParamConverter(VstString16 iFormat, IntType iToStringOffset = 0) :
278 fToStringOffset{iToStringOffset}, fFormat{std::move(iFormat)} {}
279
280 // Constructor with all values defined
282 fToStringValues(iToStringValues.cbegin(), iToStringValues.cend()) {}
283
284 inline int32 getStepCount() const override { return StepCount; }
285
286 inline ParamValue normalize(ParamType const &iDiscreteValue) const override
287 {
288 return convertDiscreteValueToNormalizedValue(StepCount, static_cast<int32>(iDiscreteValue));
289 }
290
291 inline ParamType denormalize(ParamValue iNormalizedValue) const override
292 {
293 return static_cast<ParamType>(convertNormalizedValueToDiscreteValue(StepCount, iNormalizedValue));
294 }
295
296 // toString
297 void toString(ParamType const &iValue, String128 oString, int32 /* iPrecision */) const override
298 {
299 Steinberg::UString wrapper(oString, str16BufferSize (String128));
300 if(!fFormat.empty())
301 {
302 Steinberg::String s;
303 s.printf(fFormat.c_str(), iValue + fToStringOffset);
304 wrapper.assign(s.text());
305 }
306 else
307 {
308 if(fToStringValues.empty())
309 {
310 if(!wrapper.printInt(iValue + fToStringOffset))
311 oString[0] = 0;
312 }
313 else
314 {
315 wrapper.assign(fToStringValues[iValue].c_str());
316 }
317 }
318 }
319
320private:
323 std::vector<VstString16> fToStringValues{};
324};
325
352template<typename T, class Compare = std::less<T>>
354{
355public:
358 using TMap = std::map<T, std::tuple<VstString16, ParamValue, int32>, Compare>;
359
362 using TList = std::vector<T>;
363
366 using ConstructorType = std::initializer_list<std::pair<const T, VstString16>> const &;
367
368 using ParamType = T;
369
371
376 {
377 auto stepCount = static_cast<int32>(iInitList.size() - 1);
378
379 // by definition, a discrete parameter has a step count > 0
380 DCHECK_F(stepCount > 0);
381
382 int32 i = 0;
383 for(auto &pair : iInitList)
384 {
385 auto paramValue = convertDiscreteValueToNormalizedValue(stepCount, i);
386 fMap[pair.first] = std::make_tuple(pair.second, paramValue, i);
387 fList.emplace_back(pair.first);
388 i++;
389 }
390
391 // sanity check... if not the same size it means that 2 entries in the list were the same!
392 DCHECK_F(fList.size() == fMap.size());
393 }
394
395 // getStepCount
396 inline int32 getStepCount() const override { return static_cast<int32>(fMap.size() - 1); }
397
398 // normalize
399 inline ParamValue normalize(ParamType const &iValue) const override
400 {
401 auto iter = fMap.find(iValue);
402 if(iter != fMap.cend())
403 return std::get<1>(iter->second);
404 else
405 {
406 DLOG_F(WARNING, "could not normalize value...");
407 return 0;
408 }
409 }
410
411 // denormalize
412 inline ParamType denormalize(ParamValue iNormalizedValue) const override
413 {
414 auto index = convertNormalizedValueToDiscreteValue(getStepCount(), iNormalizedValue);
415 return fList[index];
416 }
417
418 // toString
419 void toString(ParamType const &iValue, String128 oString, int32 iPrecision) const override
420 {
421 auto iter = fMap.find(iValue);
422 if(iter != fMap.cend())
423 {
424 Steinberg::UString wrapper(oString, str16BufferSize (String128));
425 wrapper.assign(std::get<0>(iter->second).c_str());
426 }
427 else
428 oString[0] = 0;
429 }
430
431private:
434};
435
441template<typename Enum, Enum MaxValue>
443{
444public:
445 using ParamType = Enum;
446
447 using IntType = std::underlying_type_t<Enum>;
448
449 using IParamConverter<Enum>::toString;
450
453 using ConstructorType = std::array<VstString16, MaxValue + 1> const &;
454
455 // Constructor - you can provide an offset for the toString conversion (ex: counting from 1 instead of 0)
456 explicit EnumParamConverter(IntType iToStringOffset = 0) : fConverter{iToStringOffset} {}
457
458 // Constructor with printf style format where the parameter (%d) will be (value + offset)
459 explicit EnumParamConverter(VstString16 iFormat, IntType iToStringOffset = 0) : fConverter{std::move(iFormat), iToStringOffset} {}
460
461 // Constructor with all values defined
462 explicit EnumParamConverter(ConstructorType iToStringValues) : fConverter{iToStringValues} {}
463
464 // getStepCount
465 inline int32 getStepCount() const override { return MaxValue; }
466
467 // normalize
468 inline ParamValue normalize(ParamType const &iDiscreteValue) const override
469 {
470 return fConverter.normalize(static_cast<IntType>(iDiscreteValue));
471 }
472
473 // denormalize
474 inline ParamType denormalize(ParamValue iNormalizedValue) const override
475 {
476 return static_cast<Enum>(fConverter.denormalize(iNormalizedValue));
477 }
478
479 // toString
480 void toString(ParamType const &iValue, String128 oString, int32 iPrecision) const override
481 {
482 fConverter.toString(static_cast<IntType>(iValue), oString, iPrecision);
483 }
484
485private:
487};
488
489
490}
BooleanParamConverter(VstString16 iFalseString=STR16("Off"), VstString16 iTrueString=STR16("On"))
Definition ParamConverters.h:113
int32 getStepCount() const override
Definition ParamConverters.h:119
VstString16 fFalseString
Definition ParamConverters.h:146
bool denormalize(ParamValue iNormalizedValue) const override
Definition ParamConverters.h:126
ParamValue normalize(bool const &iValue) const override
Definition ParamConverters.h:121
VstString16 fTrueString
Definition ParamConverters.h:147
void toString(bool const &iValue, String128 oString, int32) const override
Definition ParamConverters.h:131
static bool toBoolean(ParamValue iNormalizedValue)
Converts a normalized value to a boolean according to the rule: false for [0.0, 0....
Definition ParamConverters.h:143
ParamType denormalize(ParamValue iNormalizedValue) const override
Definition ParamConverters.h:412
int32 getStepCount() const override
Definition ParamConverters.h:396
std::map< T, std::tuple< VstString16, ParamValue, int32 >, Compare > TMap
Maintains the map of possible values of T (defined in constructor).
Definition ParamConverters.h:358
std::initializer_list< std::pair< const T, VstString16 > > const & ConstructorType
Defines the type for the constructor argument.
Definition ParamConverters.h:366
std::vector< T > TList
Defines the mapping: discrete value [0, stepCount] to T.
Definition ParamConverters.h:362
ParamValue normalize(ParamType const &iValue) const override
Definition ParamConverters.h:399
DiscreteTypeParamConverter(ConstructorType iInitList)
This constructor will be called this way when initializing a vst or jmb parameter:
Definition ParamConverters.h:375
T ParamType
Definition ParamConverters.h:368
TMap fMap
Definition ParamConverters.h:432
void toString(ParamType const &iValue, String128 oString, int32 iPrecision) const override
Definition ParamConverters.h:419
TList fList
Definition ParamConverters.h:433
A converter to deal with a discrete value which has StepCount steps.
Definition ParamConverters.h:263
IntType fToStringOffset
Definition ParamConverters.h:321
ParamType denormalize(ParamValue iNormalizedValue) const override
Definition ParamConverters.h:291
int32 getStepCount() const override
Definition ParamConverters.h:284
std::vector< VstString16 > fToStringValues
Definition ParamConverters.h:323
IntType ParamType
Definition ParamConverters.h:265
ParamValue normalize(ParamType const &iDiscreteValue) const override
Definition ParamConverters.h:286
DiscreteValueParamConverter(VstString16 iFormat, IntType iToStringOffset=0)
Definition ParamConverters.h:277
DiscreteValueParamConverter(ConstructorType iToStringValues)
Definition ParamConverters.h:281
DiscreteValueParamConverter(IntType iToStringOffset=0)
Definition ParamConverters.h:274
std::array< VstString16, StepCount+1 > const & ConstructorType
Defines the type for the constructor argument.
Definition ParamConverters.h:271
void toString(ParamType const &iValue, String128 oString, int32) const override
Definition ParamConverters.h:297
VstString16 fFormat
Definition ParamConverters.h:322
std::underlying_type_t< Enum > IntType
Definition ParamConverters.h:447
ParamType denormalize(ParamValue iNormalizedValue) const override
Definition ParamConverters.h:474
int32 getStepCount() const override
Definition ParamConverters.h:465
Enum ParamType
Definition ParamConverters.h:445
std::array< VstString16, MaxValue+1 > const & ConstructorType
Defines the type for the constructor argument.
Definition ParamConverters.h:453
ParamValue normalize(ParamType const &iDiscreteValue) const override
Definition ParamConverters.h:468
EnumParamConverter(IntType iToStringOffset=0)
Definition ParamConverters.h:456
EnumParamConverter(VstString16 iFormat, IntType iToStringOffset=0)
Definition ParamConverters.h:459
DiscreteValueParamConverter< MaxValue, IntType > fConverter
Definition ParamConverters.h:486
EnumParamConverter(ConstructorType iToStringValues)
Definition ParamConverters.h:462
void toString(ParamType const &iValue, String128 oString, int32 iPrecision) const override
Definition ParamConverters.h:480
A vst parameter is represented by a ParamValue type which is a double in the range [0,...
Definition ParamConverters.h:55
virtual void toString(ParamType const &iValue, String128 iString, int32 iPrecision) const
Definition ParamConverters.h:61
virtual std::string toString(ParamType const &iValue, int32 iPrecision) const
Definition ParamConverters.h:62
virtual int32 getStepCount() const
Definition ParamConverters.h:58
virtual ParamValue normalize(ParamType const &iValue) const =0
virtual ParamType denormalize(ParamValue iNormalizedValue) const =0
T ParamType
Definition ParamConverters.h:57
A trivial percent converter.
Definition ParamConverters.h:160
double denormalize(ParamValue iNormalizedValue) const override
Definition ParamConverters.h:170
ParamValue normalize(double const &iValue) const override
Definition ParamConverters.h:165
void toString(ParamType const &iValue, String128 oString, int32 iPrecision) const override
Definition ParamConverters.h:175
This parameter is just a no-op wrapper to the ParamValue to adapt it to the use of the ParamConverter...
Definition ParamConverters.h:75
void toString(ParamValue const &iValue, String128 oString, int32 iPrecision) const override
Definition ParamConverters.h:90
ParamValue normalize(ParamValue const &iValue) const override
Definition ParamConverters.h:80
ParamValue denormalize(ParamValue iNormalizedValue) const override
Definition ParamConverters.h:85
static void staticToString(ParamValue const &iValue, String128 oString, int32 iPrecision)
Definition ParamConverters.h:95
static T clamp(const U &iValue, const T &iLower, const T &iUpper)
Make sure that the value remains within its bounds.
Definition Misc.h:34
constexpr auto ZERO_INT32
Definition Constants.h:25
std::string toUT8String(VstString16 const &iString)
Converts a VstString16 to a regular std::string that is properly utf-8 encoded.
Definition Utils.h:35
Definition Clock.h:24
static int32 computeNextDiscreteValue(int32 iValue, int32 iStepCount, int32 iIncrement, bool iWrap)
Implements a standard behavior for what it means to increment (resp.
Definition ParamConverters.h:218
static int32 convertNormalizedValueToDiscreteValue(int32 iStepCount, ParamValue iNormalizedValue)
Implements the algorithm described in the VST documentation on how to interpret a normalized value as...
Definition ParamConverters.h:200
double Percent
Percent type represented by a double.
Definition ParamConverters.h:153
static ParamValue convertDiscreteValueToNormalizedValue(int32 iStepCount, int32 iDiscreteValue)
Implements the algorithm described in the VST documentation on how to interpret a discrete value into...
Definition ParamConverters.h:187
std::basic_string< Steinberg::char16 > VstString16
Strings made of char16 characters are represented by the native C++11 type std::basic_string<Steinber...
Definition Types.h:44