OSSIA
Open Scenario System for Interactive Application
network/dataspace/gain.hpp
1 #pragma once
2 #include <ossia/network/dataspace/dataspace_base.hpp>
3 #include <ossia/network/domain/domain_base_impl.hpp>
4 
5 namespace ossia
6 {
7 struct linear_u;
8 struct gain_u;
9 template <typename Impl>
10 struct gain_unit
11 {
12  using is_unit = std::true_type;
13  using neutral_unit = linear_u;
14  using value_type = float;
15  using concrete_type = Impl;
16  using dataspace_type = gain_u;
17  using is_multidimensional = std::false_type;
18 };
19 
21 namespace detail
22 {
23 template <typename T>
24 static const constexpr T DecibelHeadroom = 96.;
25 /*
26 template<typename T>
27 const T GainMidiPower
28  = std::log(ossia::log1p(T(12.) / DecibelHeadroom<T>) / std::log(T(127. /
29 100.))) / std::log(T(2.));
30 
31 template<typename T>
32 const T GainMidiPowPow2 = ossia::exp2(GainMidiPower<T>);
33 */
34 template <typename T>
35 static const constexpr T GainMidiPower = -1.02098087016161476192621649;
36 
37 template <typename T>
38 static const constexpr T GainMidiPowPow2 = 0.492781202603372214809951402;
39 
40 template <typename T>
41 T LinearGainToDecibels(const T value)
42 {
43  return value >= T(0.) ? T(20.0) * std::log10(value) : T(0.);
44 }
45 
46 template <typename T>
47 T LinearGainToDecibelsClipped(const T value)
48 {
49  return value <= T(0.) ? -DecibelHeadroom<T>
50  : ossia::max(T(20.0) * std::log10(value), -DecibelHeadroom<T>);
51 }
52 
53 template <typename T>
54 T DecibelsToLinearGain(const T value)
55 {
56  return std::pow(T(10.), value * T(0.05));
57 }
58 
59 template <typename T>
60 T DecibelsToLinearGainClipped(const T value)
61 {
62  return value <= -DecibelHeadroom<T> ? T(0.) : DecibelsToLinearGain(value);
63 }
64 
65 template <typename T>
66 T MidiToLinearGain(const T value)
67 {
68  return value <= T(0.)
69  ? T(0.)
70  : DecibelsToLinearGainClipped(
71  DecibelHeadroom<
72  T> * (std::pow(value / T(100.), GainMidiPowPow2<T>) - T(1.)));
73 }
74 
75 template <typename T>
76 T DecibelsToMidi(const T value)
77 {
78  return value <= -DecibelHeadroom<T>
79  ? T(0.)
80  : T(100.)
81  * std::exp(
82  ossia::log1p(value / DecibelHeadroom<T>) / GainMidiPowPow2<T>);
83 }
84 
85 template <typename T>
86 T LinearGainToMidi(const T value)
87 {
88  return DecibelsToMidi(LinearGainToDecibels(value));
89 }
90 }
91 
92 struct OSSIA_EXPORT linear_u : public gain_unit<linear_u>
93 {
94  static constexpr auto text() { constexpr_return(ossia::make_string_array("linear")); }
95 
96  static constexpr strong_value<neutral_unit>
97  to_neutral(strong_value<concrete_type> self)
98  {
99  return self;
100  }
101 
102  static constexpr value_type from_neutral(strong_value<neutral_unit> self)
103  {
104  return self.dataspace_value;
105  }
106 
107  static ossia::domain_base<float> domain() { return {0.f, 1.f}; }
108 
109  static constexpr auto bounding() { return ossia::bounding_mode::LOW; }
110 };
111 
112 struct OSSIA_EXPORT midigain_u : public gain_unit<midigain_u>
113 {
114  static constexpr auto text()
115  {
116  constexpr_return(ossia::make_string_array("midigain"));
117  }
118 
119  static strong_value<neutral_unit> to_neutral(strong_value<concrete_type> self)
120  {
121  return detail::MidiToLinearGain(self.dataspace_value);
122  }
123 
124  static value_type from_neutral(strong_value<neutral_unit> self)
125  {
126  return detail::LinearGainToMidi(self.dataspace_value);
127  }
128 
129  static ossia::domain_base<float> domain() { return {0.f, 127.f}; }
130 
131  static constexpr auto bounding() { return ossia::bounding_mode::LOW; }
132 };
133 
134 struct OSSIA_EXPORT decibel_u : public gain_unit<decibel_u>
135 {
136  static constexpr auto text()
137  {
138  constexpr_return(ossia::make_string_array("db", "dB"));
139  }
140 
141  static strong_value<neutral_unit> to_neutral(strong_value<concrete_type> self)
142  {
143  return detail::DecibelsToLinearGainClipped(self.dataspace_value);
144  }
145 
146  static value_type from_neutral(strong_value<neutral_unit> self)
147  {
148  return detail::LinearGainToDecibelsClipped(self.dataspace_value);
149  }
150 
151  static ossia::domain_base<float> domain() { return {-96.f, 12.f}; }
152 
153  static constexpr auto bounding() { return ossia::bounding_mode::LOW; }
154 };
155 
156 struct OSSIA_EXPORT decibel_raw_u : public gain_unit<decibel_raw_u>
157 {
158  static constexpr auto text()
159  {
160  constexpr_return(ossia::make_string_array("db-raw", "dB-raw"));
161  }
162 
163  static strong_value<neutral_unit> to_neutral(strong_value<concrete_type> self)
164  {
165  return detail::DecibelsToLinearGain(self.dataspace_value);
166  }
167 
168  static value_type from_neutral(strong_value<neutral_unit> self)
169  {
170  return 20.0f * std::log10(self.dataspace_value);
171  }
172 
173  static ossia::domain_base<float> domain() { return {-96.f, 12.f}; }
174 
175  static constexpr auto bounding() { return ossia::bounding_mode::FREE; }
176 };
177 }
Definition: git_info.h:7
constexpr OSSIA_INLINE auto max(const T a, const U b) noexcept -> typename std::conditional<(sizeof(T) > sizeof(U)), T, U >::type
max function tailored for values
Definition: math.hpp:96