DISTRHO Plugin Framework
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.

301 lines
7.9KB

  1. /*
  2. * DISTRHO Plugin Framework (DPF)
  3. * Copyright (C) 2012-2021 Filipe Coelho <falktx@falktx.com>
  4. *
  5. * Permission to use, copy, modify, and/or distribute this software for any purpose with
  6. * or without fee is hereby granted, provided that the above copyright notice and this
  7. * permission notice appear in all copies.
  8. *
  9. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
  10. * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
  11. * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
  12. * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
  13. * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  14. * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  15. */
  16. #ifndef DISTRHO_UTILS_HPP_INCLUDED
  17. #define DISTRHO_UTILS_HPP_INCLUDED
  18. #include "src/DistrhoDefines.h"
  19. #include <cstdarg>
  20. #include <cstdio>
  21. #include <cstdlib>
  22. #include <cstring>
  23. #include <cmath>
  24. #include <limits>
  25. #ifdef DISTRHO_PROPER_CPP11_SUPPORT
  26. # include <cstdint>
  27. #else
  28. # include <stdint.h>
  29. #endif
  30. #if defined(DISTRHO_OS_WINDOWS) && defined(_MSC_VER)
  31. #include <basetsd.h>
  32. typedef SSIZE_T ssize_t;
  33. #endif
  34. #if defined(DISTRHO_OS_MAC) && ! defined(CARLA_OS_MAC) && ! defined(DISTRHO_PROPER_CPP11_SUPPORT)
  35. namespace std {
  36. inline float fmin(float __x, float __y)
  37. { return __builtin_fminf(__x, __y); }
  38. inline float fmax(float __x, float __y)
  39. { return __builtin_fmaxf(__x, __y); }
  40. inline float rint(float __x)
  41. { return __builtin_rintf(__x); }
  42. inline float round(float __x)
  43. { return __builtin_roundf(__x); }
  44. }
  45. #endif
  46. #ifndef M_PI
  47. # define M_PI 3.14159265358979323846
  48. #endif
  49. #define DISTRHO_MACRO_AS_STRING_VALUE(MACRO) #MACRO
  50. #define DISTRHO_MACRO_AS_STRING(MACRO) DISTRHO_MACRO_AS_STRING_VALUE(MACRO)
  51. // -----------------------------------------------------------------------
  52. // misc functions
  53. /*
  54. * Return a 64-bit number from 4 8-bit numbers.
  55. */
  56. static inline
  57. int64_t d_cconst(const uint8_t a, const uint8_t b, const uint8_t c, const uint8_t d) noexcept
  58. {
  59. return (a << 24) | (b << 16) | (c << 8) | (d << 0);
  60. }
  61. /*
  62. * Return an hexadecimal representation of a MAJ.MIN.MICRO version number.
  63. */
  64. static inline
  65. uint32_t d_version(const uint8_t major, const uint8_t minor, const uint8_t micro) noexcept
  66. {
  67. return uint32_t(major << 16) | uint32_t(minor << 8) | (micro << 0);
  68. }
  69. /*
  70. * Dummy function.
  71. */
  72. static inline
  73. void d_pass() noexcept {}
  74. // -----------------------------------------------------------------------
  75. // string print functions
  76. /*
  77. * Print a string to stdout with newline (gray color).
  78. * Does nothing if DEBUG is not defined.
  79. */
  80. #ifndef DEBUG
  81. # define d_debug(...)
  82. #else
  83. static inline
  84. void d_debug(const char* const fmt, ...) noexcept
  85. {
  86. try {
  87. va_list args;
  88. va_start(args, fmt);
  89. std::fprintf(stdout, "\x1b[30;1m");
  90. std::vfprintf(stdout, fmt, args);
  91. std::fprintf(stdout, "\x1b[0m\n");
  92. va_end(args);
  93. } catch (...) {}
  94. }
  95. #endif
  96. /*
  97. * Print a string to stdout with newline.
  98. */
  99. static inline
  100. void d_stdout(const char* const fmt, ...) noexcept
  101. {
  102. try {
  103. va_list args;
  104. va_start(args, fmt);
  105. std::vfprintf(stdout, fmt, args);
  106. std::fprintf(stdout, "\n");
  107. va_end(args);
  108. } catch (...) {}
  109. }
  110. /*
  111. * Print a string to stderr with newline.
  112. */
  113. static inline
  114. void d_stderr(const char* const fmt, ...) noexcept
  115. {
  116. try {
  117. va_list args;
  118. va_start(args, fmt);
  119. std::vfprintf(stderr, fmt, args);
  120. std::fprintf(stderr, "\n");
  121. va_end(args);
  122. } catch (...) {}
  123. }
  124. /*
  125. * Print a string to stderr with newline (red color).
  126. */
  127. static inline
  128. void d_stderr2(const char* const fmt, ...) noexcept
  129. {
  130. try {
  131. va_list args;
  132. va_start(args, fmt);
  133. std::fprintf(stderr, "\x1b[31m");
  134. std::vfprintf(stderr, fmt, args);
  135. std::fprintf(stderr, "\x1b[0m\n");
  136. va_end(args);
  137. } catch (...) {}
  138. }
  139. /*
  140. * Print a safe assertion error message.
  141. */
  142. static inline
  143. void d_safe_assert(const char* const assertion, const char* const file, const int line) noexcept
  144. {
  145. d_stderr2("assertion failure: \"%s\" in file %s, line %i", assertion, file, line);
  146. }
  147. /*
  148. * Print a safe assertion error message, with 1 extra signed integer value.
  149. */
  150. static inline
  151. void d_safe_assert_int(const char* const assertion, const char* const file,
  152. const int line, const int value) noexcept
  153. {
  154. d_stderr2("assertion failure: \"%s\" in file %s, line %i, value %i", assertion, file, line, value);
  155. }
  156. /*
  157. * Print a safe assertion error message, with 1 extra unsigned integer value.
  158. */
  159. static inline
  160. void d_safe_assert_uint(const char* const assertion, const char* const file,
  161. const int line, const uint value) noexcept
  162. {
  163. d_stderr2("assertion failure: \"%s\" in file %s, line %i, value %u", assertion, file, line, value);
  164. }
  165. /*
  166. * Print a safe assertion error message, with 2 extra signed integer values.
  167. */
  168. static inline
  169. void d_safe_assert_int2(const char* const assertion, const char* const file,
  170. const int line, const int v1, const int v2) noexcept
  171. {
  172. d_stderr2("assertion failure: \"%s\" in file %s, line %i, v1 %i, v2 %i", assertion, file, line, v1, v2);
  173. }
  174. /*
  175. * Print a safe assertion error message, with 2 extra unsigned integer values.
  176. */
  177. static inline
  178. void d_safe_assert_uint2(const char* const assertion, const char* const file,
  179. const int line, const uint v1, const uint v2) noexcept
  180. {
  181. d_stderr2("assertion failure: \"%s\" in file %s, line %i, v1 %u, v2 %u", assertion, file, line, v1, v2);
  182. }
  183. /*
  184. * Print a safe assertion error message, with a custom error message.
  185. */
  186. static inline
  187. void d_custom_safe_assert(const char* const message, const char* const assertion, const char* const file,
  188. const int line) noexcept
  189. {
  190. d_stderr2("assertion failure: %s, condition \"%s\" in file %s, line %i", message, assertion, file, line);
  191. }
  192. /*
  193. * Print a safe exception error message.
  194. */
  195. static inline
  196. void d_safe_exception(const char* const exception, const char* const file, const int line) noexcept
  197. {
  198. d_stderr2("exception caught: \"%s\" in file %s, line %i", exception, file, line);
  199. }
  200. // -----------------------------------------------------------------------
  201. // math functions
  202. /*
  203. * Safely compare two floating point numbers.
  204. * Returns true if they match.
  205. */
  206. template<typename T>
  207. static inline
  208. bool d_isEqual(const T& v1, const T& v2)
  209. {
  210. return std::abs(v1-v2) < std::numeric_limits<T>::epsilon();
  211. }
  212. /*
  213. * Safely compare two floating point numbers.
  214. * Returns true if they don't match.
  215. */
  216. template<typename T>
  217. static inline
  218. bool d_isNotEqual(const T& v1, const T& v2)
  219. {
  220. return std::abs(v1-v2) >= std::numeric_limits<T>::epsilon();
  221. }
  222. /*
  223. * Safely check if a floating point number is zero.
  224. */
  225. template<typename T>
  226. static inline
  227. bool d_isZero(const T& value)
  228. {
  229. return std::abs(value) < std::numeric_limits<T>::epsilon();
  230. }
  231. /*
  232. * Safely check if a floating point number is not zero.
  233. */
  234. template<typename T>
  235. static inline
  236. bool d_isNotZero(const T& value)
  237. {
  238. return std::abs(value) >= std::numeric_limits<T>::epsilon();
  239. }
  240. /*
  241. * Get next power of 2.
  242. */
  243. static inline
  244. uint32_t d_nextPowerOf2(uint32_t size) noexcept
  245. {
  246. DISTRHO_SAFE_ASSERT_RETURN(size > 0, 0);
  247. // http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
  248. --size;
  249. size |= size >> 1;
  250. size |= size >> 2;
  251. size |= size >> 4;
  252. size |= size >> 8;
  253. size |= size >> 16;
  254. return ++size;
  255. }
  256. // -----------------------------------------------------------------------
  257. #ifndef DONT_SET_USING_DISTRHO_NAMESPACE
  258. // If your code uses a lot of DISTRHO classes, then this will obviously save you
  259. // a lot of typing, but can be disabled by setting DONT_SET_USING_DISTRHO_NAMESPACE.
  260. namespace DISTRHO_NAMESPACE {}
  261. using namespace DISTRHO_NAMESPACE;
  262. #endif
  263. // -----------------------------------------------------------------------
  264. #endif // DISTRHO_UTILS_HPP_INCLUDED