You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

460 lines
16KB

  1. /*
  2. ==============================================================================
  3. This file is part of the dRowAudio JUCE module
  4. Copyright 2004-13 by dRowAudio.
  5. ------------------------------------------------------------------------------
  6. dRowAudio is provided under the terms of The MIT License (MIT):
  7. Permission is hereby granted, free of charge, to any person obtaining a copy
  8. of this software and associated documentation files (the "Software"), to deal
  9. in the Software without restriction, including without limitation the rights
  10. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11. copies of the Software, and to permit persons to whom the Software is
  12. furnished to do so, subject to the following conditions:
  13. The above copyright notice and this permission notice shall be included in all
  14. copies or substantial portions of the Software.
  15. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  21. SOFTWARE.
  22. ==============================================================================
  23. */
  24. #ifndef __DROWAUDIO_MATHSUTILITIES_H__
  25. #define __DROWAUDIO_MATHSUTILITIES_H__
  26. #if JUCE_MSVC
  27. #pragma warning (disable: 4505)
  28. #endif
  29. //==============================================================================
  30. /** Contains a value and its reciprocal.
  31. This has some handy operator overloads to speed up multiplication and divisions.
  32. */
  33. template <typename FloatingPointType>
  34. class Reciprocal
  35. {
  36. public:
  37. /** Creates a 1/1 value/reciprocal pair. */
  38. Reciprocal() { set (1.0); }
  39. /** Creates a 1/x value/reciprocal pair. */
  40. Reciprocal (FloatingPointType initalValue) { set (initalValue); }
  41. /** Returns the value. */
  42. FloatingPointType get() const noexcept { return value; }
  43. /** Returns the value. */
  44. FloatingPointType getValue() const noexcept { return value; }
  45. /** Returns the reciprocal. */
  46. FloatingPointType getReciprocal() const noexcept { return reciprocal; }
  47. /** Sets the value updating the reciprocal. */
  48. FloatingPointType set (FloatingPointType newValue) noexcept
  49. {
  50. jassert (newValue != 0);
  51. value = newValue;
  52. reciprocal = (FloatingPointType) (1.0 / value);
  53. return value;
  54. }
  55. /** Sets the value updating the reciprocal. */
  56. FloatingPointType operator= (FloatingPointType newValue) noexcept { return set (newValue); }
  57. FloatingPointType operator+ (FloatingPointType operand) const noexcept { return value + operand; }
  58. FloatingPointType operator+= (FloatingPointType operand) noexcept { return set (value + operand); }
  59. FloatingPointType operator- (FloatingPointType operand) const noexcept { return value - operand; }
  60. FloatingPointType operator-= (FloatingPointType operand) noexcept { return set (value - operand); }
  61. FloatingPointType operator* (FloatingPointType operand) const noexcept { return value * operand; }
  62. FloatingPointType operator/ (FloatingPointType operand) const noexcept { return operand * reciprocal * value; }
  63. FloatingPointType operator*= (FloatingPointType operand) noexcept { return set (value *= operand); }
  64. FloatingPointType operator/= (FloatingPointType operand) noexcept { return set (operand * reciprocal * value); }
  65. private:
  66. FloatingPointType value, reciprocal;
  67. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Reciprocal)
  68. };
  69. //==============================================================================
  70. /** Returns true if the given integer number is even. */
  71. inline bool isEven (int number) noexcept
  72. {
  73. return ! (number & 0x1);
  74. }
  75. /** Returns true if the given integer number is odd. */
  76. inline bool isOdd (int number) noexcept
  77. {
  78. return number & 0x1;
  79. }
  80. //==============================================================================
  81. /** Finds the maximum value and location of this in a buffer regardless of sign. */
  82. template <typename FloatingPointType>
  83. inline void findAbsoluteMax (const FloatingPointType* samples, int numSamples,
  84. int& maxSampleLocation, FloatingPointType& maxSampleValue) noexcept
  85. {
  86. maxSampleValue = 0;
  87. for (int i = 0; i < numSamples; ++i)
  88. {
  89. const FloatingPointType absoluteSample = fabs (samples[i]);
  90. if (absoluteSample > maxSampleValue)
  91. {
  92. maxSampleValue = absoluteSample;
  93. maxSampleLocation = i;
  94. }
  95. }
  96. }
  97. /** Normalises a set of samples to the absolute maximum contained within the buffer. */
  98. template <typename FloatingPointType>
  99. inline void normalise (FloatingPointType* samples, int numSamples) noexcept
  100. {
  101. FloatingPointType max = 0;
  102. int location;
  103. findAbsoluteMax (samples, numSamples, location, max);
  104. if (max != 0)
  105. {
  106. const FloatingPointType oneOverMax = 1 / max;
  107. for (int i = 0; i < numSamples; ++i)
  108. samples[i] *= oneOverMax;
  109. }
  110. else
  111. {
  112. zeromem (samples, numSamples * sizeof (float));
  113. }
  114. }
  115. /** Squares all the values in an array. */
  116. template <typename FloatingPointType>
  117. inline void square (FloatingPointType* samples, int numSamples)
  118. {
  119. for (int i = 0; i < numSamples; ++i)
  120. samples[i] = juce::square<FloatingPointType> (samples[i]);
  121. }
  122. //==============================================================================
  123. /** Finds the autocorrelation of a set of given samples.
  124. This will cross-correlate inputSamples with itself and put the result in
  125. output samples. Note that this uses a shrinking integration window, assuming
  126. values outside of numSamples are 0. This leads to an exponetially decreasing
  127. autocorrelation function.
  128. */
  129. template <typename FloatingPointType>
  130. inline void autocorrelate (const FloatingPointType* inputSamples, int numSamples, FloatingPointType* outputSamples) noexcept
  131. {
  132. for (int i = 0; i < numSamples; i++)
  133. {
  134. FloatingPointType sum = 0;
  135. for (int j = 0; j < numSamples - i; j++)
  136. sum += inputSamples[j] * inputSamples[j + i];
  137. outputSamples[i] = sum * (static_cast<FloatingPointType> (1) / numSamples);
  138. }
  139. }
  140. /** Finds the autocorrelation of a set of given samples using a
  141. square-difference function.
  142. This will cross-correlate inputSamples with itself and put the result in
  143. output samples. Note that this uses a shrinking integration window, assuming
  144. values outside of numSamples are 0. This leads to an exponetially decreasing
  145. autocorrelation function.
  146. */
  147. template <typename FloatingPointType>
  148. inline void sdfAutocorrelate (const FloatingPointType* inputSamples, int numSamples, FloatingPointType* outputSamples) noexcept
  149. {
  150. for (int i = 0; i < numSamples; i++)
  151. {
  152. FloatingPointType sum = 0;
  153. for (int j = 0; j < numSamples - i; j++)
  154. sum += squareNumber (inputSamples[j] - inputSamples[j + i]);
  155. outputSamples[i] = sum;
  156. }
  157. }
  158. /** Performs a first order differential on the set of given samples.
  159. This is the same as finding the difference between each sample and the previous.
  160. Note that outputSamples can point to the same location as inputSamples.
  161. */
  162. template <typename FloatingPointType>
  163. inline void differentiate (const FloatingPointType* inputSamples, int numSamples, FloatingPointType* outputSamples) noexcept
  164. {
  165. FloatingPointType lastSample = 0.0;
  166. for (int i = 0; i < numSamples; ++i)
  167. {
  168. FloatingPointType currentSample = inputSamples[i];
  169. outputSamples[i] = currentSample - lastSample;
  170. lastSample = currentSample;
  171. }
  172. }
  173. /** Finds the mean of a set of samples. */
  174. template <typename FloatingPointType>
  175. inline FloatingPointType findMean (const FloatingPointType* samples, int numSamples) noexcept
  176. {
  177. FloatingPointType total = 0;
  178. for (int i = 0; i < numSamples; ++i)
  179. total += samples[i];
  180. return total / numSamples;
  181. }
  182. /** Returns the median of a set of samples assuming they are sorted. */
  183. template <typename FloatingPointType>
  184. inline FloatingPointType findMedian (const FloatingPointType* samples, int numSamples) noexcept
  185. {
  186. if (isEven (numSamples % 2)) // is even
  187. {
  188. return samples[numSamples / 2];
  189. }
  190. else
  191. {
  192. const int lowerIndex = int (numSamples / 2);
  193. const FloatingPointType lowerSample = samples[lowerIndex];
  194. const FloatingPointType upperSample = samples[lowerIndex + 1];
  195. return (lowerSample + upperSample) / 2;
  196. }
  197. }
  198. /** Finds the variance of a set of samples. */
  199. template <typename FloatingPointType>
  200. inline FloatingPointType findVariance (const FloatingPointType* samples, int numSamples) noexcept
  201. {
  202. const FloatingPointType mean = findMean (samples, numSamples);
  203. FloatingPointType total = 0;
  204. for (int i = 0; i < numSamples; ++i)
  205. total += squareNumber (samples[i] - mean);
  206. return total / numSamples;
  207. }
  208. /** Finds the corrected variance for a set of samples suitable for a sample standard deviation.
  209. Note the N - 1 in the formula to correct for small data sets.
  210. */
  211. template <typename FloatingPointType>
  212. inline FloatingPointType findCorrectedVariance (const FloatingPointType* samples, int numSamples) noexcept
  213. {
  214. const FloatingPointType mean = findMean (samples, numSamples);
  215. FloatingPointType total = 0;
  216. for (int i = 0; i < numSamples; ++i)
  217. total += squareNumber (samples[i] - mean);
  218. return total / (numSamples - 1);
  219. }
  220. /** Finds the sample standard deviation for a set of samples. */
  221. template <typename FloatingPointType>
  222. inline FloatingPointType findStandardDeviation (const FloatingPointType* samples, int numSamples) noexcept
  223. {
  224. return sqrt (findCorrectedVariance (samples, numSamples));
  225. }
  226. /** Finds the RMS for a set of samples. */
  227. template <typename FloatingPointType>
  228. inline FloatingPointType findRMS (const FloatingPointType* samples, int numSamples) noexcept
  229. {
  230. FloatingPointType sum = 0;
  231. for (int i = 0; i < numSamples; ++i)
  232. sum += juce::square (*samples++);
  233. return std::sqrt (sum / numSamples);
  234. }
  235. //==============================================================================
  236. /** Linear Interpolater.
  237. Performs a linear interpolation for a fractional buffer position.
  238. Note: For speed no bounds checking is performed on the buffer position so it is
  239. up to the caller to make sure it is less than the buffer size or you will be
  240. reading random memory and probably get an audio blow-up.
  241. */
  242. template <typename FloatingPointType>
  243. inline FloatingPointType linearInterpolate (const FloatingPointType* buffer, int bufferSize, FloatingPointType bufferPosition) noexcept
  244. {
  245. int lower = (int) bufferPosition;
  246. int upper = lower + 1;
  247. if (upper == bufferSize)
  248. upper = 0;
  249. FloatingPointType difference = bufferPosition - lower;
  250. return (buffer[upper] * difference) + (buffer[lower] * (static_cast<FloatingPointType> (1) - difference));
  251. }
  252. /** Checks to see if two values are equal within a given precision.
  253. */
  254. template <typename FloatingPointType>
  255. inline bool almostEqual (FloatingPointType firstValue, FloatingPointType secondValue, FloatingPointType precision = 0.00001)
  256. {
  257. if (fabs (firstValue - secondValue) < precision)
  258. return true;
  259. else
  260. return false;
  261. }
  262. /** Normalises a value to a range of 0-1 with a given minimum & maximum.
  263. This is just a quick function to make more readable code and desn't do any error checking.
  264. If your value is outside the range you will get a normalised value < 0 or > 1.
  265. */
  266. template <typename FloatingPointType>
  267. inline FloatingPointType normalise (const FloatingPointType valueToNormalise, const FloatingPointType minimum, const FloatingPointType maximum) noexcept
  268. {
  269. return (valueToNormalise - minimum) / (maximum - minimum);
  270. }
  271. /** Scales a value to have a log range between a given minimum & maximum.
  272. This is just a quick function to make more readable code and desn't do any error checking.
  273. This is useful when scaling values for meters etc. A good starting point is a normalised
  274. input value, minimum of 1 and maximum of 40.
  275. */
  276. template <typename FloatingPointType>
  277. inline FloatingPointType logBase10Scale (const FloatingPointType valueToScale,
  278. const FloatingPointType minimum,
  279. const FloatingPointType maximum) noexcept
  280. {
  281. return log10 (minimum + ((maximum - minimum) * valueToScale)) / log10 (maximum);
  282. }
  283. /** Converts a frequency in hertz to its Mel (or melody) based scale.
  284. The Mel scale is devised so that 1KHz represents a human perceived doubling in pitch.
  285. */
  286. template <typename FloatingPointType>
  287. inline FloatingPointType melScale (const FloatingPointType frequencyInHerts) noexcept
  288. {
  289. return 2595 * log10 (1 + (frequencyInHerts / 700.0));
  290. }
  291. //==============================================================================
  292. /** Checks to see if a number is NaN eg. sqrt (-1). */
  293. template <typename Type>
  294. inline static bool isnan (Type value)
  295. {
  296. #if JUCE_MAC
  297. return std::isnan (value);
  298. #else
  299. volatile Type num = value;
  300. return num != num;
  301. #endif
  302. }
  303. /** Checks to see if a number is Inf eg. 100.0 / 0.0. */
  304. template <typename Type>
  305. inline static bool isinf (Type value)
  306. {
  307. #if ! JUCE_WINDOWS
  308. return std::isinf (value);
  309. #else
  310. return ! _finite (value);
  311. #endif
  312. }
  313. //==============================================================================
  314. /** Sinc function. */
  315. template <typename Type>
  316. inline Type sinc (const Type x) noexcept
  317. {
  318. if (x == 0)
  319. return static_cast<Type> (1);
  320. return sin (x) / x;
  321. }
  322. /** Sinc function normalised with PI for audio applications.
  323. N.B. For accuracy this needs to use a double precision PI value internally
  324. so a cast will occur if floats are used.
  325. */
  326. template<typename FloatingPointType>
  327. inline FloatingPointType sincPi (const FloatingPointType x) noexcept
  328. {
  329. if (x == 0)
  330. return static_cast<FloatingPointType> (1);
  331. return static_cast<FloatingPointType> (std::sin (double_Pi * x) / (double_Pi * x));
  332. }
  333. /** Returns true if the argument is a power of 2.
  334. This will return false if 0 is passed.
  335. */
  336. template <typename IntegerType>
  337. inline bool isPowerOfTwo (IntegerType number) noexcept
  338. {
  339. return (number) && ! (number & (number - 1));
  340. }
  341. /** Returns the next power of 2 of the given number. */
  342. inline int nextPowerOfTwo (int number) noexcept
  343. {
  344. if (isPowerOfTwo (number))
  345. return number;
  346. else
  347. return (int) pow (2.0, ceil (log ((double) number) / log (2.0)));
  348. }
  349. /** Returns the previous power of 2.
  350. This may return 0 if a number < 1 is passed.
  351. */
  352. inline int prevPowerOfTwo (int number) noexcept
  353. {
  354. if (isPowerOfTwo (number))
  355. return number;
  356. else
  357. return (int) (pow (2.0, ceil (log ((double) number) / log (2.0))) * 0.5);
  358. }
  359. /** Returns the power which 2 has to be raised to to get the given number.
  360. If the given number is not an exact power of 2 the next nearest power will be given.
  361. E.g. 1024 will return 10 as will 1023.
  362. */
  363. inline int findPowerForBaseTwo (int number) noexcept
  364. {
  365. if (isPowerOfTwo (number))
  366. return (int) (log ((double) number) / log(2.0));
  367. else
  368. return (int) (log ((double) nextPowerOfTwo (number)) / log(2.0));
  369. }
  370. #if JUCE_MSVC || DOXYGEN
  371. /** Log2 function for the MSVC compiler. */
  372. inline double log2 (double number)
  373. {
  374. return log (number) / log (2.0);
  375. }
  376. /** Log2f function for the MSVC compiler. */
  377. inline float log2f (float number)
  378. {
  379. return log (number) / log (2.0f);
  380. }
  381. #endif
  382. #endif //__DROWAUDIO_MATHSUTILITIES_H__