AudioLevel.cpp
Go to the documentation of this file.
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
2 
3 /*
4  Sonic Visualiser
5  An audio file viewer and annotation editor.
6  Centre for Digital Music, Queen Mary, University of London.
7 
8  This program is free software; you can redistribute it and/or
9  modify it under the terms of the GNU General Public License as
10  published by the Free Software Foundation; either version 2 of the
11  License, or (at your option) any later version. See the file
12  COPYING included with this distribution for more information.
13 */
14 
15 /*
16  This is a modified version of a source file from the
17  Rosegarden MIDI and audio sequencer and notation editor.
18  This file copyright 2000-2006 Chris Cannam.
19 */
20 
21 #include "AudioLevel.h"
22 #include <cmath>
23 #include <iostream>
24 #include <map>
25 #include <vector>
26 #include <cassert>
27 #include "system/System.h"
28 
29 const double AudioLevel::DB_FLOOR = -1000.;
30 
32 {
33  FaderDescription(double _minDb, double _maxDb, double _zeroPoint) :
34  minDb(_minDb), maxDb(_maxDb), zeroPoint(_zeroPoint) { }
35 
36  double minDb;
37  double maxDb;
38  double zeroPoint; // as fraction of total throw
39 };
40 
41 static const FaderDescription faderTypes[] = {
42  FaderDescription(-40., +6., 0.75), // short
43  FaderDescription(-70., +10., 0.80), // long
44  FaderDescription(-70., 0., 1.00), // IEC268
45  FaderDescription(-70., +10., 0.80), // IEC268 long
46  FaderDescription(-40., 0., 1.00), // preview
47 };
48 
49 double
50 AudioLevel::multiplier_to_dB(double multiplier)
51 {
52  if (multiplier == 0.) return DB_FLOOR;
53  else if (multiplier < 0.) return multiplier_to_dB(-multiplier);
54  double dB = 10 * log10(multiplier);
55  return dB;
56 }
57 
58 double
60 {
61  if (dB == DB_FLOOR) return 0.;
62  double m = pow(10., dB / 10.);
63  return m;
64 }
65 
66 /* IEC 60-268-18 fader levels. Thanks to Steve Harris. */
67 
68 static double iec_dB_to_fader(double db)
69 {
70  double def = 0.0f; // Meter deflection %age
71 
72  if (db < -70.0f) {
73  def = 0.0f;
74  } else if (db < -60.0f) {
75  def = (db + 70.0f) * 0.25f;
76  } else if (db < -50.0f) {
77  def = (db + 60.0f) * 0.5f + 2.5f; // corrected from 5.0f base, thanks Robin Gareus
78  } else if (db < -40.0f) {
79  def = (db + 50.0f) * 0.75f + 7.5f;
80  } else if (db < -30.0f) {
81  def = (db + 40.0f) * 1.5f + 15.0f;
82  } else if (db < -20.0f) {
83  def = (db + 30.0f) * 2.0f + 30.0f;
84  } else {
85  def = (db + 20.0f) * 2.5f + 50.0f;
86  }
87 
88  return def;
89 }
90 
91 static double iec_fader_to_dB(double def) // Meter deflection %age
92 {
93  double db = 0.0f;
94 
95  if (def >= 50.0f) {
96  db = (def - 50.0f) / 2.5f - 20.0f;
97  } else if (def >= 30.0f) {
98  db = (def - 30.0f) / 2.0f - 30.0f;
99  } else if (def >= 15.0f) {
100  db = (def - 15.0f) / 1.5f - 40.0f;
101  } else if (def >= 7.5f) {
102  db = (def - 7.5f) / 0.75f - 50.0f;
103  } else if (def >= 2.5f) {
104  db = (def - 2.5f) / 0.5f - 60.0f;
105  } else {
106  db = (def / 0.25f) - 70.0f;
107  }
108 
109  return db;
110 }
111 
112 double
113 AudioLevel::fader_to_dB(int level, int maxLevel, FaderType type)
114 {
115  if (level == 0) return DB_FLOOR;
116 
117  if (type == IEC268Meter || type == IEC268LongMeter) {
118 
119  double maxPercent = iec_dB_to_fader(faderTypes[type].maxDb);
120  double percent = double(level) * maxPercent / double(maxLevel);
121  double dB = iec_fader_to_dB(percent);
122  return dB;
123 
124  } else { // scale proportional to sqrt(fabs(dB))
125 
126  int zeroLevel = int(round(maxLevel * faderTypes[type].zeroPoint));
127 
128  if (level >= zeroLevel) {
129 
130  double value = level - zeroLevel;
131  double scale = (maxLevel - zeroLevel) /
132  sqrt(faderTypes[type].maxDb);
133  value /= scale;
134  double dB = pow(value, 2.);
135  return dB;
136 
137  } else {
138 
139  double value = zeroLevel - level;
140  double scale = zeroLevel / sqrt(0. - faderTypes[type].minDb);
141  value /= scale;
142  double dB = pow(value, 2.);
143  return 0. - dB;
144  }
145  }
146 }
147 
148 
149 int
150 AudioLevel::dB_to_fader(double dB, int maxLevel, FaderType type)
151 {
152  if (dB == DB_FLOOR) return 0;
153 
154  if (type == IEC268Meter || type == IEC268LongMeter) {
155 
156  // The IEC scale gives a "percentage travel" for a given dB
157  // level, but it reaches 100% at 0dB. So we want to treat the
158  // result not as a percentage, but as a scale between 0 and
159  // whatever the "percentage" for our (possibly >0dB) max dB is.
160 
161  double maxPercent = iec_dB_to_fader(faderTypes[type].maxDb);
162  double percent = iec_dB_to_fader(dB);
163  int faderLevel = int((maxLevel * percent) / maxPercent + 0.01f);
164 
165  if (faderLevel < 0) faderLevel = 0;
166  if (faderLevel > maxLevel) faderLevel = maxLevel;
167  return faderLevel;
168 
169  } else {
170 
171  int zeroLevel = int(round(maxLevel * faderTypes[type].zeroPoint));
172 
173  if (dB >= 0.) {
174 
175  if (faderTypes[type].maxDb <= 0.) {
176 
177  return maxLevel;
178 
179  } else {
180 
181  double value = sqrt(dB);
182  double scale = (maxLevel - zeroLevel) / sqrt(faderTypes[type].maxDb);
183  value *= scale;
184  int level = int(value + 0.01f) + zeroLevel;
185  if (level > maxLevel) level = maxLevel;
186  return level;
187  }
188 
189  } else {
190 
191  dB = 0. - dB;
192  double value = sqrt(dB);
193  double scale = zeroLevel / sqrt(0. - faderTypes[type].minDb);
194  value *= scale;
195  int level = zeroLevel - int(value + 0.01f);
196  if (level < 0) level = 0;
197  return level;
198  }
199  }
200 }
201 
202 
203 double
204 AudioLevel::fader_to_multiplier(int level, int maxLevel, FaderType type)
205 {
206  if (level == 0) return 0.;
207  return dB_to_multiplier(fader_to_dB(level, maxLevel, type));
208 }
209 
210 int
211 AudioLevel::multiplier_to_fader(double multiplier, int maxLevel, FaderType type)
212 {
213  if (multiplier == 0.) return 0;
214  double dB = multiplier_to_dB(multiplier);
215  int fader = dB_to_fader(dB, maxLevel, type);
216  return fader;
217 }
218 
219 int
221 {
222  assert(levels > 0);
223  return multiplier_to_fader(m, levels, PreviewLevel);
224 }
225 
226 double
227 AudioLevel::preview_to_multiplier(int level, int levels)
228 {
229  assert(levels > 0);
230  return fader_to_multiplier(level, levels, PreviewLevel);
231 }
232 
233 
static double preview_to_multiplier(int level, int levels)
Definition: AudioLevel.cpp:227
static double fader_to_multiplier(int level, int maxLevel, FaderType type)
Definition: AudioLevel.cpp:204
static double multiplier_to_dB(double multiplier)
Definition: AudioLevel.cpp:50
static int multiplier_to_preview(double multiplier, int levels)
Definition: AudioLevel.cpp:220
static const double DB_FLOOR
Definition: AudioLevel.h:38
static const FaderDescription faderTypes[]
Definition: AudioLevel.cpp:41
static int multiplier_to_fader(double multiplier, int maxFaderLevel, FaderType type)
Definition: AudioLevel.cpp:211
static double iec_dB_to_fader(double db)
Definition: AudioLevel.cpp:68
FaderDescription(double _minDb, double _maxDb, double _zeroPoint)
Definition: AudioLevel.cpp:33
static double iec_fader_to_dB(double def)
Definition: AudioLevel.cpp:91
static int dB_to_fader(double dB, int maxFaderLevel, FaderType type)
Definition: AudioLevel.cpp:150
static double fader_to_dB(int level, int maxLevel, FaderType type)
Definition: AudioLevel.cpp:113
static double dB_to_multiplier(double dB)
Definition: AudioLevel.cpp:59