OpenShot Library | OpenShotAudio 0.2.2
juce_NormalisableRange.h
1
2/** @weakgroup juce_core-maths
3 * @{
4 */
5/*
6 ==============================================================================
7
8 This file is part of the JUCE library.
9 Copyright (c) 2017 - ROLI Ltd.
10
11 JUCE is an open source library subject to commercial or open-source
12 licensing.
13
14 The code included in this file is provided under the terms of the ISC license
15 http://www.isc.org/downloads/software-support-policy/isc-license. Permission
16 To use, copy, modify, and/or distribute this software for any purpose with or
17 without fee is hereby granted provided that the above copyright notice and
18 this permission notice appear in all copies.
19
20 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
21 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
22 DISCLAIMED.
23
24 ==============================================================================
25*/
26
27namespace juce
28{
29
30//==============================================================================
31/**
32 Represents a mapping between an arbitrary range of values and a
33 normalised 0->1 range.
34
35 The properties of the mapping also include an optional snapping interval
36 and skew-factor.
37
38 @see Range
39
40 @tags{Core}
41*/
42template <typename ValueType>
44{
45public:
46 /** Creates a continuous range that performs a dummy mapping. */
47 NormalisableRange() = default;
48
49 NormalisableRange (const NormalisableRange&) = default;
50 NormalisableRange& operator= (const NormalisableRange&) = default;
52 NormalisableRange& operator= (NormalisableRange&&) = default;
53
54 /** Creates a NormalisableRange with a given range, interval and skew factor. */
55 NormalisableRange (ValueType rangeStart,
56 ValueType rangeEnd,
57 ValueType intervalValue,
58 ValueType skewFactor,
59 bool useSymmetricSkew = false) noexcept
60 : start (rangeStart), end (rangeEnd), interval (intervalValue),
61 skew (skewFactor), symmetricSkew (useSymmetricSkew)
62 {
63 checkInvariants();
64 }
65
66 /** Creates a NormalisableRange with a given range, continuous interval, but a dummy skew-factor. */
67 NormalisableRange (ValueType rangeStart,
68 ValueType rangeEnd) noexcept
69 : start (rangeStart), end (rangeEnd)
70 {
71 checkInvariants();
72 }
73
74 /** Creates a NormalisableRange with a given range and interval, but a dummy skew-factor. */
75 NormalisableRange (ValueType rangeStart,
76 ValueType rangeEnd,
77 ValueType intervalValue) noexcept
78 : start (rangeStart), end (rangeEnd), interval (intervalValue)
79 {
80 checkInvariants();
81 }
82
83 /** Creates a NormalisableRange with a given range, continuous interval, but a dummy skew-factor. */
85 : NormalisableRange (range.getStart(), range.getEnd())
86 {
87 }
88
89 /** Creates a NormalisableRange with a given range and interval, but a dummy skew-factor. */
90 NormalisableRange (Range<ValueType> range, ValueType intervalValue) noexcept
91 : NormalisableRange (range.getStart(), range.getEnd(), intervalValue)
92 {
93 }
94
95 /** A function object which can remap a value in some way based on the start and end of a range. */
96 using ValueRemapFunction = std::function<ValueType(ValueType rangeStart,
97 ValueType rangeEnd,
98 ValueType valueToRemap)>;
99
100 /** Creates a NormalisableRange with a given range and an injective mapping function.
101
102 @param rangeStart The minimum value in the range.
103 @param rangeEnd The maximum value in the range.
104 @param convertFrom0To1Func A function which uses the current start and end of this NormalisableRange
105 and produces a mapped value from a normalised value.
106 @param convertTo0To1Func A function which uses the current start and end of this NormalisableRange
107 and produces a normalised value from a mapped value.
108 @param snapToLegalValueFunc A function which uses the current start and end of this NormalisableRange
109 to take a mapped value and snap it to the nearest legal value.
110 */
111 NormalisableRange (ValueType rangeStart,
112 ValueType rangeEnd,
113 ValueRemapFunction convertFrom0To1Func,
114 ValueRemapFunction convertTo0To1Func,
115 ValueRemapFunction snapToLegalValueFunc = {}) noexcept
116 : start (rangeStart),
117 end (rangeEnd),
118 convertFrom0To1Function (std::move (convertFrom0To1Func)),
119 convertTo0To1Function (std::move (convertTo0To1Func)),
120 snapToLegalValueFunction (std::move (snapToLegalValueFunc))
121 {
122 checkInvariants();
123 }
124
125 /** Uses the properties of this mapping to convert a non-normalised value to
126 its 0->1 representation.
127 */
128 ValueType convertTo0to1 (ValueType v) const noexcept
129 {
130 if (convertTo0To1Function != nullptr)
131 return clampTo0To1 (convertTo0To1Function (start, end, v));
132
133 auto proportion = clampTo0To1 ((v - start) / (end - start));
134
135 if (skew == static_cast<ValueType> (1))
136 return proportion;
137
138 if (! symmetricSkew)
139 return std::pow (proportion, skew);
140
141 auto distanceFromMiddle = static_cast<ValueType> (2) * proportion - static_cast<ValueType> (1);
142
143 return (static_cast<ValueType> (1) + std::pow (std::abs (distanceFromMiddle), skew)
144 * (distanceFromMiddle < ValueType() ? static_cast<ValueType> (-1)
145 : static_cast<ValueType> (1)))
146 / static_cast<ValueType> (2);
147 }
148
149 /** Uses the properties of this mapping to convert a normalised 0->1 value to
150 its full-range representation.
151 */
152 ValueType convertFrom0to1 (ValueType proportion) const noexcept
153 {
154 proportion = clampTo0To1 (proportion);
155
156 if (convertFrom0To1Function != nullptr)
157 return convertFrom0To1Function (start, end, proportion);
158
159 if (! symmetricSkew)
160 {
161 if (skew != static_cast<ValueType> (1) && proportion > ValueType())
162 proportion = std::exp (std::log (proportion) / skew);
163
164 return start + (end - start) * proportion;
165 }
166
167 auto distanceFromMiddle = static_cast<ValueType> (2) * proportion - static_cast<ValueType> (1);
168
169 if (skew != static_cast<ValueType> (1) && distanceFromMiddle != static_cast<ValueType> (0))
170 distanceFromMiddle = std::exp (std::log (std::abs (distanceFromMiddle)) / skew)
171 * (distanceFromMiddle < ValueType() ? static_cast<ValueType> (-1)
172 : static_cast<ValueType> (1));
173
174 return start + (end - start) / static_cast<ValueType> (2) * (static_cast<ValueType> (1) + distanceFromMiddle);
175 }
176
177 /** Takes a non-normalised value and snaps it based on either the interval property of
178 this NormalisableRange or the lambda function supplied to the constructor.
179 */
180 ValueType snapToLegalValue (ValueType v) const noexcept
181 {
182 if (snapToLegalValueFunction != nullptr)
183 return snapToLegalValueFunction (start, end, v);
184
185 if (interval > ValueType())
186 v = start + interval * std::floor ((v - start) / interval + static_cast<ValueType> (0.5));
187
188 return (v <= start || end <= start) ? start : (v >= end ? end : v);
189 }
190
191 /** Returns the extent of the normalisable range. */
192 Range<ValueType> getRange() const noexcept { return { start, end }; }
193
194 /** Given a value which is between the start and end points, this sets the skew
195 such that convertFrom0to1 (0.5) will return this value.
196
197 If you have used lambda functions for convertFrom0to1Func and convertFrom0to1Func in the
198 constructor of this class then the skew value is ignored.
199
200 @param centrePointValue this must be greater than the start of the range and less than the end.
201 */
202 void setSkewForCentre (ValueType centrePointValue) noexcept
203 {
204 jassert (centrePointValue > start);
205 jassert (centrePointValue < end);
206
207 symmetricSkew = false;
208 skew = std::log (static_cast<ValueType> (0.5)) / std::log ((centrePointValue - start) / (end - start));
209 checkInvariants();
210 }
211
212 /** The minimum value of the non-normalised range. */
213 ValueType start = 0;
214
215 /** The maximum value of the non-normalised range. */
216 ValueType end = 1;
217
218 /** The snapping interval that should be used (for a non-normalised value). Use 0 for a
219 continuous range.
220
221 If you have used a lambda function for snapToLegalValueFunction in the constructor of
222 this class then the interval is ignored.
223 */
224 ValueType interval = 0;
225
226 /** An optional skew factor that alters the way values are distribute across the range.
227
228 The skew factor lets you skew the mapping logarithmically so that larger or smaller
229 values are given a larger proportion of the available space.
230
231 A factor of 1.0 has no skewing effect at all. If the factor is < 1.0, the lower end
232 of the range will fill more of the slider's length; if the factor is > 1.0, the upper
233 end of the range will be expanded.
234
235 If you have used lambda functions for convertFrom0to1Func and convertFrom0to1Func in the
236 constructor of this class then the skew value is ignored.
237 */
238 ValueType skew = 1;
239
240 /** If true, the skew factor applies from the middle of the slider to each of its ends. */
241 bool symmetricSkew = false;
242
243private:
244 void checkInvariants() const
245 {
246 jassert (end > start);
247 jassert (interval >= ValueType());
248 jassert (skew > ValueType());
249 }
250
251 static ValueType clampTo0To1 (ValueType value)
252 {
253 auto clampedValue = jlimit (static_cast<ValueType> (0), static_cast<ValueType> (1), value);
254
255 // If you hit this assertion then either your normalisation function is not working
256 // correctly or your input is out of the expected bounds.
257 jassert (clampedValue == value);
258
259 return clampedValue;
260 }
261
262 ValueRemapFunction convertFrom0To1Function, convertTo0To1Function, snapToLegalValueFunction;
263};
264
265} // namespace juce
266
267/** @}*/
Represents a mapping between an arbitrary range of values and a normalised 0->1 range.
ValueType skew
An optional skew factor that alters the way values are distribute across the range.
ValueType end
The maximum value of the non-normalised range.
bool symmetricSkew
If true, the skew factor applies from the middle of the slider to each of its ends.
ValueType snapToLegalValue(ValueType v) const noexcept
Takes a non-normalised value and snaps it based on either the interval property of this NormalisableR...
std::function< ValueType(ValueType rangeStart, ValueType rangeEnd, ValueType valueToRemap)> ValueRemapFunction
A function object which can remap a value in some way based on the start and end of a range.
NormalisableRange()=default
Creates a continuous range that performs a dummy mapping.
ValueType start
The minimum value of the non-normalised range.
ValueType convertFrom0to1(ValueType proportion) const noexcept
Uses the properties of this mapping to convert a normalised 0->1 value to its full-range representati...
NormalisableRange(ValueType rangeStart, ValueType rangeEnd) noexcept
Creates a NormalisableRange with a given range, continuous interval, but a dummy skew-factor.
void setSkewForCentre(ValueType centrePointValue) noexcept
Given a value which is between the start and end points, this sets the skew such that convertFrom0to1...
NormalisableRange(ValueType rangeStart, ValueType rangeEnd, ValueRemapFunction convertFrom0To1Func, ValueRemapFunction convertTo0To1Func, ValueRemapFunction snapToLegalValueFunc={}) noexcept
Creates a NormalisableRange with a given range and an injective mapping function.
NormalisableRange(ValueType rangeStart, ValueType rangeEnd, ValueType intervalValue) noexcept
Creates a NormalisableRange with a given range and interval, but a dummy skew-factor.
Range< ValueType > getRange() const noexcept
Returns the extent of the normalisable range.
ValueType interval
The snapping interval that should be used (for a non-normalised value).
NormalisableRange(Range< ValueType > range, ValueType intervalValue) noexcept
Creates a NormalisableRange with a given range and interval, but a dummy skew-factor.
NormalisableRange(ValueType rangeStart, ValueType rangeEnd, ValueType intervalValue, ValueType skewFactor, bool useSymmetricSkew=false) noexcept
Creates a NormalisableRange with a given range, interval and skew factor.
ValueType convertTo0to1(ValueType v) const noexcept
Uses the properties of this mapping to convert a non-normalised value to its 0->1 representation.
NormalisableRange(Range< ValueType > range) noexcept
Creates a NormalisableRange with a given range, continuous interval, but a dummy skew-factor.
A general-purpose range object, that simply represents any linear range with a start and end point.
Definition: juce_Range.h:44