AAX SDK 2.6.1
Avid Audio Extensions Development Kit
Loading...
Searching...
No Matches
AAX_CRangeTaperDelegate.h
Go to the documentation of this file.
1/*================================================================================================*/
2/*
3 *
4 * Copyright 2013-2017, 2019, 2023 Avid Technology, Inc.
5 * All rights reserved.
6 *
7 * CONFIDENTIAL: this document contains confidential information of Avid. Do
8 * not disclose to any third party. Use of the information contained in this
9 * document is subject to an Avid SDK license.
10 *
11 */
12
19/*================================================================================================*/
20
21
22#ifndef AAX_CRANGETAPERDELEGATE_H
23#define AAX_CRANGETAPERDELEGATE_H
24
25#include "AAX_ITaperDelegate.h"
26#include "AAX.h" //for types
27
28#include <cmath> //for floor()
29#include <vector>
30
31
79template <typename T, int32_t RealPrecision=1000>
81{
82public:
96 AAX_CRangeTaperDelegate(T* range, double* rangesSteps, long numRanges, bool useSmartRounding = true);
99
100 //Virtual Overrides
102 T GetMinimumValue() const AAX_OVERRIDE { return mMinValue; }
103 T GetMaximumValue() const AAX_OVERRIDE { return mMaxValue; }
104 T ConstrainRealValue(T value) const AAX_OVERRIDE;
105 T NormalizedToReal(double normalizedValue) const AAX_OVERRIDE;
106 double RealToNormalized(T realValue) const AAX_OVERRIDE;
107
108protected:
109 T Round(double iValue) const;
110 T SmartRound(double value) const;
111
112private:
113 T mMinValue;
114 T mMaxValue;
115 long mNumRanges;
116 std::vector<T> mRanges;
117 std::vector<double> mRangesSteps;
118 std::vector<double> mRangesPercents;
119 std::vector<double> mRangesStepsCount;
120 bool mUseSmartRounding;
121};
122
123template <typename T, int32_t RealPrecision>
124AAX_CRangeTaperDelegate<T, RealPrecision>::AAX_CRangeTaperDelegate(T* ranges, double* rangesSteps, long numRanges, bool useSmartRounding) :
126 mMinValue(*ranges),
127 mMaxValue(*(ranges + numRanges)),
128 mNumRanges(numRanges),
129 mRanges( ranges, ranges + numRanges + 1),
130 mRangesSteps( rangesSteps, rangesSteps + numRanges),
131 mUseSmartRounding( useSmartRounding )
132{
133 mRangesStepsCount.reserve(numRanges);
134 mRangesPercents.reserve(numRanges);
135 int i = 0;
136 for (; i < mNumRanges; i++)
137 {
138 mRangesStepsCount.push_back( (mRanges.at(i + 1) - mRanges.at(i)) / mRangesSteps.at(i));
139 }
140 double numSteps = 0;
141 for (i = 0; i < mNumRanges; i++)
142 {
143 numSteps += mRangesStepsCount.at(i);
144 }
145 for (i = 0; i < mNumRanges; i++)
146 {
147 mRangesPercents.push_back( mRangesStepsCount.at(i) / numSteps );
148 }
149}
150
151template <typename T, int32_t RealPrecision>
153 mMinValue(rhs.mMinValue),
154 mMaxValue(rhs.mMaxValue),
155 mNumRanges(rhs.mNumRanges),
156 mRanges( rhs.mRanges.begin(), rhs.mRanges.end()),
157 mRangesSteps( rhs.mRangesSteps.begin(), rhs.mRangesSteps.end()),
158 mRangesPercents( rhs.mRangesPercents.begin(), rhs.mRangesPercents.end()),
159 mRangesStepsCount( rhs.mRangesStepsCount.begin(), rhs.mRangesStepsCount.end()),
160 mUseSmartRounding( rhs.mUseSmartRounding )
161{
162}
163
164template <typename T, int32_t RealPrecision>
166{
167 if (this == &rhs)
168 return *this;
169
170 this->mMinValue = rhs.mMinValue;
171 this->mMaxValue = rhs.mMaxValue;
172 this->mNumRanges = rhs.mNumRanges;
173 this->mRanges.assign( rhs.mRanges.begin(), rhs.mRanges.end());
174 this->mRangesSteps.assign( rhs.mRangesSteps.begin(), rhs.mRangesSteps.end());
175 this->mRangesPercents.assign( rhs.mRangesPercents.begin(), rhs.mRangesPercents.end());
176 this->mRangesStepsCount.assign( rhs.mRangesStepsCount.begin(), rhs.mRangesStepsCount.end());
177
178 return *this;
179}
180
181template <typename T, int32_t RealPrecision>
183{
184 return ((0 >= RealPrecision) ? static_cast<T>(iValue) :
185 (0 <= iValue) ? floor( iValue*RealPrecision + 0.5f ) / RealPrecision :
186 ceil( iValue*RealPrecision - 0.5f ) / RealPrecision
187 );
188}
189
190template <typename T, int32_t RealPrecision>
192{
194}
195
196template <typename T, int32_t RealPrecision>
198{
199 if (mMinValue == mMaxValue)
200 return mMinValue;
201
202 if (RealPrecision)
203 value = Round(value); //reduce the precision to get proper rounding behavior with integers.
204
205 const T& highValue = mMaxValue > mMinValue ? mMaxValue : mMinValue;
206 const T& lowValue = mMaxValue > mMinValue ? mMinValue : mMaxValue;
207
208 if (value > highValue)
209 return highValue;
210 if (value < lowValue)
211 return lowValue;
212
213 return value;
214}
215
216template <typename T, int32_t RealPrecision>
218{
219 double percentTotal = normalizedValue;
220
221 double percent = 0.0;
222 long i = 0;
223 for (; i < mNumRanges; i++)
224 {
225 if ((percentTotal >= percent) && (percentTotal < (percent + mRangesPercents.at( i ) )))
226 break;
227 percent += mRangesPercents.at( i );
228 }
229
230 double extValue;
231 if (i == mNumRanges)
232 extValue = mMaxValue; // our control is 100% of maximum
233 else
234 extValue = mRanges.at(i) + ((mRanges.at(i+1) - mRanges.at(i))*(percentTotal - percent)) / (mRangesPercents.at(i));
235
236 T realValue = T(extValue);
237 if ( mUseSmartRounding )
238 realValue = SmartRound(extValue); //reduce the precision to get proper rounding behavior with integers.
239
240 return ConstrainRealValue(realValue);
241}
242
243template <typename T, int32_t RealPrecision>
245{
246 realValue = ConstrainRealValue(realValue);
247
248 double percentTotal = 0.0;
249 long i = 0;
250 for (; i < mNumRanges; i++)
251 {
252 if ((realValue >= mRanges[i]) && (realValue < mRanges[i+1]))
253 break;
254 percentTotal += mRangesPercents[i];
255 }
256
257 if (i == mNumRanges)
258 percentTotal = 1.0; // our control is 100% of maximum
259 else if (mRanges.at(i + 1) == mRanges.at(i))
260 ; // no action; total percent does not change
261 else
262 percentTotal += (realValue - mRanges.at(i))/(mRanges.at(i + 1) - mRanges.at(i)) * mRangesPercents.at(i);
263
264 double normalizedValue = percentTotal;
265 return normalizedValue;
266}
267
268template <typename T, int32_t RealPrecision>
270{
271 int32_t i = 0;
272 for (; i < mNumRanges; i++)
273 {
274 if ((value >= mRanges.at(i)) && (value < mRanges.at(i + 1) ))
275 break;
276 if ( i == mNumRanges - 1 )
277 break;
278 }
279
280 int32_t longVal = 0;
281 if (value >= 0)
282 longVal = int32_t(floor(value / mRangesSteps.at(i) + 0.5));
283 else
284 longVal = int32_t(ceil(value / mRangesSteps.at(i) - 0.5));
285
286 return static_cast<double>(longVal) * mRangesSteps.at(i);
287}
288
289
290#endif
Defines the taper conversion behavior for a parameter.
Various utility definitions for AAX.
#define AAX_OVERRIDE
override keyword macro
Definition: AAX.h:151
A piecewise-linear taper conforming to AAX_ITaperDelegate.
Definition: AAX_CRangeTaperDelegate.h:81
AAX_CRangeTaperDelegate(T *range, double *rangesSteps, long numRanges, bool useSmartRounding=true)
Constructs a Range Taper with specified minimum and maximum values.
Definition: AAX_CRangeTaperDelegate.h:124
T GetMaximumValue() const AAX_OVERRIDE
Returns the taper's maximum real value.
Definition: AAX_CRangeTaperDelegate.h:103
double RealToNormalized(T realValue) const AAX_OVERRIDE
Normalizes a real parameter value.
Definition: AAX_CRangeTaperDelegate.h:244
T SmartRound(double value) const
Definition: AAX_CRangeTaperDelegate.h:269
T NormalizedToReal(double normalizedValue) const AAX_OVERRIDE
Converts a normalized value to a real value.
Definition: AAX_CRangeTaperDelegate.h:217
T Round(double iValue) const
Definition: AAX_CRangeTaperDelegate.h:182
AAX_CRangeTaperDelegate< T, RealPrecision > * Clone() const AAX_OVERRIDE
Constructs and returns a copy of the taper delegate.
Definition: AAX_CRangeTaperDelegate.h:191
T GetMinimumValue() const AAX_OVERRIDE
Returns the taper's minimum real value.
Definition: AAX_CRangeTaperDelegate.h:102
AAX_CRangeTaperDelegate & operator=(AAX_CRangeTaperDelegate &rhs)
Definition: AAX_CRangeTaperDelegate.h:165
T ConstrainRealValue(T value) const AAX_OVERRIDE
Applies a contraint to the value and returns the constrained value.
Definition: AAX_CRangeTaperDelegate.h:197
Definition: AAX_ITaperDelegate.h:86