Jamba C++ API  4.0.0
ParamConverters.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2018-2019 pongasoft
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5  * use this file except in compliance with the License. You may obtain a copy of
6  * the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13  * License for the specific language governing permissions and limitations under
14  * the License.
15  *
16  * @author Yan Pujante
17  */
18 #pragma once
19 
20 #include <pongasoft/Utils/Misc.h>
21 #include <pongasoft/VST/Types.h>
23 
24 #include <pluginterfaces/vst/vsttypes.h>
25 #include <pluginterfaces/vst/ivstparameterchanges.h>
26 #include <pluginterfaces/base/ustring.h>
27 #include <base/source/fstring.h>
28 #include <pluginterfaces/base/ftypes.h>
29 
30 #include <cmath>
31 #include <algorithm>
32 #include <memory>
33 #include <string>
34 #include <array>
35 #include <vector>
36 #include <map>
37 #include <type_traits>
39 
40 namespace pongasoft::VST {
41 
42 using namespace Steinberg;
43 using namespace Steinberg::Vst;
44 
52 template<typename T>
54 {
55 public:
56  using ParamType = T;
57  virtual int32 getStepCount() const { return 0; }
58  virtual ParamValue normalize(ParamType const &iValue) const = 0;
59  virtual ParamType denormalize(ParamValue iNormalizedValue) const = 0;
60  virtual void toString(ParamType const &iValue, String128 iString, int32 iPrecision) const { }
61  virtual std::string toString(ParamType const &iValue, int32 iPrecision) const
62  {
63  String128 s;
64  s[0] = 0;
65  toString(iValue, s, iPrecision);
66  return VstUtils::toUT8String(s);
67  }
68 };
69 
73 class RawParamConverter : public IParamConverter<ParamValue>
74 {
75 public:
76 
78 
79  inline ParamValue normalize(ParamValue const &iValue) const override
80  {
81  return Utils::clamp(iValue, 0.0, 1.0);
82  }
83 
84  inline ParamValue denormalize(ParamValue iNormalizedValue) const override
85  {
86  return Utils::clamp(iNormalizedValue, 0.0, 1.0);
87  }
88 
89  inline void toString(ParamValue const &iValue, String128 oString, int32 iPrecision) const override
90  {
91  staticToString(iValue, oString, iPrecision);
92  }
93 
94  static inline void staticToString(ParamValue const &iValue, String128 oString, int32 iPrecision)
95  {
96  Steinberg::UString wrapper(oString, str16BufferSize(String128));
97  if(!wrapper.printFloat(iValue, iPrecision))
98  oString[0] = 0;
99  }
100 };
101 
108 {
109 public:
111 
112  explicit BooleanParamConverter(VstString16 iFalseString = STR16("Off"),
113  VstString16 iTrueString = STR16("On")) :
114  fFalseString{std::move(iFalseString)},
115  fTrueString{std::move(iTrueString)}
116  {}
117 
118  inline int32 getStepCount() const override { return 1; }
119 
120  inline ParamValue normalize(bool const &iValue) const override
121  {
122  return iValue ? 1.0 : 0;
123  }
124 
125  inline bool denormalize(ParamValue iNormalizedValue) const override
126  {
127  return toBoolean(iNormalizedValue);
128  }
129 
130  inline void toString(bool const &iValue, String128 oString, int32 /* iPrecision */) const override
131  {
132  Steinberg::UString wrapper(oString, str16BufferSize(String128));
133  if(iValue)
134  wrapper.assign(fTrueString.c_str());
135  else
136  wrapper.assign(fFalseString.c_str());
137  }
138 
142  inline static bool toBoolean(ParamValue iNormalizedValue) { return iNormalizedValue >= 0.5; }
143 
144 protected:
147 };
148 
152 using Percent = double;
153 
158 class PercentParamConverter : public IParamConverter<Percent>
159 {
160 public:
161 
163 
164  inline ParamValue normalize(double const &iValue) const override
165  {
166  return Utils::clamp(iValue, 0.0, 1.0);
167  }
168 
169  inline double denormalize(ParamValue iNormalizedValue) const override
170  {
171  return Utils::clamp(iNormalizedValue, 0.0, 1.0);
172  }
173 
174  inline void toString(ParamType const &iValue, String128 oString, int32 iPrecision) const override
175  {
176  Steinberg::UString wrapper(oString, str16BufferSize (String128));
177  wrapper.printFloat(iValue * 100, iPrecision);
178  wrapper.append(STR16("%"));
179  }
180 };
181 
186 static inline ParamValue convertDiscreteValueToNormalizedValue(int32 iStepCount, int32 iDiscreteValue)
187 {
188  auto value = Utils::clamp<int32, int32>(iDiscreteValue, 0, iStepCount);
189  if(value == 0)
190  return value;
191  else
192  return value / static_cast<ParamValue>(iStepCount);
193 }
194 
199 static inline int32 convertNormalizedValueToDiscreteValue(int32 iStepCount, ParamValue iNormalizedValue)
200 {
201  // ParamValue must remain within its bounds
202  auto value = Utils::clamp(iNormalizedValue, 0.0, 1.0);
203  auto discreteValue = std::floor(std::min(static_cast<ParamValue>(iStepCount), value * (iStepCount + 1)));
204  return static_cast<int32>(discreteValue);
205 }
206 
212 template<int32 StepCount, typename IntType = int32>
214 {
215 public:
216  using ParamType = IntType;
217 
219 
220  // Constructor - you can provide an offset for the toString conversion (ex: counting from 1 instead of 0)
221  explicit DiscreteValueParamConverter(IntType iToStringOffset = 0) : fToStringOffset{iToStringOffset} {}
222 
223  // Constructor with printf style format where the parameter (%d) will be (value + offset)
224  explicit DiscreteValueParamConverter(VstString16 iFormat, IntType iToStringOffset = 0) :
225  fToStringOffset{iToStringOffset}, fFormat{std::move(iFormat)} {}
226 
227  // Constructor with all values defined
228  explicit DiscreteValueParamConverter(std::array<VstString16, StepCount + 1> const &iToStringValues) :
229  fToStringValues(iToStringValues.cbegin(), iToStringValues.cend()) {}
230 
231  inline int32 getStepCount() const override { return StepCount; }
232 
233  inline ParamValue normalize(ParamType const &iDiscreteValue) const override
234  {
235  return convertDiscreteValueToNormalizedValue(StepCount, static_cast<int32>(iDiscreteValue));
236  }
237 
238  inline ParamType denormalize(ParamValue iNormalizedValue) const override
239  {
240  return static_cast<ParamType>(convertNormalizedValueToDiscreteValue(StepCount, iNormalizedValue));
241  }
242 
243  // toString
244  void toString(ParamType const &iValue, String128 oString, int32 /* iPrecision */) const override
245  {
246  Steinberg::UString wrapper(oString, str16BufferSize (String128));
247  if(!fFormat.empty())
248  {
249  String s;
250  s.printf(fFormat.c_str(), iValue + fToStringOffset);
251  wrapper.assign(s.text());
252  }
253  else
254  {
255  if(fToStringValues.empty())
256  {
257  if(!wrapper.printInt(iValue + fToStringOffset))
258  oString[0] = 0;
259  }
260  else
261  {
262  wrapper.assign(fToStringValues[iValue].c_str());
263  }
264  }
265  }
266 
267 private:
268  IntType fToStringOffset{};
269  VstString16 fFormat{};
270  std::vector<VstString16> fToStringValues{};
271 };
272 
299 template<typename T, class Compare = std::less<T>>
301 {
302 public:
305  using TMap = std::map<T, std::tuple<VstString16, ParamValue, int32>, Compare>;
306 
309  using TList = std::vector<T>;
310 
313  using ConstructorType = std::initializer_list<std::pair<const T, VstString16>> const &;
314 
315  using ParamType = T;
316 
318 
323  {
324  auto stepCount = static_cast<int32>(iInitList.size() - 1);
325 
326  // by definition, a discrete parameter has a step count > 0
327  DCHECK_F(stepCount > 0);
328 
329  int32 i = 0;
330  for(auto &pair : iInitList)
331  {
332  auto paramValue = convertDiscreteValueToNormalizedValue(stepCount, i);
333  fMap[pair.first] = std::make_tuple(pair.second, paramValue, i);
334  fList.emplace_back(pair.first);
335  i++;
336  }
337 
338  // sanity check... if not the same size it means that 2 entries in the list were the same!
339  DCHECK_F(fList.size() == fMap.size());
340  }
341 
342  // getStepCount
343  inline int32 getStepCount() const override { return static_cast<int32>(fMap.size() - 1); }
344 
345  // normalize
346  inline ParamValue normalize(ParamType const &iValue) const override
347  {
348  auto iter = fMap.find(iValue);
349  if(iter != fMap.cend())
350  return std::get<1>(iter->second);
351  else
352  {
353  DLOG_F(WARNING, "could not normalize value...");
354  return 0;
355  }
356  }
357 
358  // denormalize
359  inline ParamType denormalize(ParamValue iNormalizedValue) const override
360  {
361  auto index = convertNormalizedValueToDiscreteValue(getStepCount(), iNormalizedValue);
362  return fList[index];
363  }
364 
365  // toString
366  void toString(ParamType const &iValue, String128 oString, int32 iPrecision) const override
367  {
368  auto iter = fMap.find(iValue);
369  if(iter != fMap.cend())
370  {
371  Steinberg::UString wrapper(oString, str16BufferSize (String128));
372  wrapper.assign(std::get<0>(iter->second).c_str());
373  }
374  else
375  oString[0] = 0;
376  }
377 
378 private:
379  TMap fMap{};
380  TList fList{};
381 };
382 
388 template<typename Enum, Enum MaxValue>
390 {
391 public:
392  using ParamType = Enum;
393 
394  using IntType = std::underlying_type_t<Enum>;
395 
397 
400  using ConstructorType = std::array<VstString16, MaxValue + 1> const &;
401 
402  // Constructor - you can provide an offset for the toString conversion (ex: counting from 1 instead of 0)
403  explicit EnumParamConverter(IntType iToStringOffset = 0) : fConverter{iToStringOffset} {}
404 
405  // Constructor with printf style format where the parameter (%d) will be (value + offset)
406  explicit EnumParamConverter(VstString16 iFormat, IntType iToStringOffset = 0) : fConverter{std::move(iFormat), iToStringOffset} {}
407 
408  // Constructor with all values defined
409  explicit EnumParamConverter(ConstructorType iToStringValues) : fConverter{iToStringValues} {}
410 
411  // getStepCount
412  inline int32 getStepCount() const override { return MaxValue; }
413 
414  // normalize
415  inline ParamValue normalize(ParamType const &iDiscreteValue) const override
416  {
417  return fConverter.normalize(static_cast<IntType>(iDiscreteValue));
418  }
419 
420  // denormalize
421  inline ParamType denormalize(ParamValue iNormalizedValue) const override
422  {
423  return static_cast<Enum>(fConverter.denormalize(iNormalizedValue));
424  }
425 
426  // toString
427  void toString(ParamType const &iValue, String128 oString, int32 iPrecision) const override
428  {
429  fConverter.toString(static_cast<IntType>(iValue), oString, iPrecision);
430  }
431 
432 private:
434 };
435 
436 
437 }
int32 getStepCount() const override
Definition: ParamConverters.h:231
static T clamp(const U &iValue, const T &iLower, const T &iUpper)
Make sure that the value remains within its bounds.
Definition: Misc.h:33
void toString(ParamType const &iValue, String128 oString, int32 iPrecision) const override
Definition: ParamConverters.h:366
virtual void toString(ParamType const &iValue, String128 iString, int32 iPrecision) const
Definition: ParamConverters.h:60
std::initializer_list< std::pair< const T, VstString16 > > const & ConstructorType
Defines the type for the constructor argument.
Definition: ParamConverters.h:313
double denormalize(ParamValue iNormalizedValue) const override
Definition: ParamConverters.h:169
std::vector< T > TList
Defines the mapping: discrete value [0, stepCount] to T.
Definition: ParamConverters.h:309
int32 getStepCount() const override
Definition: ParamConverters.h:118
Enum ParamType
Definition: ParamConverters.h:56
DiscreteValueParamConverter(std::array< VstString16, StepCount+1 > const &iToStringValues)
Definition: ParamConverters.h:228
void toString(ParamType const &iValue, String128 oString, int32 iPrecision) const override
Definition: ParamConverters.h:427
std::underlying_type_t< Enum > IntType
Definition: ParamConverters.h:394
DiscreteValueParamConverter(VstString16 iFormat, IntType iToStringOffset=0)
Definition: ParamConverters.h:224
EnumParamConverter(ConstructorType iToStringValues)
Definition: ParamConverters.h:409
std::array< VstString16, MaxValue+1 > const & ConstructorType
Defines the type for the constructor argument.
Definition: ParamConverters.h:400
DiscreteValueParamConverter(IntType iToStringOffset=0)
Definition: ParamConverters.h:221
DiscreteTypeParamConverter(ConstructorType iInitList)
This constructor will be called this way when initializing a vst or jmb parameter:
Definition: ParamConverters.h:322
void toString(bool const &iValue, String128 oString, int32) const override
Definition: ParamConverters.h:130
This converters maps a list of values of type T to discrete values.
Definition: ParamConverters.h:300
This parameter is just a no-op wrapper to the ParamValue to adapt it to the use of the ParamConverter...
Definition: ParamConverters.h:73
ParamValue normalize(ParamValue const &iValue) const override
Definition: ParamConverters.h:79
ParamValue normalize(double const &iValue) const override
Definition: ParamConverters.h:164
int32 getStepCount() const override
Definition: ParamConverters.h:343
A trivial percent converter.
Definition: ParamConverters.h:158
static void staticToString(ParamValue const &iValue, String128 oString, int32 iPrecision)
Definition: ParamConverters.h:94
ParamValue normalize(ParamType const &iDiscreteValue) const override
Definition: ParamConverters.h:415
EnumParamConverter(VstString16 iFormat, IntType iToStringOffset=0)
Definition: ParamConverters.h:406
ParamType denormalize(ParamValue iNormalizedValue) const override
Definition: ParamConverters.h:359
double Percent
Percent type represented by a double.
Definition: ParamConverters.h:152
void toString(ParamValue const &iValue, String128 oString, int32 iPrecision) const override
Definition: ParamConverters.h:89
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:43
ParamValue normalize(bool const &iValue) const override
Definition: ParamConverters.h:120
ParamValue normalize(ParamType const &iValue) const override
Definition: ParamConverters.h:346
static bool toBoolean(ParamValue iNormalizedValue)
Converts a normalized value to a boolean according to the rule: false for [0.0, 0....
Definition: ParamConverters.h:142
int32 getStepCount() const override
Definition: ParamConverters.h:412
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:186
VstString16 fTrueString
Definition: ParamConverters.h:146
bool denormalize(ParamValue iNormalizedValue) const override
Definition: ParamConverters.h:125
void toString(ParamType const &iValue, String128 oString, int32 iPrecision) const override
Definition: ParamConverters.h:174
Manages the very common case when a param represents a boolean value.
Definition: ParamConverters.h:107
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:199
ParamType denormalize(ParamValue iNormalizedValue) const override
Definition: ParamConverters.h:421
A converter to deal with a discrete value which has StepCount steps.
Definition: ParamConverters.h:213
ParamValue denormalize(ParamValue iNormalizedValue) const override
Definition: ParamConverters.h:84
virtual int32 getStepCount() const
Definition: ParamConverters.h:57
Enum ParamType
Definition: ParamConverters.h:392
VstString16 fFalseString
Definition: ParamConverters.h:145
EnumParamConverter(IntType iToStringOffset=0)
Definition: ParamConverters.h:403
ParamType denormalize(ParamValue iNormalizedValue) const override
Definition: ParamConverters.h:238
DiscreteValueParamConverter< MaxValue, IntType > fConverter
Definition: ParamConverters.h:433
std::map< T, std::tuple< VstString16, ParamValue, int32 >, Compare > TMap
Maintains the map of possible values of T (defined in constructor)
Definition: ParamConverters.h:305
Definition: Clock.h:23
virtual std::string toString(ParamType const &iValue, int32 iPrecision) const
Definition: ParamConverters.h:61
BooleanParamConverter(VstString16 iFalseString=STR16("Off"), VstString16 iTrueString=STR16("On"))
Definition: ParamConverters.h:112
A converter to deal with an enum (assumes that the enum is contiguous, starts at 0 and that MaxValue ...
Definition: ParamConverters.h:389
std::string toUT8String(VstString16 const &iString)
Converts a VstString16 to a regular std::string that is properly utf-8 encoded.
Definition: Utils.h:34
void toString(ParamType const &iValue, String128 oString, int32) const override
Definition: ParamConverters.h:244
ParamValue normalize(ParamType const &iDiscreteValue) const override
Definition: ParamConverters.h:233
A vst parameter is represented by a ParamValue type which is a double in the range [0,...
Definition: ParamConverters.h:53