OpenShot Library | OpenShotAudio  0.2.2
juce_LookupTable.cpp
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  By using JUCE, you agree to the terms of both the JUCE 5 End-User License
11  Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
12  27th April 2017).
13 
14  End User License Agreement: www.juce.com/juce-5-licence
15  Privacy Policy: www.juce.com/juce-5-privacy-policy
16 
17  Or: You may also use this code under the terms of the GPL v3 (see
18  www.gnu.org/licenses).
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 
27 namespace juce
28 {
29 namespace dsp
30 {
31 
32 template <typename FloatType>
34 {
35  data.resize (1);
36 }
37 
38 template <typename FloatType>
39 LookupTable<FloatType>::LookupTable (const std::function<FloatType(size_t)>& functionToApproximate,
40  size_t numPointsToUse)
41 {
42  initialise (functionToApproximate, numPointsToUse);
43 }
44 
45 //==============================================================================
46 template <typename FloatType>
47 void LookupTable<FloatType>::initialise (const std::function<FloatType(size_t)>& functionToApproximate,
48  size_t numPointsToUse)
49 {
50  data.resize (static_cast<int> (getRequiredBufferSize (numPointsToUse)));
51 
52  for (size_t i = 0; i < numPointsToUse; ++i)
53  {
54  auto value = functionToApproximate (i);
55 
56  jassert (! std::isnan (value));
57  jassert (! std::isinf (value));
58  // Make sure functionToApproximate returns a sensible value for the entire specified range.
59  // E.g., this won't work for zero: [] (size_t i) { return 1.0f / i; }
60 
61  data.getReference (static_cast<int> (i)) = value;
62  }
63 
64  prepare();
65 }
66 
67 template <typename FloatType>
68 void LookupTable<FloatType>::prepare() noexcept
69 {
70  auto guardIndex = static_cast<int> (getGuardIndex());
71  data.getReference (guardIndex) = data.getUnchecked (guardIndex - 1);
72 }
73 
74 template <typename FloatType>
75 void LookupTableTransform<FloatType>::initialise (const std::function<FloatType(FloatType)>& functionToApproximate,
76  FloatType minInputValueToUse,
77  FloatType maxInputValueToUse,
78  size_t numPoints)
79 {
80  jassert (maxInputValueToUse > minInputValueToUse);
81 
82  minInputValue = minInputValueToUse;
83  maxInputValue = maxInputValueToUse;
84  scaler = FloatType (numPoints - 1) / (maxInputValueToUse - minInputValueToUse);
85  offset = -minInputValueToUse * scaler;
86 
87  const auto initFn = [functionToApproximate, minInputValueToUse, maxInputValueToUse, numPoints] (size_t i)
88  {
89  return functionToApproximate (
90  jlimit (
91  minInputValueToUse, maxInputValueToUse,
92  jmap (FloatType (i), FloatType (0), FloatType (numPoints - 1), minInputValueToUse, maxInputValueToUse))
93  );
94  };
95 
96  lookupTable.initialise (initFn, numPoints);
97 }
98 
99 //==============================================================================
100 template <typename FloatType>
101 double LookupTableTransform<FloatType>::calculateMaxRelativeError (const std::function<FloatType(FloatType)>& functionToApproximate,
102  FloatType minInputValue,
103  FloatType maxInputValue,
104  size_t numPoints,
105  size_t numTestPoints)
106 {
107  jassert (maxInputValue > minInputValue);
108 
109  if (numTestPoints == 0)
110  numTestPoints = 100 * numPoints; // use default
111 
112  LookupTableTransform transform (functionToApproximate, minInputValue, maxInputValue, numPoints);
113 
114  double maxError = 0;
115 
116  for (size_t i = 0; i < numTestPoints; ++i)
117  {
118  auto inputValue = jmap (FloatType (i), FloatType (0), FloatType (numTestPoints - 1), minInputValue, maxInputValue);
119  auto approximatedOutputValue = transform.processSample (inputValue);
120  auto referenceOutputValue = functionToApproximate (inputValue);
121 
122  maxError = jmax (maxError, calculateRelativeDifference ((double) referenceOutputValue, (double) approximatedOutputValue));
123  }
124 
125  return maxError;
126 }
127 
128 //==============================================================================
129 template <typename FloatType>
130 double LookupTableTransform<FloatType>::calculateRelativeDifference (double x, double y) noexcept
131 {
132  static const auto eps = std::numeric_limits<double>::min();
133 
134  auto absX = std::abs (x);
135  auto absY = std::abs (y);
136  auto absDiff = std::abs (x - y);
137 
138  if (absX < eps)
139  {
140  if (absY >= eps)
141  return absDiff / absY;
142 
143  return absDiff; // return the absolute error if both numbers are too close to zero
144  }
145 
146  return absDiff / std::min (absX, absY);
147 }
148 
149 //==============================================================================
150 template class LookupTable<float>;
151 template class LookupTable<double>;
152 
153 template class LookupTableTransform<float>;
154 template class LookupTableTransform<double>;
155 
156 } // namespace dsp
157 } // namespace juce
Class for approximating expensive arithmetic operations.
void initialise(const std::function< FloatType(FloatType)> &functionToApproximate, FloatType minInputValueToUse, FloatType maxInputValueToUse, size_t numPoints)
Initialises or changes the parameters of a LookupTableTransform object.
FloatType processSample(FloatType value) const noexcept
Calculates the approximated value for the given input value with range checking.
static double calculateMaxRelativeError(const std::function< FloatType(FloatType)> &functionToApproximate, FloatType minInputValue, FloatType maxInputValue, size_t numPoints, size_t numTestPoints=0)
Calculates the maximum relative error of the approximation for the specified parameter set.
Class for efficiently approximating expensive arithmetic operations.
FloatType getUnchecked(FloatType index) const noexcept
Calculates the approximated value for the given index without range checking.
void initialise(const std::function< FloatType(size_t)> &functionToApproximate, size_t numPointsToUse)
Initialises or changes the parameters of a LookupTable object.
LookupTable()
Creates an uninitialised LookupTable object.