OpenShot Audio Library | OpenShotAudio  0.3.0
juce_NormalisableRange.h
1 /*
2  ==============================================================================
3 
4  This file is part of the JUCE library.
5  Copyright (c) 2017 - ROLI Ltd.
6 
7  JUCE is an open source library subject to commercial or open-source
8  licensing.
9 
10  The code included in this file is provided under the terms of the ISC license
11  http://www.isc.org/downloads/software-support-policy/isc-license. Permission
12  To use, copy, modify, and/or distribute this software for any purpose with or
13  without fee is hereby granted provided that the above copyright notice and
14  this permission notice appear in all copies.
15 
16  JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
17  EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
18  DISCLAIMED.
19 
20  ==============================================================================
21 */
22 
23 namespace juce
24 {
25 
26 //==============================================================================
38 template <typename ValueType>
40 {
41 public:
43  NormalisableRange() = default;
44 
45  NormalisableRange (const NormalisableRange&) = default;
46  NormalisableRange& operator= (const NormalisableRange&) = default;
48  NormalisableRange& operator= (NormalisableRange&&) = default;
49 
51  NormalisableRange (ValueType rangeStart,
52  ValueType rangeEnd,
53  ValueType intervalValue,
54  ValueType skewFactor,
55  bool useSymmetricSkew = false) noexcept
56  : start (rangeStart), end (rangeEnd), interval (intervalValue),
57  skew (skewFactor), symmetricSkew (useSymmetricSkew)
58  {
59  checkInvariants();
60  }
61 
63  NormalisableRange (ValueType rangeStart,
64  ValueType rangeEnd) noexcept
65  : start (rangeStart), end (rangeEnd)
66  {
67  checkInvariants();
68  }
69 
71  NormalisableRange (ValueType rangeStart,
72  ValueType rangeEnd,
73  ValueType intervalValue) noexcept
74  : start (rangeStart), end (rangeEnd), interval (intervalValue)
75  {
76  checkInvariants();
77  }
78 
81  : NormalisableRange (range.getStart(), range.getEnd())
82  {
83  }
84 
86  NormalisableRange (Range<ValueType> range, ValueType intervalValue) noexcept
87  : NormalisableRange (range.getStart(), range.getEnd(), intervalValue)
88  {
89  }
90 
92  using ValueRemapFunction = std::function<ValueType(ValueType rangeStart,
93  ValueType rangeEnd,
94  ValueType valueToRemap)>;
95 
107  NormalisableRange (ValueType rangeStart,
108  ValueType rangeEnd,
109  ValueRemapFunction convertFrom0To1Func,
110  ValueRemapFunction convertTo0To1Func,
111  ValueRemapFunction snapToLegalValueFunc = {}) noexcept
112  : start (rangeStart),
113  end (rangeEnd),
114  convertFrom0To1Function (std::move (convertFrom0To1Func)),
115  convertTo0To1Function (std::move (convertTo0To1Func)),
116  snapToLegalValueFunction (std::move (snapToLegalValueFunc))
117  {
118  checkInvariants();
119  }
120 
124  ValueType convertTo0to1 (ValueType v) const noexcept
125  {
126  if (convertTo0To1Function != nullptr)
127  return clampTo0To1 (convertTo0To1Function (start, end, v));
128 
129  auto proportion = clampTo0To1 ((v - start) / (end - start));
130 
131  if (skew == static_cast<ValueType> (1))
132  return proportion;
133 
134  if (! symmetricSkew)
135  return std::pow (proportion, skew);
136 
137  auto distanceFromMiddle = static_cast<ValueType> (2) * proportion - static_cast<ValueType> (1);
138 
139  return (static_cast<ValueType> (1) + std::pow (std::abs (distanceFromMiddle), skew)
140  * (distanceFromMiddle < ValueType() ? static_cast<ValueType> (-1)
141  : static_cast<ValueType> (1)))
142  / static_cast<ValueType> (2);
143  }
144 
148  ValueType convertFrom0to1 (ValueType proportion) const noexcept
149  {
150  proportion = clampTo0To1 (proportion);
151 
152  if (convertFrom0To1Function != nullptr)
153  return convertFrom0To1Function (start, end, proportion);
154 
155  if (! symmetricSkew)
156  {
157  if (skew != static_cast<ValueType> (1) && proportion > ValueType())
158  proportion = std::exp (std::log (proportion) / skew);
159 
160  return start + (end - start) * proportion;
161  }
162 
163  auto distanceFromMiddle = static_cast<ValueType> (2) * proportion - static_cast<ValueType> (1);
164 
165  if (skew != static_cast<ValueType> (1) && distanceFromMiddle != static_cast<ValueType> (0))
166  distanceFromMiddle = std::exp (std::log (std::abs (distanceFromMiddle)) / skew)
167  * (distanceFromMiddle < ValueType() ? static_cast<ValueType> (-1)
168  : static_cast<ValueType> (1));
169 
170  return start + (end - start) / static_cast<ValueType> (2) * (static_cast<ValueType> (1) + distanceFromMiddle);
171  }
172 
176  ValueType snapToLegalValue (ValueType v) const noexcept
177  {
178  if (snapToLegalValueFunction != nullptr)
179  return snapToLegalValueFunction (start, end, v);
180 
181  if (interval > ValueType())
182  v = start + interval * std::floor ((v - start) / interval + static_cast<ValueType> (0.5));
183 
184  return (v <= start || end <= start) ? start : (v >= end ? end : v);
185  }
186 
188  Range<ValueType> getRange() const noexcept { return { start, end }; }
189 
198  void setSkewForCentre (ValueType centrePointValue) noexcept
199  {
200  jassert (centrePointValue > start);
201  jassert (centrePointValue < end);
202 
203  symmetricSkew = false;
204  skew = std::log (static_cast<ValueType> (0.5)) / std::log ((centrePointValue - start) / (end - start));
205  checkInvariants();
206  }
207 
209  ValueType start = 0;
210 
212  ValueType end = 1;
213 
220  ValueType interval = 0;
221 
234  ValueType skew = 1;
235 
237  bool symmetricSkew = false;
238 
239 private:
240  void checkInvariants() const
241  {
242  jassert (end > start);
243  jassert (interval >= ValueType());
244  jassert (skew > ValueType());
245  }
246 
247  static ValueType clampTo0To1 (ValueType value)
248  {
249  auto clampedValue = jlimit (static_cast<ValueType> (0), static_cast<ValueType> (1), value);
250 
251  // If you hit this assertion then either your normalisation function is not working
252  // correctly or your input is out of the expected bounds.
253  jassert (clampedValue == value);
254 
255  return clampedValue;
256  }
257 
258  ValueRemapFunction convertFrom0To1Function, convertTo0To1Function, snapToLegalValueFunction;
259 };
260 
261 } // namespace juce
ValueType snapToLegalValue(ValueType v) const noexcept
Range< ValueType > getRange() const noexcept
std::function< ValueType(ValueType rangeStart, ValueType rangeEnd, ValueType valueToRemap)> ValueRemapFunction
ValueType convertFrom0to1(ValueType proportion) const noexcept
NormalisableRange(ValueType rangeStart, ValueType rangeEnd) noexcept
void setSkewForCentre(ValueType centrePointValue) noexcept
NormalisableRange(ValueType rangeStart, ValueType rangeEnd, ValueRemapFunction convertFrom0To1Func, ValueRemapFunction convertTo0To1Func, ValueRemapFunction snapToLegalValueFunc={}) noexcept
NormalisableRange(ValueType rangeStart, ValueType rangeEnd, ValueType intervalValue) noexcept
NormalisableRange(Range< ValueType > range, ValueType intervalValue) noexcept
NormalisableRange(ValueType rangeStart, ValueType rangeEnd, ValueType intervalValue, ValueType skewFactor, bool useSymmetricSkew=false) noexcept
ValueType convertTo0to1(ValueType v) const noexcept
NormalisableRange(Range< ValueType > range) noexcept