HART  0.2.0
High level Audio Regression and Testing
Loading...
Searching...
No Matches
hart_utils.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <algorithm> // min(), max()
4#include <cctype> // isalpha()
5#include <cmath> // pow()
6#include <exception>
7#include <limits> // infinity(), nan()
8#include <memory>
9#include <ostream>
10#include <string>
11#include <unordered_map>
12
14
15namespace hart
16{
17
18/// @defgroup Utilities Utilities
19/// @brief Handy functions and constants
20/// @{
21
22/// @brief Infinity
23constexpr double inf = std::numeric_limits<double>::infinity();
24
25/// @brief Infinity
26constexpr double oo = inf;
27
28/// @brief pi
29constexpr double pi = 3.14159265358979323846;
30
31/// @brief 2 * pi
32constexpr double twoPi = 2.0 * pi;
33
34/// @brief pi / 2
35constexpr double halfPi = pi / 2.0;
36
37/// @brief Helper values for channel indices
39{
40 left = 0,
41 right = 1
42};
43
44/// @brief Helper values for mid-side channel indices
46{
47 mid = 0,
48 side = 1
49};
50
51/// @brief Helper values for something that could loop, like a Signal
52enum class Loop
53{
54 no,
55 yes
56};
57
58/// @brief Oversampling ratio
60{
61 x4 = 4,
62 x8 = 8,
63 x16 = 16
64};
65
66/// @brief @brief Interpolation method
67enum class Interpolation
68{
69 nearest,
70 linear
71};
72
73inline std::ostream& operator<< (std::ostream& os, Oversampling oversampling)
74{
75 return os << "Oversampling::x" << static_cast<int> (oversampling);
76}
77
78/// @brief Returns a quiet NaN value for the given floating-point type.
79template<typename FloatType>
80inline FloatType nan()
81{
82 return std::numeric_limits<FloatType>::quiet_NaN();
83}
84
85/// @brief `std::clamp()` replacement for C++11
86template <typename NumericType>
87NumericType clamp (const NumericType& value, const NumericType& low, const NumericType& high)
88{
89 return std::min<NumericType> (std::max<NumericType> (value, low), high);
90}
91
92/// @brief Converts dB to linear value (ratio)
93/// @param valueDb Value in decibels
94/// @return Value in linear domain
95template <typename SampleType>
96inline static SampleType decibelsToRatio (SampleType valueDb)
97{
98 if (valueDb < -120)
99 return 0;
100
101 return std::pow (static_cast<SampleType> (10), valueDb / static_cast<SampleType> (20));
102}
103
104/// @brief Converts linear value (ratio) to dB
105/// @param valueLinear Value in linear domain
106/// @return Value in decibels
107template <typename SampleType>
108inline static SampleType ratioToDecibels (SampleType valueLinear)
109{
110 if (valueLinear < 1e-6)
111 return -120;
112
113 return static_cast<SampleType> (20 * std::log10 (valueLinear));
114}
115
116/// @brief Converts dB to linear value (power)
117/// @param valueDb Value in decibels
118/// @return Value in linear domain
119template <typename SampleType>
120inline static SampleType decibelsToPower (SampleType valueDb)
121{
122 if (valueDb < -120)
123 return 0;
124
125 return std::pow (static_cast<SampleType> (10), valueDb / static_cast<SampleType> (10));
126}
127
128/// @brief Converts linear value (power) to dB
129/// @param valueLinear Value in linear domain
130/// @return Value in decibels
131template <typename SampleType>
132inline static SampleType powerToDecibels (SampleType valueLinear)
133{
134 if (valueLinear < 1e-12)
135 return -120;
136
137 return static_cast<SampleType> (10 * std::log10 (valueLinear));
138}
139
140/// @brief Compares two floating point numbers within a given tolerance
141template <typename SampleType>
142inline static SampleType floatsEqual (SampleType a, SampleType b, SampleType epsilon = (SampleType) 1e-8)
143{
144 return std::abs (a - b) < epsilon;
145}
146
147/// @brief Compares two floating point numbers within a given tolerance
148template <typename SampleType>
149inline static SampleType floatsNotEqual (SampleType a, SampleType b, SampleType epsilon = (SampleType) 1e-8)
150{
151 return std::abs (a - b) >= epsilon;
152}
153
154/// @brief Rounds a floating point value to a `size_t` value
155template <typename SampleType>
156inline static size_t roundToSizeT (SampleType x)
157{
158 return static_cast<size_t> (x + (SampleType) 0.5);
159}
160
161/// @brief Anns an offset in cents to a frequency in Hz
162inline double addCents (double baseFrequencyHz, double cents)
163{
164 return baseFrequencyHz * std::pow (2.0, cents / 1200.0);
165}
166
167/// @brief Keeps phase in 0..twoPi range
168template <typename SampleType>
169SampleType wrapPhase (const SampleType phaseRadians)
170{
171 SampleType wrappedPhaseRadians = std::remainder (phaseRadians, (SampleType) hart::twoPi);
172
173 if (wrappedPhaseRadians < 0.0)
174 wrappedPhaseRadians += hart::twoPi;
175
176 return wrappedPhaseRadians;
177}
178
179/// @brief Checks if the provided file path is absolute
180inline static bool isAbsolutePath (const std::string& path)
181{
182 if (path.empty())
183 return false;
184
185 if (path[0] == '/' || path[0] == '\\')
186 return true;
187
188 #ifdef _WIN32
189 if (path.size() > 1 && std::isalpha (path[0]) && path[1] == ':')
190 return true;
191 #endif
192
193 return false;
194}
195
196/// @brief Converts path to absolute, if it's relative
197/// @details Relative paths are resolved based on a provided `--data-root-path` CLI argument
198inline static std::string toAbsolutePath (const std::string& path)
199{
200 if (isAbsolutePath(path))
201 return path;
202
204}
205
206/// @brief `std::unordered_map::contains()` replacement for C++11
207template <typename KeyType, typename ValueType>
208inline static bool contains (const std::unordered_map<KeyType, ValueType>& map, const KeyType& key)
209{
210 return map.find (key) != map.end();
211}
212
213/// @brief `std::make_unique()` replacement for C++11
214/// @details For C++11 compatibility only. If you're one C++14 or later, just use STL version.
215template<typename ObjectType, typename... Args>
216std::unique_ptr<ObjectType> make_unique (Args&&... args)
217{
218 return std::unique_ptr<ObjectType> (new ObjectType (std::forward<Args> (args)...));
219}
220
221/// @brief Returns `true` if an exception is currently being unwound
222inline static bool isExceptionUnwinding()
223{
224#if defined(__cpp_lib_uncaught_exceptions)
225 return std::uncaught_exceptions() > 0;
226#else
227 return std::uncaught_exception();
228#endif
229}
230
231/// @brief Defines a basic string representation of your class
232/// @details If your class takes ctor arguments, it's strongly encouraged to make a proper
233/// implementation of `represent()`, so that you get more detailed test failure reports.
234/// See @ref hart::DSP::represent(), @ref hart::Matcher::represent(),
235/// @ref hart::Signal::represent() for the description.
236#define HART_DEFINE_GENERIC_REPRESENT(ClassName)
237 virtual void represent(std::ostream& stream) const override
238 {
239 stream << #ClassName "()";
240 }
241
242/// @private
243#if defined(__GNUC__) || defined(__clang__)
244 #define HART_DEPRECATED(msg) __attribute__((deprecated(msg)))
245#elif defined(_MSC_VER)
246 #define HART_DEPRECATED(msg) __declspec(deprecated(msg))
247#else
248 #define HART_DEPRECATED(msg)
249#endif
250
251} // namespace hart
constexpr double twoPi
2 * pi
static bool isAbsolutePath(const std::string &path)
Checks if the provided file path is absolute.
FloatType nan()
Returns a quiet NaN value for the given floating-point type.
Channel
Helper values for channel indices.
SampleType wrapPhase(const SampleType phaseRadians)
Keeps phase in 0..twoPi range.
static bool contains(const std::unordered_map< KeyType, ValueType > &map, const KeyType &key)
std::unordered_map::contains() replacement for C++11
constexpr double halfPi
pi / 2
static size_t roundToSizeT(SampleType x)
Rounds a floating point value to a size_t value.
constexpr double inf
Infinity.
static SampleType ratioToDecibels(SampleType valueLinear)
Converts linear value (ratio) to dB.
static SampleType floatsNotEqual(SampleType a, SampleType b, SampleType epsilon=(SampleType) 1e-8)
Compares two floating point numbers within a given tolerance.
MidSideChannel
Helper values for mid-side channel indices.
Interpolation
Interpolation method.
std::unique_ptr< ObjectType > make_unique(Args &&... args)
std::make_unique() replacement for C++11
static SampleType powerToDecibels(SampleType valueLinear)
Converts linear value (power) to dB.
double addCents(double baseFrequencyHz, double cents)
Anns an offset in cents to a frequency in Hz.
NumericType clamp(const NumericType &value, const NumericType &low, const NumericType &high)
std::clamp() replacement for C++11
constexpr double oo
Infinity.
static std::string toAbsolutePath(const std::string &path)
Converts path to absolute, if it's relative.
static SampleType decibelsToRatio(SampleType valueDb)
Converts dB to linear value (ratio)
static bool isExceptionUnwinding()
Returns true if an exception is currently being unwound.
constexpr double pi
pi
static SampleType floatsEqual(SampleType a, SampleType b, SampleType epsilon=(SampleType) 1e-8)
Compares two floating point numbers within a given tolerance.
static SampleType decibelsToPower(SampleType valueDb)
Converts dB to linear value (power)
Oversampling
Oversampling ratio.
Loop
Helper values for something that could loop, like a Signal.
Holds values set by the user via CLI interface.
std::string getDataRootPath()
Get data root path set by a "`--data-root-path`,`-d`" argument.
static CLIConfig & getInstance()
Get the singleton instance.