Jamba C++ API 8.0.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
23#include <pongasoft/VST/Types.h>
25
26#include <pluginterfaces/vst/vsttypes.h>
27#include <pluginterfaces/base/ustring.h>
28#include <base/source/fstring.h>
29#include <pluginterfaces/base/ftypes.h>
30
31#include <algorithm>
32#include <concepts>
33#include <string>
34#include <array>
35#include <vector>
36#include <map>
37#include <type_traits>
39
40namespace pongasoft::VST {
41
42using namespace Steinberg;
43using namespace Steinberg::Vst;
44
52template<typename T>
54{
55public:
56 virtual ~IParamConverter() = default;
57
58 using ParamType = T;
59 virtual int32 getStepCount() const { return 0; }
60 virtual ParamValue normalize(ParamType const &iValue) const = 0;
61 virtual ParamType denormalize(ParamValue iNormalizedValue) const = 0;
62 virtual void toString(ParamType const &iValue, String128 iString, int32 iPrecision) const { }
63 virtual std::string toString(ParamType const &iValue, int32 iPrecision) const
64 {
65 String128 s;
66 s[0] = 0;
67 toString(iValue, s, iPrecision);
68 return VstUtils::toUT8String(s);
69 }
70};
71
72template<typename T, typename ParamType>
73concept IsDerivedFromIParamConverter = std::derived_from<T, IParamConverter<ParamType>>;
74
76template<typename T>
77concept IsIParamConverter = requires
78 { typename T::ParamType; } &&
80
84class RawParamConverter : public IParamConverter<ParamValue>
85{
86public:
87
89
90 ParamValue normalize(ParamValue const &iValue) const override
91 {
92 return Utils::clamp(iValue, 0.0, 1.0);
93 }
94
95 ParamValue denormalize(ParamValue iNormalizedValue) const override
96 {
97 return Utils::clamp(iNormalizedValue, 0.0, 1.0);
98 }
99
100 void toString(ParamValue const &iValue, String128 oString, int32 iPrecision) const override
101 {
102 staticToString(iValue, oString, iPrecision);
103 }
104
105 static void staticToString(ParamValue const &iValue, String128 oString, int32 iPrecision)
106 {
107 Steinberg::UString wrapper(oString, str16BufferSize(String128));
108 if(!wrapper.printFloat(iValue, iPrecision))
109 oString[0] = 0;
110 }
111};
112
119{
120public:
122
123 explicit BooleanParamConverter(VstString16 iFalseString = STR16("Off"),
124 VstString16 iTrueString = STR16("On")) :
125 fFalseString{std::move(iFalseString)},
126 fTrueString{std::move(iTrueString)}
127 {}
128
129 int32 getStepCount() const override { return 1; }
130
131 ParamValue normalize(bool const &iValue) const override
132 {
133 return iValue ? 1.0 : 0;
134 }
135
136 bool denormalize(ParamValue iNormalizedValue) const override
137 {
138 return toBoolean(iNormalizedValue);
139 }
140
141 void toString(bool const &iValue, String128 oString, int32 /* iPrecision */) const override
142 {
143 Steinberg::UString wrapper(oString, str16BufferSize(String128));
144 if(iValue)
145 wrapper.assign(fTrueString.c_str());
146 else
147 wrapper.assign(fFalseString.c_str());
148 }
149
153 static constexpr bool toBoolean(ParamValue iNormalizedValue) { return iNormalizedValue >= 0.5; }
154
155protected:
158};
159
163using Percent = double;
164
170{
171public:
172
174
175 ParamValue normalize(Percent const &iValue) const override
176 {
177 return Utils::clamp(iValue, 0.0, 1.0);
178 }
179
180 Percent denormalize(ParamValue iNormalizedValue) const override
181 {
182 return Utils::clamp(iNormalizedValue, 0.0, 1.0);
183 }
184
185 void toString(ParamType const &iValue, String128 oString, int32 iPrecision) const override
186 {
187 Steinberg::UString wrapper(oString, str16BufferSize (String128));
188 wrapper.printFloat(iValue * 100, iPrecision);
189 wrapper.append(STR16("%"));
190 }
191};
192
197static constexpr ParamValue convertDiscreteValueToNormalizedValue(int32 iStepCount, int32 iDiscreteValue)
198{
199 auto value = Utils::clamp<int32, int32>(iDiscreteValue, 0, iStepCount);
200 if(value == 0)
201 return value;
202 else
203 return value / static_cast<ParamValue>(iStepCount);
204}
205
210static constexpr int32 convertNormalizedValueToDiscreteValue(int32 iStepCount, ParamValue iNormalizedValue)
211{
212 // ParamValue must remain within its bounds
213 auto value = Utils::clamp(iNormalizedValue, 0.0, 1.0);
214 auto discreteValue = std::min(static_cast<ParamValue>(iStepCount), value * (iStepCount + 1));
215 // Implementation note: this takes care of std::floor and is 100% equivalent since we know everything is >= 0
216 return static_cast<int32>(discreteValue);
217}
218
229static constexpr int32 computeNextDiscreteValue(int32 iValue, int32 iStepCount, int32 iIncrement, bool iWrap)
230{
231 // no increment, noop
232 if(iIncrement == 0)
233 return iValue;
234
235 if(iStepCount > 0)
236 {
237 auto discreteValue = iValue + iIncrement;
238
239 // handles wrapping
240 if(iWrap)
241 {
242 if(iIncrement > 0)
243 {
244 while(discreteValue > iStepCount)
245 discreteValue -= iStepCount + 1;
246 }
247 else
248 {
249 while(discreteValue < 0)
250 discreteValue += iStepCount + 1;
251 }
252 }
253 else
254 {
255 // no wrapping => simply clamp the value to the range
256 discreteValue = Utils::clamp(discreteValue, Utils::ZERO_INT32, iStepCount);
257 }
258
259 return discreteValue;
260 }
261 else
262 {
263 return iValue;
264 }
265}
266
272template<int32 StepCount, Utils::IntegralOrEnum IntType = int32>
274{
275public:
276 using ParamType = IntType;
277
278 using IParamConverter<IntType>::toString;
279
282 using ConstructorType = std::array<VstString16, StepCount + 1> const &;
283
284 // Constructor - you can provide an offset for the toString conversion (ex: counting from 1 instead of 0)
285 explicit DiscreteValueParamConverter(IntType iToStringOffset = 0) : fToStringOffset{iToStringOffset} {}
286
287 // Constructor with printf style format where the parameter (%d) will be (value + offset)
288 explicit DiscreteValueParamConverter(VstString16 iFormat, IntType iToStringOffset = 0) :
289 fToStringOffset{iToStringOffset}, fFormat{std::move(iFormat)} {}
290
291 // Constructor with all values defined
293 fToStringValues(iToStringValues.cbegin(), iToStringValues.cend()) {}
294
295 int32 getStepCount() const override { return StepCount; }
296
297 ParamValue normalize(ParamType const &iDiscreteValue) const override
298 {
299 return convertDiscreteValueToNormalizedValue(StepCount, static_cast<int32>(iDiscreteValue));
300 }
301
302 ParamType denormalize(ParamValue iNormalizedValue) const override
303 {
304 return static_cast<ParamType>(convertNormalizedValueToDiscreteValue(StepCount, iNormalizedValue));
305 }
306
307 // toString
308 void toString(ParamType const &iValue, String128 oString, int32 /* iPrecision */) const override
309 {
310 Steinberg::UString wrapper(oString, str16BufferSize (String128));
311 if(!fFormat.empty())
312 {
313 Steinberg::String s;
314 s.printf(fFormat.c_str(), iValue + fToStringOffset);
315 wrapper.assign(s.text());
316 }
317 else
318 {
319 if(fToStringValues.empty())
320 {
321 if(!wrapper.printInt(iValue + fToStringOffset))
322 oString[0] = 0;
323 }
324 else
325 {
326 wrapper.assign(fToStringValues[iValue].c_str());
327 }
328 }
329 }
330
331private:
334 std::vector<VstString16> fToStringValues{};
335};
336
363template<typename T, class Compare = std::less<T>>
365{
366public:
369 using TMap = std::map<T, std::tuple<VstString16, ParamValue, int32>, Compare>;
370
373 using TList = std::vector<T>;
374
377 using ConstructorType = std::initializer_list<std::pair<const T, VstString16>> const &;
378
379 using ParamType = T;
380
382
387 {
388 auto stepCount = static_cast<int32>(iInitList.size() - 1);
389
390 // by definition, a discrete parameter has a step count > 0
391 DCHECK_F(stepCount > 0);
392
393 int32 i = 0;
394 for(auto &pair : iInitList)
395 {
396 auto paramValue = convertDiscreteValueToNormalizedValue(stepCount, i);
397 fMap[pair.first] = std::make_tuple(pair.second, paramValue, i);
398 fList.emplace_back(pair.first);
399 i++;
400 }
401
402 // sanity check... if not the same size it means that 2 entries in the list were the same!
403 DCHECK_F(fList.size() == fMap.size());
404 }
405
406 // getStepCount
407 int32 getStepCount() const override { return static_cast<int32>(fMap.size() - 1); }
408
409 // normalize
410 ParamValue normalize(ParamType const &iValue) const override
411 {
412 auto iter = fMap.find(iValue);
413 if(iter != fMap.cend())
414 return std::get<1>(iter->second);
415 else
416 {
417 DLOG_F(WARNING, "could not normalize value...");
418 return 0;
419 }
420 }
421
422 // denormalize
423 ParamType denormalize(ParamValue iNormalizedValue) const override
424 {
425 auto index = convertNormalizedValueToDiscreteValue(getStepCount(), iNormalizedValue);
426 return fList[index];
427 }
428
429 // toString
430 void toString(ParamType const &iValue, String128 oString, int32 iPrecision) const override
431 {
432 auto iter = fMap.find(iValue);
433 if(iter != fMap.cend())
434 {
435 Steinberg::UString wrapper(oString, str16BufferSize (String128));
436 wrapper.assign(std::get<0>(iter->second).c_str());
437 }
438 else
439 oString[0] = 0;
440 }
441
442private:
445};
446
452template<typename Enum, Enum MaxValue> requires std::is_enum_v<Enum>
454{
455public:
456 using ParamType = Enum;
457
458 using IntType = std::underlying_type_t<Enum>;
459
460 using IParamConverter<Enum>::toString;
461
464 using ConstructorType = std::array<VstString16, MaxValue + 1> const &;
465
466 // Constructor - you can provide an offset for the toString conversion (ex: counting from 1 instead of 0)
467 explicit EnumParamConverter(IntType iToStringOffset = 0) : fConverter{iToStringOffset} {}
468
469 // Constructor with printf style format where the parameter (%d) will be (value + offset)
470 explicit EnumParamConverter(VstString16 iFormat, IntType iToStringOffset = 0) : fConverter{std::move(iFormat), iToStringOffset} {}
471
472 // Constructor with all values defined
473 explicit EnumParamConverter(ConstructorType iToStringValues) : fConverter{iToStringValues} {}
474
475 // getStepCount
476 int32 getStepCount() const override { return MaxValue; }
477
478 // normalize
479 ParamValue normalize(ParamType const &iDiscreteValue) const override
480 {
481 return fConverter.normalize(static_cast<IntType>(iDiscreteValue));
482 }
483
484 // denormalize
485 ParamType denormalize(ParamValue iNormalizedValue) const override
486 {
487 return static_cast<Enum>(fConverter.denormalize(iNormalizedValue));
488 }
489
490 // toString
491 void toString(ParamType const &iValue, String128 oString, int32 iPrecision) const override
492 {
493 fConverter.toString(static_cast<IntType>(iValue), oString, iPrecision);
494 }
495
496private:
498};
499
500
501}
BooleanParamConverter(VstString16 iFalseString=STR16("Off"), VstString16 iTrueString=STR16("On"))
Definition ParamConverters.h:123
int32 getStepCount() const override
Definition ParamConverters.h:129
VstString16 fFalseString
Definition ParamConverters.h:156
bool denormalize(ParamValue iNormalizedValue) const override
Definition ParamConverters.h:136
static constexpr bool toBoolean(ParamValue iNormalizedValue)
Converts a normalized value to a boolean according to the rule: false for [0.0, 0....
Definition ParamConverters.h:153
ParamValue normalize(bool const &iValue) const override
Definition ParamConverters.h:131
VstString16 fTrueString
Definition ParamConverters.h:157
void toString(bool const &iValue, String128 oString, int32) const override
Definition ParamConverters.h:141
ParamType denormalize(ParamValue iNormalizedValue) const override
Definition ParamConverters.h:423
int32 getStepCount() const override
Definition ParamConverters.h:407
std::map< T, std::tuple< VstString16, ParamValue, int32 >, Compare > TMap
Maintains the map of possible values of T (defined in constructor).
Definition ParamConverters.h:369
std::initializer_list< std::pair< const T, VstString16 > > const & ConstructorType
Defines the type for the constructor argument.
Definition ParamConverters.h:377
std::vector< T > TList
Defines the mapping: discrete value [0, stepCount] to T.
Definition ParamConverters.h:373
ParamValue normalize(ParamType const &iValue) const override
Definition ParamConverters.h:410
DiscreteTypeParamConverter(ConstructorType iInitList)
This constructor will be called this way when initializing a vst or jmb parameter:
Definition ParamConverters.h:386
T ParamType
Definition ParamConverters.h:379
TMap fMap
Definition ParamConverters.h:443
void toString(ParamType const &iValue, String128 oString, int32 iPrecision) const override
Definition ParamConverters.h:430
TList fList
Definition ParamConverters.h:444
A converter to deal with a discrete value which has StepCount steps.
Definition ParamConverters.h:274
IntType fToStringOffset
Definition ParamConverters.h:332
ParamType denormalize(ParamValue iNormalizedValue) const override
Definition ParamConverters.h:302
int32 getStepCount() const override
Definition ParamConverters.h:295
std::vector< VstString16 > fToStringValues
Definition ParamConverters.h:334
IntType ParamType
Definition ParamConverters.h:276
ParamValue normalize(ParamType const &iDiscreteValue) const override
Definition ParamConverters.h:297
DiscreteValueParamConverter(VstString16 iFormat, IntType iToStringOffset=0)
Definition ParamConverters.h:288
DiscreteValueParamConverter(ConstructorType iToStringValues)
Definition ParamConverters.h:292
DiscreteValueParamConverter(IntType iToStringOffset=0)
Definition ParamConverters.h:285
std::array< VstString16, StepCount+1 > const & ConstructorType
Defines the type for the constructor argument.
Definition ParamConverters.h:282
void toString(ParamType const &iValue, String128 oString, int32) const override
Definition ParamConverters.h:308
VstString16 fFormat
Definition ParamConverters.h:333
std::underlying_type_t< Enum > IntType
Definition ParamConverters.h:458
ParamType denormalize(ParamValue iNormalizedValue) const override
Definition ParamConverters.h:485
int32 getStepCount() const override
Definition ParamConverters.h:476
Enum ParamType
Definition ParamConverters.h:456
std::array< VstString16, MaxValue+1 > const & ConstructorType
Defines the type for the constructor argument.
Definition ParamConverters.h:464
ParamValue normalize(ParamType const &iDiscreteValue) const override
Definition ParamConverters.h:479
EnumParamConverter(IntType iToStringOffset=0)
Definition ParamConverters.h:467
EnumParamConverter(VstString16 iFormat, IntType iToStringOffset=0)
Definition ParamConverters.h:470
DiscreteValueParamConverter< MaxValue, IntType > fConverter
Definition ParamConverters.h:497
EnumParamConverter(ConstructorType iToStringValues)
Definition ParamConverters.h:473
void toString(ParamType const &iValue, String128 oString, int32 iPrecision) const override
Definition ParamConverters.h:491
A vst parameter is represented by a ParamValue type which is a double in the range [0,...
Definition ParamConverters.h:54
virtual void toString(ParamType const &iValue, String128 iString, int32 iPrecision) const
Definition ParamConverters.h:62
virtual std::string toString(ParamType const &iValue, int32 iPrecision) const
Definition ParamConverters.h:63
virtual int32 getStepCount() const
Definition ParamConverters.h:59
virtual ParamValue normalize(ParamType const &iValue) const =0
virtual ParamType denormalize(ParamValue iNormalizedValue) const =0
virtual ~IParamConverter()=default
T ParamType
Definition ParamConverters.h:58
A trivial percent converter.
Definition ParamConverters.h:170
ParamValue normalize(Percent const &iValue) const override
Definition ParamConverters.h:175
Percent denormalize(ParamValue iNormalizedValue) const override
Definition ParamConverters.h:180
void toString(ParamType const &iValue, String128 oString, int32 iPrecision) const override
Definition ParamConverters.h:185
This parameter is just a no-op wrapper to the ParamValue to adapt it to the use of the ParamConverter...
Definition ParamConverters.h:85
void toString(ParamValue const &iValue, String128 oString, int32 iPrecision) const override
Definition ParamConverters.h:100
ParamValue normalize(ParamValue const &iValue) const override
Definition ParamConverters.h:90
ParamValue denormalize(ParamValue iNormalizedValue) const override
Definition ParamConverters.h:95
static void staticToString(ParamValue const &iValue, String128 oString, int32 iPrecision)
Definition ParamConverters.h:105
Definition ParamConverters.h:73
Defines the concept that matches IParamConverter.
Definition ParamConverters.h:77
static constexpr 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 constexpr 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:197
static constexpr 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:210
double Percent
Percent type represented by a double.
Definition ParamConverters.h:163
static constexpr int32 computeNextDiscreteValue(int32 iValue, int32 iStepCount, int32 iIncrement, bool iWrap)
Implements a standard behavior for what it means to increment (resp.
Definition ParamConverters.h:229
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