Mercurial > hg > svcore
comparison base/AudioLevel.cpp @ 1527:710e6250a401 zoom
Merge from default branch
author | Chris Cannam |
---|---|
date | Mon, 17 Sep 2018 13:51:14 +0100 |
parents | 71202259002d |
children | 3db9a9fc2612 |
comparison
equal
deleted
inserted
replaced
1324:d4a28d1479a8 | 1527:710e6250a401 |
---|---|
29 const double AudioLevel::DB_FLOOR = -1000.; | 29 const double AudioLevel::DB_FLOOR = -1000.; |
30 | 30 |
31 struct FaderDescription | 31 struct FaderDescription |
32 { | 32 { |
33 FaderDescription(double _minDb, double _maxDb, double _zeroPoint) : | 33 FaderDescription(double _minDb, double _maxDb, double _zeroPoint) : |
34 minDb(_minDb), maxDb(_maxDb), zeroPoint(_zeroPoint) { } | 34 minDb(_minDb), maxDb(_maxDb), zeroPoint(_zeroPoint) { } |
35 | 35 |
36 double minDb; | 36 double minDb; |
37 double maxDb; | 37 double maxDb; |
38 double zeroPoint; // as fraction of total throw | 38 double zeroPoint; // as fraction of total throw |
39 }; | 39 }; |
95 static double iec_fader_to_dB(double def) // Meter deflection %age | 95 static double iec_fader_to_dB(double def) // Meter deflection %age |
96 { | 96 { |
97 double db = 0.0f; | 97 double db = 0.0f; |
98 | 98 |
99 if (def >= 50.0f) { | 99 if (def >= 50.0f) { |
100 db = (def - 50.0f) / 2.5f - 20.0f; | 100 db = (def - 50.0f) / 2.5f - 20.0f; |
101 } else if (def >= 30.0f) { | 101 } else if (def >= 30.0f) { |
102 db = (def - 30.0f) / 2.0f - 30.0f; | 102 db = (def - 30.0f) / 2.0f - 30.0f; |
103 } else if (def >= 15.0f) { | 103 } else if (def >= 15.0f) { |
104 db = (def - 15.0f) / 1.5f - 40.0f; | 104 db = (def - 15.0f) / 1.5f - 40.0f; |
105 } else if (def >= 7.5f) { | 105 } else if (def >= 7.5f) { |
106 db = (def - 7.5f) / 0.75f - 50.0f; | 106 db = (def - 7.5f) / 0.75f - 50.0f; |
107 } else if (def >= 2.5f) { | 107 } else if (def >= 2.5f) { |
108 db = (def - 2.5f) / 0.5f - 60.0f; | 108 db = (def - 2.5f) / 0.5f - 60.0f; |
109 } else { | 109 } else { |
110 db = (def / 0.25f) - 70.0f; | 110 db = (def / 0.25f) - 70.0f; |
111 } | 111 } |
112 | 112 |
113 return db; | 113 return db; |
114 } | 114 } |
115 | 115 |
118 { | 118 { |
119 if (level == 0) return DB_FLOOR; | 119 if (level == 0) return DB_FLOOR; |
120 | 120 |
121 if (type == IEC268Meter || type == IEC268LongMeter) { | 121 if (type == IEC268Meter || type == IEC268LongMeter) { |
122 | 122 |
123 double maxPercent = iec_dB_to_fader(faderTypes[type].maxDb); | 123 double maxPercent = iec_dB_to_fader(faderTypes[type].maxDb); |
124 double percent = double(level) * maxPercent / double(maxLevel); | 124 double percent = double(level) * maxPercent / double(maxLevel); |
125 double dB = iec_fader_to_dB(percent); | 125 double dB = iec_fader_to_dB(percent); |
126 return dB; | 126 return dB; |
127 | 127 |
128 } else { // scale proportional to sqrt(fabs(dB)) | 128 } else { // scale proportional to sqrt(fabs(dB)) |
129 | 129 |
130 int zeroLevel = int(maxLevel * faderTypes[type].zeroPoint); | 130 int zeroLevel = int(round(maxLevel * faderTypes[type].zeroPoint)); |
131 | 131 |
132 if (level >= zeroLevel) { | 132 if (level >= zeroLevel) { |
133 | 133 |
134 double value = level - zeroLevel; | 134 double value = level - zeroLevel; |
135 double scale = (maxLevel - zeroLevel) / | 135 double scale = (maxLevel - zeroLevel) / |
136 sqrt(faderTypes[type].maxDb); | 136 sqrt(faderTypes[type].maxDb); |
137 value /= scale; | 137 value /= scale; |
138 double dB = pow(value, 2.); | 138 double dB = pow(value, 2.); |
139 return dB; | 139 return dB; |
140 | 140 |
141 } else { | 141 } else { |
142 | 142 |
143 double value = zeroLevel - level; | 143 double value = zeroLevel - level; |
144 double scale = zeroLevel / sqrt(0. - faderTypes[type].minDb); | 144 double scale = zeroLevel / sqrt(0. - faderTypes[type].minDb); |
145 value /= scale; | 145 value /= scale; |
146 double dB = pow(value, 2.); | 146 double dB = pow(value, 2.); |
147 return 0. - dB; | 147 return 0. - dB; |
148 } | 148 } |
149 } | 149 } |
150 } | 150 } |
151 | 151 |
152 | 152 |
153 int | 153 int |
155 { | 155 { |
156 if (dB == DB_FLOOR) return 0; | 156 if (dB == DB_FLOOR) return 0; |
157 | 157 |
158 if (type == IEC268Meter || type == IEC268LongMeter) { | 158 if (type == IEC268Meter || type == IEC268LongMeter) { |
159 | 159 |
160 // The IEC scale gives a "percentage travel" for a given dB | 160 // The IEC scale gives a "percentage travel" for a given dB |
161 // level, but it reaches 100% at 0dB. So we want to treat the | 161 // level, but it reaches 100% at 0dB. So we want to treat the |
162 // result not as a percentage, but as a scale between 0 and | 162 // result not as a percentage, but as a scale between 0 and |
163 // whatever the "percentage" for our (possibly >0dB) max dB is. | 163 // whatever the "percentage" for our (possibly >0dB) max dB is. |
164 | 164 |
165 double maxPercent = iec_dB_to_fader(faderTypes[type].maxDb); | 165 double maxPercent = iec_dB_to_fader(faderTypes[type].maxDb); |
166 double percent = iec_dB_to_fader(dB); | 166 double percent = iec_dB_to_fader(dB); |
167 int faderLevel = int((maxLevel * percent) / maxPercent + 0.01f); | 167 int faderLevel = int((maxLevel * percent) / maxPercent + 0.01f); |
168 | 168 |
169 if (faderLevel < 0) faderLevel = 0; | 169 if (faderLevel < 0) faderLevel = 0; |
170 if (faderLevel > maxLevel) faderLevel = maxLevel; | 170 if (faderLevel > maxLevel) faderLevel = maxLevel; |
171 return faderLevel; | 171 return faderLevel; |
172 | 172 |
173 } else { | 173 } else { |
174 | 174 |
175 int zeroLevel = int(maxLevel * faderTypes[type].zeroPoint); | 175 int zeroLevel = int(round(maxLevel * faderTypes[type].zeroPoint)); |
176 | 176 |
177 if (dB >= 0.) { | 177 if (dB >= 0.) { |
178 | 178 |
179 if (faderTypes[type].maxDb <= 0.) { | 179 if (faderTypes[type].maxDb <= 0.) { |
180 | 180 |
181 return maxLevel; | 181 return maxLevel; |
182 | 182 |
183 } else { | 183 } else { |
187 value *= scale; | 187 value *= scale; |
188 int level = int(value + 0.01f) + zeroLevel; | 188 int level = int(value + 0.01f) + zeroLevel; |
189 if (level > maxLevel) level = maxLevel; | 189 if (level > maxLevel) level = maxLevel; |
190 return level; | 190 return level; |
191 } | 191 } |
192 | 192 |
193 } else { | 193 } else { |
194 | 194 |
195 dB = 0. - dB; | 195 dB = 0. - dB; |
196 double value = sqrt(dB); | 196 double value = sqrt(dB); |
197 double scale = zeroLevel / sqrt(0. - faderTypes[type].minDb); | 197 double scale = zeroLevel / sqrt(0. - faderTypes[type].minDb); |
198 value *= scale; | 198 value *= scale; |
199 int level = zeroLevel - int(value + 0.01f); | 199 int level = zeroLevel - int(value + 0.01f); |
200 if (level < 0) level = 0; | 200 if (level < 0) level = 0; |
201 return level; | 201 return level; |
202 } | 202 } |
203 } | 203 } |
204 } | 204 } |
205 | 205 |
206 | 206 |
207 double | 207 double |
208 AudioLevel::fader_to_multiplier(int level, int maxLevel, FaderType type) | 208 AudioLevel::fader_to_multiplier(int level, int maxLevel, FaderType type) |
209 { | 209 { |
210 if (level == 0) return 0.; | 210 if (level == 0) return 0.; |
211 return dB_to_multiplier(fader_to_dB(level, maxLevel, type)); | 211 return dB_to_multiplier(fader_to_dB(level, maxLevel, type)); |
224 const LevelList & | 224 const LevelList & |
225 getPreviewLevelCache(int levels) | 225 getPreviewLevelCache(int levels) |
226 { | 226 { |
227 LevelList &ll = previewLevelCache[levels]; | 227 LevelList &ll = previewLevelCache[levels]; |
228 if (ll.empty()) { | 228 if (ll.empty()) { |
229 for (int i = 0; i <= levels; ++i) { | 229 for (int i = 0; i <= levels; ++i) { |
230 double m = AudioLevel::fader_to_multiplier | 230 double m = AudioLevel::fader_to_multiplier |
231 (i + levels/4, levels + levels/4, AudioLevel::PreviewLevel); | 231 (i + levels/4, levels + levels/4, AudioLevel::PreviewLevel); |
232 if (levels == 1) m /= 100; // noise | 232 if (levels == 1) m /= 100; // noise |
233 ll.push_back(m); | 233 ll.push_back(m); |
234 } | 234 } |
235 } | 235 } |
236 return ll; | 236 return ll; |
237 } | 237 } |
238 */ | 238 */ |
239 | 239 |
253 int lo = 0, hi = levels; | 253 int lo = 0, hi = levels; |
254 | 254 |
255 // binary search | 255 // binary search |
256 int level = -1; | 256 int level = -1; |
257 while (result < 0) { | 257 while (result < 0) { |
258 int newlevel = (lo + hi) / 2; | 258 int newlevel = (lo + hi) / 2; |
259 if (newlevel == level || | 259 if (newlevel == level || |
260 newlevel == 0 || | 260 newlevel == 0 || |
261 newlevel == levels) { | 261 newlevel == levels) { |
262 result = newlevel; | 262 result = newlevel; |
263 break; | 263 break; |
264 } | 264 } |
265 level = newlevel; | 265 level = newlevel; |
266 if (ll[level] >= m) { | 266 if (ll[level] >= m) { |
267 hi = level; | 267 hi = level; |
268 } else if (ll[level+1] >= m) { | 268 } else if (ll[level+1] >= m) { |
269 result = level; | 269 result = level; |
270 } else { | 270 } else { |
271 lo = level; | 271 lo = level; |
272 } | 272 } |
273 } | 273 } |
274 | 274 |
275 return result; | 275 return result; |
276 | 276 |
277 */ | 277 */ |
278 } | 278 } |
279 | 279 |
286 if (level < 0) return -preview_to_multiplier(-level, levels); | 286 if (level < 0) return -preview_to_multiplier(-level, levels); |
287 const LevelList &ll = getPreviewLevelCache(levels); | 287 const LevelList &ll = getPreviewLevelCache(levels); |
288 return ll[level]; | 288 return ll[level]; |
289 */ | 289 */ |
290 } | 290 } |
291 | 291 |
292 | 292 |