comparison base/AudioLevel.cpp @ 0:fc9323a41f5a

start base : Sonic Visualiser sv1-1.0rc1
author lbajardsilogic
date Fri, 11 May 2007 09:08:14 +0000
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:fc9323a41f5a
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
28 const float AudioLevel::DB_FLOOR = -1000.f;
29
30 struct FaderDescription
31 {
32 FaderDescription(float _minDb, float _maxDb, float _zeroPoint) :
33 minDb(_minDb), maxDb(_maxDb), zeroPoint(_zeroPoint) { }
34
35 float minDb;
36 float maxDb;
37 float zeroPoint; // as fraction of total throw
38 };
39
40 static const FaderDescription faderTypes[] = {
41 FaderDescription(-40.f, +6.f, 0.75f), // short
42 FaderDescription(-70.f, +10.f, 0.80f), // long
43 FaderDescription(-70.f, 0.f, 1.00f), // IEC268
44 FaderDescription(-70.f, +10.f, 0.80f), // IEC268 long
45 FaderDescription(-40.f, 0.f, 1.00f), // preview
46 };
47
48 //typedef std::vector<float> LevelList;
49 //static std::map<int, LevelList> previewLevelCache;
50 //static const LevelList &getPreviewLevelCache(int levels);
51
52 float
53 AudioLevel::multiplier_to_dB(float multiplier)
54 {
55 if (multiplier == 0.f) return DB_FLOOR;
56 else if (multiplier < 0.f) return multiplier_to_dB(-multiplier);
57 float dB = 10 * log10f(multiplier);
58 return dB;
59 }
60
61 float
62 AudioLevel::dB_to_multiplier(float dB)
63 {
64 if (dB == DB_FLOOR) return 0.f;
65 float m = powf(10.f, dB / 10.f);
66 return m;
67 }
68
69 /* IEC 60-268-18 fader levels. Thanks to Steve Harris. */
70
71 static float iec_dB_to_fader(float db)
72 {
73 float def = 0.0f; // Meter deflection %age
74
75 if (db < -70.0f) {
76 def = 0.0f;
77 } else if (db < -60.0f) {
78 def = (db + 70.0f) * 0.25f;
79 } else if (db < -50.0f) {
80 def = (db + 60.0f) * 0.5f + 5.0f;
81 } else if (db < -40.0f) {
82 def = (db + 50.0f) * 0.75f + 7.5f;
83 } else if (db < -30.0f) {
84 def = (db + 40.0f) * 1.5f + 15.0f;
85 } else if (db < -20.0f) {
86 def = (db + 30.0f) * 2.0f + 30.0f;
87 } else {
88 def = (db + 20.0f) * 2.5f + 50.0f;
89 }
90
91 return def;
92 }
93
94 static float iec_fader_to_dB(float def) // Meter deflection %age
95 {
96 float db = 0.0f;
97
98 if (def >= 50.0f) {
99 db = (def - 50.0f) / 2.5f - 20.0f;
100 } else if (def >= 30.0f) {
101 db = (def - 30.0f) / 2.0f - 30.0f;
102 } else if (def >= 15.0f) {
103 db = (def - 15.0f) / 1.5f - 40.0f;
104 } else if (def >= 7.5f) {
105 db = (def - 7.5f) / 0.75f - 50.0f;
106 } else if (def >= 5.0f) {
107 db = (def - 5.0f) / 0.5f - 60.0f;
108 } else {
109 db = (def / 0.25f) - 70.0f;
110 }
111
112 return db;
113 }
114
115 float
116 AudioLevel::fader_to_dB(int level, int maxLevel, FaderType type)
117 {
118 if (level == 0) return DB_FLOOR;
119
120 if (type == IEC268Meter || type == IEC268LongMeter) {
121
122 float maxPercent = iec_dB_to_fader(faderTypes[type].maxDb);
123 float percent = float(level) * maxPercent / float(maxLevel);
124 float dB = iec_fader_to_dB(percent);
125 return dB;
126
127 } else { // scale proportional to sqrt(fabs(dB))
128
129 int zeroLevel = int(maxLevel * faderTypes[type].zeroPoint);
130
131 if (level >= zeroLevel) {
132
133 float value = level - zeroLevel;
134 float scale = float(maxLevel - zeroLevel) /
135 sqrtf(faderTypes[type].maxDb);
136 value /= scale;
137 float dB = powf(value, 2.f);
138 return dB;
139
140 } else {
141
142 float value = zeroLevel - level;
143 float scale = zeroLevel / sqrtf(0.f - faderTypes[type].minDb);
144 value /= scale;
145 float dB = powf(value, 2.f);
146 return 0.f - dB;
147 }
148 }
149 }
150
151
152 int
153 AudioLevel::dB_to_fader(float dB, int maxLevel, FaderType type)
154 {
155 if (dB == DB_FLOOR) return 0;
156
157 if (type == IEC268Meter || type == IEC268LongMeter) {
158
159 // The IEC scale gives a "percentage travel" for a given dB
160 // level, but it reaches 100% at 0dB. So we want to treat the
161 // result not as a percentage, but as a scale between 0 and
162 // whatever the "percentage" for our (possibly >0dB) max dB is.
163
164 float maxPercent = iec_dB_to_fader(faderTypes[type].maxDb);
165 float percent = iec_dB_to_fader(dB);
166 int faderLevel = int((maxLevel * percent) / maxPercent + 0.01f);
167
168 if (faderLevel < 0) faderLevel = 0;
169 if (faderLevel > maxLevel) faderLevel = maxLevel;
170 return faderLevel;
171
172 } else {
173
174 int zeroLevel = int(maxLevel * faderTypes[type].zeroPoint);
175
176 if (dB >= 0.f) {
177
178 if (faderTypes[type].maxDb <= 0.f) {
179
180 return maxLevel;
181
182 } else {
183
184 float value = sqrtf(dB);
185 float scale = (maxLevel - zeroLevel) / sqrtf(faderTypes[type].maxDb);
186 value *= scale;
187 int level = int(value + 0.01f) + zeroLevel;
188 if (level > maxLevel) level = maxLevel;
189 return level;
190 }
191
192 } else {
193
194 dB = 0.f - dB;
195 float value = sqrtf(dB);
196 float scale = zeroLevel / sqrtf(0.f - faderTypes[type].minDb);
197 value *= scale;
198 int level = zeroLevel - int(value + 0.01f);
199 if (level < 0) level = 0;
200 return level;
201 }
202 }
203 }
204
205
206 float
207 AudioLevel::fader_to_multiplier(int level, int maxLevel, FaderType type)
208 {
209 if (level == 0) return 0.f;
210 return dB_to_multiplier(fader_to_dB(level, maxLevel, type));
211 }
212
213 int
214 AudioLevel::multiplier_to_fader(float multiplier, int maxLevel, FaderType type)
215 {
216 if (multiplier == 0.f) return 0;
217 float dB = multiplier_to_dB(multiplier);
218 int fader = dB_to_fader(dB, maxLevel, type);
219 return fader;
220 }
221
222 /*
223 const LevelList &
224 getPreviewLevelCache(int levels)
225 {
226 LevelList &ll = previewLevelCache[levels];
227 if (ll.empty()) {
228 for (int i = 0; i <= levels; ++i) {
229 float m = AudioLevel::fader_to_multiplier
230 (i + levels/4, levels + levels/4, AudioLevel::PreviewLevel);
231 if (levels == 1) m /= 100; // noise
232 ll.push_back(m);
233 }
234 }
235 return ll;
236 }
237 */
238
239 int
240 AudioLevel::multiplier_to_preview(float m, int levels)
241 {
242 assert(levels > 0);
243 return multiplier_to_fader(m, levels, PreviewLevel);
244
245 /* The original multiplier_to_preview which follows is not thread-safe.
246
247 if (m < 0.f) return -multiplier_to_preview(-m, levels);
248
249 const LevelList &ll = getPreviewLevelCache(levels);
250 int result = -1;
251
252 int lo = 0, hi = levels;
253
254 // binary search
255 int level = -1;
256 while (result < 0) {
257 int newlevel = (lo + hi) / 2;
258 if (newlevel == level ||
259 newlevel == 0 ||
260 newlevel == levels) {
261 result = newlevel;
262 break;
263 }
264 level = newlevel;
265 if (ll[level] >= m) {
266 hi = level;
267 } else if (ll[level+1] >= m) {
268 result = level;
269 } else {
270 lo = level;
271 }
272 }
273
274 return result;
275
276 */
277 }
278
279 float
280 AudioLevel::preview_to_multiplier(int level, int levels)
281 {
282 assert(levels > 0);
283 return fader_to_multiplier(level, levels, PreviewLevel);
284 /*
285 if (level < 0) return -preview_to_multiplier(-level, levels);
286 const LevelList &ll = getPreviewLevelCache(levels);
287 return ll[level];
288 */
289 }
290
291