1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
2
3 /*
4 Rosegarden
5 A sequencer and musical notation editor.
6 Copyright 2000-2021 the Rosegarden development team.
7 See the AUTHORS file for more details.
8
9 This program is free software; you can redistribute it and/or
10 modify it under the terms of the GNU General Public License as
11 published by the Free Software Foundation; either version 2 of the
12 License, or (at your option) any later version. See the file
13 COPYING included with this distribution for more information.
14 */
15
16 #include "base/AudioLevel.h"
17 #include <cmath>
18 #include <iostream>
19 #include <map>
20 #include <vector>
21
22 namespace Rosegarden {
23
24 struct FaderDescription
25 {
FaderDescriptionRosegarden::FaderDescription26 FaderDescription(float i_minDb, float i_maxDb, float i_zeroPoint) :
27 minDb(i_minDb), maxDb(i_maxDb), zeroPoint(i_zeroPoint) { }
28
29 float minDb;
30 float maxDb;
31 float zeroPoint; // as fraction of total throw
32 };
33
34 static const FaderDescription faderTypes[] = {
35 FaderDescription(-40.0, +6.0, 0.75), // short
36 FaderDescription(-70.0, +10.0, 0.80), // long
37 FaderDescription(-70.0, 0.0, 1.00), // IEC268
38 FaderDescription(-70.0, +10.0, 0.80), // IEC268 long
39 FaderDescription(-40.0, 0.0, 1.00), // preview
40 };
41
42 typedef std::vector<float> LevelList;
43 static std::map<int, LevelList> previewLevelCache;
44 static const LevelList &getPreviewLevelCache(int levels);
45
46 float
multiplier_to_dB(float multiplier)47 AudioLevel::multiplier_to_dB(float multiplier)
48 {
49 if (multiplier == 0.0) return DB_FLOOR;
50 float dB = 10 * log10f(multiplier);
51 return dB;
52 }
53
54 float
dB_to_multiplier(float dB)55 AudioLevel::dB_to_multiplier(float dB)
56 {
57 if (dB == DB_FLOOR) return 0.0;
58 float m = powf(10.0, dB / 10.0);
59 return m;
60 }
61
62 /* IEC 60-268-18 fader levels. Thanks to Steve Harris. */
63
iec_dB_to_fader(float db)64 static float iec_dB_to_fader(float db)
65 {
66 float def = 0.0f; // Meter deflection %age
67
68 if (db < -70.0f) {
69 def = 0.0f;
70 } else if (db < -60.0f) {
71 def = (db + 70.0f) * 0.25f;
72 } else if (db < -50.0f) {
73 def = (db + 60.0f) * 0.5f + 2.5f; // corrected from 5.0f base, thanks Robin Gareus
74 } else if (db < -40.0f) {
75 def = (db + 50.0f) * 0.75f + 7.5f;
76 } else if (db < -30.0f) {
77 def = (db + 40.0f) * 1.5f + 15.0f;
78 } else if (db < -20.0f) {
79 def = (db + 30.0f) * 2.0f + 30.0f;
80 } else {
81 def = (db + 20.0f) * 2.5f + 50.0f;
82 }
83
84 return def;
85 }
86
iec_fader_to_dB(float def)87 static float iec_fader_to_dB(float def) // Meter deflection %age
88 {
89 float db = 0.0f;
90
91 if (def >= 50.0f) {
92 db = (def - 50.0f) / 2.5f - 20.0f;
93 } else if (def >= 30.0f) {
94 db = (def - 30.0f) / 2.0f - 30.0f;
95 } else if (def >= 15.0f) {
96 db = (def - 15.0f) / 1.5f - 40.0f;
97 } else if (def >= 7.5f) {
98 db = (def - 7.5f) / 0.75f - 50.0f;
99 } else if (def >= 2.5f) {
100 db = (def - 2.5f) / 0.5f - 60.0f;
101 } else {
102 db = (def / 0.25f) - 70.0f;
103 }
104
105 return db;
106 }
107
108 float
fader_to_dB(int level,int maxLevel,FaderType type)109 AudioLevel::fader_to_dB(int level, int maxLevel, FaderType type)
110 {
111 if (level == 0) return DB_FLOOR;
112
113 if (type == IEC268Meter || type == IEC268LongMeter) {
114
115 float maxPercent = iec_dB_to_fader(faderTypes[type].maxDb);
116 float percent = float(level) * maxPercent / float(maxLevel);
117 float dB = iec_fader_to_dB(percent);
118 return dB;
119
120 } else { // scale proportional to sqrt(fabs(dB))
121
122 int zeroLevel = int(maxLevel * faderTypes[type].zeroPoint);
123
124 if (level >= zeroLevel) {
125
126 float value = level - zeroLevel;
127 float scale = float(maxLevel - zeroLevel) /
128 sqrtf(faderTypes[type].maxDb);
129 value /= scale;
130 float dB = powf(value, 2.0);
131 return dB;
132
133 } else {
134
135 float value = zeroLevel - level;
136 float scale = zeroLevel / sqrtf(0.0 - faderTypes[type].minDb);
137 value /= scale;
138 float dB = powf(value, 2.0);
139 return 0.0 - dB;
140 }
141 }
142 }
143
144
145 int
dB_to_fader(float dB,int maxLevel,FaderType type)146 AudioLevel::dB_to_fader(float dB, int maxLevel, FaderType type)
147 {
148 if (dB == DB_FLOOR) return 0;
149
150 if (type == IEC268Meter || type == IEC268LongMeter) {
151
152 // The IEC scale gives a "percentage travel" for a given dB
153 // level, but it reaches 100% at 0dB. So we want to treat the
154 // result not as a percentage, but as a scale between 0 and
155 // whatever the "percentage" for our (possibly >0dB) max dB is.
156
157 float maxPercent = iec_dB_to_fader(faderTypes[type].maxDb);
158 float percent = iec_dB_to_fader(dB);
159 int faderLevel = int((maxLevel * percent) / maxPercent + 0.01);
160
161 if (faderLevel < 0) faderLevel = 0;
162 if (faderLevel > maxLevel) faderLevel = maxLevel;
163 return faderLevel;
164
165 } else {
166
167 int zeroLevel = int(maxLevel * faderTypes[type].zeroPoint);
168
169 if (dB >= 0.0) {
170
171 float value = sqrtf(dB);
172 float scale = (maxLevel - zeroLevel) / sqrtf(faderTypes[type].maxDb);
173 value *= scale;
174 int level = int(value + 0.01) + zeroLevel;
175 if (level > maxLevel) level = maxLevel;
176 return level;
177
178 } else {
179
180 dB = 0.0 - dB;
181 float value = sqrtf(dB);
182 float scale = zeroLevel / sqrtf(0.0 - faderTypes[type].minDb);
183 value *= scale;
184 int level = zeroLevel - int(value + 0.01);
185 if (level < 0) level = 0;
186 return level;
187 }
188 }
189 }
190
191
192 float
fader_to_multiplier(int level,int maxLevel,FaderType type)193 AudioLevel::fader_to_multiplier(int level, int maxLevel, FaderType type)
194 {
195 if (level == 0) return 0.0;
196 return dB_to_multiplier(fader_to_dB(level, maxLevel, type));
197 }
198
199 int
multiplier_to_fader(float multiplier,int maxLevel,FaderType type)200 AudioLevel::multiplier_to_fader(float multiplier, int maxLevel, FaderType type)
201 {
202 if (multiplier == 0.0) return 0;
203 float dB = multiplier_to_dB(multiplier);
204 int fader = dB_to_fader(dB, maxLevel, type);
205 return fader;
206 }
207
208
209 const LevelList &
getPreviewLevelCache(int levels)210 getPreviewLevelCache(int levels)
211 {
212 LevelList &ll = previewLevelCache[levels];
213 if (ll.empty()) {
214 for (int i = 0; i <= levels; ++i) {
215 float m = AudioLevel::fader_to_multiplier
216 (i, levels, AudioLevel::PreviewLevel);
217 if (levels == 1) m /= 100; // noise
218 ll.push_back(m);
219 }
220 }
221 return ll;
222 }
223
224 int
multiplier_to_preview(float m,int levels)225 AudioLevel::multiplier_to_preview(float m, int levels)
226 {
227 const LevelList &ll = getPreviewLevelCache(levels);
228 int result = -1;
229
230 int lo = 0, hi = levels;
231
232 // binary search
233 int level = -1;
234 while (result < 0) {
235 int newlevel = (lo + hi) / 2;
236 if (newlevel == level ||
237 newlevel == 0 ||
238 newlevel == levels) {
239 result = newlevel;
240 break;
241 }
242 level = newlevel;
243 if (ll[level] >= m) {
244 hi = level;
245 } else if (ll[level+1] >= m) {
246 result = level;
247 } else {
248 lo = level;
249 }
250 }
251
252 return result;
253 }
254
255 float
preview_to_multiplier(int level,int levels)256 AudioLevel::preview_to_multiplier(int level, int levels)
257 {
258 const LevelList &ll = getPreviewLevelCache(levels);
259 return ll[level];
260 }
261
262 int AudioLevel::m_panLaw = 0;
263
264 float
panGainLeft(float pan)265 AudioLevel::panGainLeft(float pan) // Apply panning law to left channel
266 {
267 if (m_panLaw == 3) {
268 // -3dB Panning Law (variant)
269 //
270 // This law has the same characteristics as the -3dB law described
271 // below, except that a channel's gain begins at +3dB and decreases to
272 // 0dB as the control is moved through the center position. This
273 // setting must be used with caution, as the increased edge gains could
274 // introduce clipping.
275 //
276 return sqrtf(fabsf((100.0 - pan) / 100.0)); // -3dB pan law (variant)
277
278 } else if (m_panLaw == 2) {
279 // -6dB Panning Law
280 //
281 // A channel's gain begins at 0dB and decreases to -6dB as the control
282 // is moved to the center. From there on the signal continues to
283 // decrease until it is completely attenuated at the opposite edge.
284 // The 3dB dip in the combined power of both channels when the control
285 // is centered will cause the extremes to sound louder than the center.
286 //
287 return (100.0 - pan) / 200.0;
288
289 } else if (m_panLaw == 1) {
290 // -3dB Panning Law
291 //
292 // A channel's gain begins at 0dB and decreases to -3dB as the control
293 // is centered. From there on the signal continues to decrease until
294 // it is completely attenuated at the opposite edge. The combined
295 // power of both channels remains constant throughout the panning
296 // range, resulting in an apparent constant loudness.
297 //
298 return sqrtf(fabsf((100.0 - pan) / 200.0));
299
300 } else {
301 // OdB Panning Law (default)
302 //
303 // A channel's gain begins at 0dB and remains at 0dB as the control is
304 // moved to the the center. From there on the signal decreases
305 // linearly till it is completely attenuated at the opposite edge.
306 // Since both channels have a gain of 0dB at the center, the net
307 // effect is a 3dB boost in apparent loudness when the control is
308 // centered. This is a basic balance pot.
309 //
310 return (pan > 0.0) ? (100.0 - pan) / 100.0 : 1.0;
311
312 }
313 }
314
315 float
panGainRight(float pan)316 AudioLevel::panGainRight(float pan) // Apply panning law to right channel
317 {
318 if (m_panLaw == 3) {
319 return sqrtf(fabsf((100.0 + pan) / 100.0)); // -3dB pannig law (variant)
320
321 } else if (m_panLaw == 2) {
322 return (100.0 + pan) / 200.0; // -6dB pan law
323
324 } else if (m_panLaw == 1) {
325 return sqrtf(fabsf((100.0 + pan) / 200.0)); // -3dB panning law
326
327 } else {
328 return (pan < 0.0) ? (100.0 + pan) / 100.0 : 1.0; // 0dB panning law (default)
329
330 }
331 }
332
AudioPanD(MidiByte midiPan)333 double AudioLevel::AudioPanD(MidiByte midiPan)
334 {
335 // Scale 0-64 from 0 to 100.
336 if (midiPan <= 64)
337 return static_cast<double>(midiPan) / 64.0 * 100.0;
338
339 // Scale 64-127 from 100 to 200.
340 return static_cast<double>(midiPan - 1) / 63.0 * 100.0;
341 }
342
AudioPanI(MidiByte midiPan)343 int AudioLevel::AudioPanI(MidiByte midiPan)
344 {
345 // ??? A table would be faster.
346
347 // Scale 0-64 from 0 to 100.
348 if (midiPan <= 64) {
349 // Adding 32 (half of 64) to get proper rounding.
350 return (midiPan * 100 + 32) / 64;
351 }
352
353 // Scale 64-127 from 100 to 200.
354 // Adding 31 (half of 63 truncated) to get proper rounding.
355 return ((midiPan - 1) * 100 + 31) / 63;
356 }
357
MIDIPanI(int audioPan)358 MidiByte AudioLevel::MIDIPanI(int audioPan)
359 {
360 // Scale 0-100 to 0-64. (Add 50 to get proper rounding.)
361 if (audioPan <= 100)
362 return (audioPan * 64 + 50) / 100;
363
364 // Scale 100-200 to 64-127. (Add 50 to get proper rounding.)
365 return (audioPan * 63 + 50) / 100 + 1;
366 }
367
368
369 }
370