Jamba C++ API  4.1.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 
222  using ConstructorType = std::array<VstString16, StepCount + 1> const &;
223 
224  // Constructor - you can provide an offset for the toString conversion (ex: counting from 1 instead of 0)
225  explicit DiscreteValueParamConverter(IntType iToStringOffset = 0) : fToStringOffset{iToStringOffset} {}
226 
227  // Constructor with printf style format where the parameter (%d) will be (value + offset)
228  explicit DiscreteValueParamConverter(VstString16 iFormat, IntType iToStringOffset = 0) :
229  fToStringOffset{iToStringOffset}, fFormat{std::move(iFormat)} {}
230 
231  // Constructor with all values defined
232  explicit DiscreteValueParamConverter(ConstructorType iToStringValues) :
233  fToStringValues(iToStringValues.cbegin(), iToStringValues.cend()) {}
234 
235  inline int32 getStepCount() const override { return StepCount; }
236 
237  inline ParamValue normalize(ParamType const &iDiscreteValue) const override
238  {
239  return convertDiscreteValueToNormalizedValue(StepCount, static_cast<int32>(iDiscreteValue));
240  }
241 
242  inline ParamType denormalize(ParamValue iNormalizedValue) const override
243  {
244  return static_cast<ParamType>(convertNormalizedValueToDiscreteValue(StepCount, iNormalizedValue));
245  }
246 
247  // toString
248  void toString(ParamType const &iValue, String128 oString, int32 /* iPrecision */) const override
249  {
250  Steinberg::UString wrapper(oString, str16BufferSize (String128));
251  if(!fFormat.empty())
252  {
253  String s;
254  s.printf(fFormat.c_str(), iValue + fToStringOffset);
255  wrapper.assign(s.text());
256  }
257  else
258  {
259  if(fToStringValues.empty())
260  {
261  if(!wrapper.printInt(iValue + fToStringOffset))
262  oString[0] = 0;
263  }
264  else
265  {
266  wrapper.assign(fToStringValues[iValue].c_str());
267  }
268  }
269  }
270 
271 private:
272  IntType fToStringOffset{};
273  VstString16 fFormat{};
274  std::vector<VstString16> fToStringValues{};
275 };
276 
303 template<typename T, class Compare = std::less<T>>
305 {
306 public:
309  using TMap = std::map<T, std::tuple<VstString16, ParamValue, int32>, Compare>;
310 
313  using TList = std::vector<T>;
314 
317  using ConstructorType = std::initializer_list<std::pair<const T, VstString16>> const &;
318 
319  using ParamType = T;
320 
322 
327  {
328  auto stepCount = static_cast<int32>(iInitList.size() - 1);
329 
330  // by definition, a discrete parameter has a step count > 0
331  DCHECK_F(stepCount > 0);
332 
333  int32 i = 0;
334  for(auto &pair : iInitList)
335  {
336  auto paramValue = convertDiscreteValueToNormalizedValue(stepCount, i);
337  fMap[pair.first] = std::make_tuple(pair.second, paramValue, i);
338  fList.emplace_back(pair.first);
339  i++;
340  }
341 
342  // sanity check... if not the same size it means that 2 entries in the list were the same!
343  DCHECK_F(fList.size() == fMap.size());
344  }
345 
346  // getStepCount
347  inline int32 getStepCount() const override { return static_cast<int32>(fMap.size() - 1); }
348 
349  // normalize
350  inline ParamValue normalize(ParamType const &iValue) const override
351  {
352  auto iter = fMap.find(iValue);
353  if(iter != fMap.cend())
354  return std::get<1>(iter->second);
355  else
356  {
357  DLOG_F(WARNING, "could not normalize value...");
358  return 0;
359  }
360  }
361 
362  // denormalize
363  inline ParamType denormalize(ParamValue iNormalizedValue) const override
364  {
365  auto index = convertNormalizedValueToDiscreteValue(getStepCount(), iNormalizedValue);
366  return fList[index];
367  }
368 
369  // toString
370  void toString(ParamType const &iValue, String128 oString, int32 iPrecision) const override
371  {
372  auto iter = fMap.find(iValue);
373  if(iter != fMap.cend())
374  {
375  Steinberg::UString wrapper(oString, str16BufferSize (String128));
376  wrapper.assign(std::get<0>(iter->second).c_str());
377  }
378  else
379  oString[0] = 0;
380  }
381 
382 private:
383  TMap fMap{};
384  TList fList{};
385 };
386 
392 template<typename Enum, Enum MaxValue>
394 {
395 public:
396  using ParamType = Enum;
397 
398  using IntType = std::underlying_type_t<Enum>;
399 
401 
404  using ConstructorType = std::array<VstString16, MaxValue + 1> const &;
405 
406  // Constructor - you can provide an offset for the toString conversion (ex: counting from 1 instead of 0)
407  explicit EnumParamConverter(IntType iToStringOffset = 0) : fConverter{iToStringOffset} {}
408 
409  // Constructor with printf style format where the parameter (%d) will be (value + offset)
410  explicit EnumParamConverter(VstString16 iFormat, IntType iToStringOffset = 0) : fConverter{std::move(iFormat), iToStringOffset} {}
411 
412  // Constructor with all values defined
413  explicit EnumParamConverter(ConstructorType iToStringValues) : fConverter{iToStringValues} {}
414 
415  // getStepCount
416  inline int32 getStepCount() const override { return MaxValue; }
417 
418  // normalize
419  inline ParamValue normalize(ParamType const &iDiscreteValue) const override
420  {
421  return fConverter.normalize(static_cast<IntType>(iDiscreteValue));
422  }
423 
424  // denormalize
425  inline ParamType denormalize(ParamValue iNormalizedValue) const override
426  {
427  return static_cast<Enum>(fConverter.denormalize(iNormalizedValue));
428  }
429 
430  // toString
431  void toString(ParamType const &iValue, String128 oString, int32 iPrecision) const override
432  {
433  fConverter.toString(static_cast<IntType>(iValue), oString, iPrecision);
434  }
435 
436 private:
438 };
439 
440 
441 }
int32 getStepCount() const override
Definition: ParamConverters.h:235
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:370
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:317
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:313
int32 getStepCount() const override
Definition: ParamConverters.h:118
DiscreteValueParamConverter(ConstructorType iToStringValues)
Definition: ParamConverters.h:232
Enum ParamType
Definition: ParamConverters.h:56
void toString(ParamType const &iValue, String128 oString, int32 iPrecision) const override
Definition: ParamConverters.h:431
std::underlying_type_t< Enum > IntType
Definition: ParamConverters.h:398
DiscreteValueParamConverter(VstString16 iFormat, IntType iToStringOffset=0)
Definition: ParamConverters.h:228
EnumParamConverter(ConstructorType iToStringValues)
Definition: ParamConverters.h:413
std::array< VstString16, MaxValue+1 > const & ConstructorType
Defines the type for the constructor argument.
Definition: ParamConverters.h:404
std::array< VstString16, StepCount+1 > const & ConstructorType
Defines the type for the constructor argument.
Definition: ParamConverters.h:222
DiscreteValueParamConverter(IntType iToStringOffset=0)
Definition: ParamConverters.h:225
DiscreteTypeParamConverter(ConstructorType iInitList)
This constructor will be called this way when initializing a vst or jmb parameter:
Definition: ParamConverters.h:326
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:304
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:347
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:419
EnumParamConverter(VstString16 iFormat, IntType iToStringOffset=0)
Definition: ParamConverters.h:410
ParamType denormalize(ParamValue iNormalizedValue) const override
Definition: ParamConverters.h:363
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:350
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:416
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:425
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:396
VstString16 fFalseString
Definition: ParamConverters.h:145
EnumParamConverter(IntType iToStringOffset=0)
Definition: ParamConverters.h:407
ParamType denormalize(ParamValue iNormalizedValue) const override
Definition: ParamConverters.h:242
DiscreteValueParamConverter< MaxValue, IntType > fConverter
Definition: ParamConverters.h:437
std::map< T, std::tuple< VstString16, ParamValue, int32 >, Compare > TMap
Maintains the map of possible values of T (defined in constructor)
Definition: ParamConverters.h:309
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:393
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:248
ParamValue normalize(ParamType const &iDiscreteValue) const override
Definition: ParamConverters.h:237
A vst parameter is represented by a ParamValue type which is a double in the range [0,...
Definition: ParamConverters.h:53