Mercurial > hg > svcore
comparison base/AudioLevel.cpp @ 0:da6937383da8
initial import
author | Chris Cannam |
---|---|
date | Tue, 10 Jan 2006 16:33:16 +0000 |
parents | |
children | d86891498eef |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:da6937383da8 |
---|---|
1 /* -*- c-basic-offset: 4 -*- vi:set ts=8 sts=4 sw=4: */ | |
2 | |
3 /* | |
4 A waveform viewer and audio annotation editor. | |
5 Chris Cannam, Queen Mary University of London, 2005 | |
6 | |
7 This is experimental software. Not for distribution. | |
8 */ | |
9 | |
10 /* | |
11 This is a modified version of a source file from the | |
12 Rosegarden MIDI and audio sequencer and notation editor. | |
13 This file copyright 2000-2005 Chris Cannam. | |
14 */ | |
15 | |
16 #include "base/AudioLevel.h" | |
17 #include <cmath> | |
18 #include <iostream> | |
19 #include <map> | |
20 #include <vector> | |
21 #include <cassert> | |
22 | |
23 const float AudioLevel::DB_FLOOR = -1000.0; | |
24 | |
25 struct FaderDescription | |
26 { | |
27 FaderDescription(float _minDb, float _maxDb, float _zeroPoint) : | |
28 minDb(_minDb), maxDb(_maxDb), zeroPoint(_zeroPoint) { } | |
29 | |
30 float minDb; | |
31 float maxDb; | |
32 float zeroPoint; // as fraction of total throw | |
33 }; | |
34 | |
35 static const FaderDescription faderTypes[] = { | |
36 FaderDescription(-40.0, +6.0, 0.75), // short | |
37 FaderDescription(-70.0, +10.0, 0.80), // long | |
38 FaderDescription(-70.0, 0.0, 1.00), // IEC268 | |
39 FaderDescription(-70.0, +10.0, 0.80), // IEC268 long | |
40 FaderDescription(-40.0, 0.0, 1.00), // preview | |
41 }; | |
42 | |
43 typedef std::vector<float> LevelList; | |
44 static std::map<int, LevelList> previewLevelCache; | |
45 static const LevelList &getPreviewLevelCache(int levels); | |
46 | |
47 float | |
48 AudioLevel::multiplier_to_dB(float multiplier) | |
49 { | |
50 if (multiplier == 0.0) return DB_FLOOR; | |
51 float dB = 10 * log10f(multiplier); | |
52 return dB; | |
53 } | |
54 | |
55 float | |
56 AudioLevel::dB_to_multiplier(float dB) | |
57 { | |
58 if (dB == DB_FLOOR) return 0.0; | |
59 float m = powf(10.0, dB / 10.0); | |
60 return m; | |
61 } | |
62 | |
63 /* IEC 60-268-18 fader levels. Thanks to Steve Harris. */ | |
64 | |
65 static float iec_dB_to_fader(float db) | |
66 { | |
67 float def = 0.0f; // Meter deflection %age | |
68 | |
69 if (db < -70.0f) { | |
70 def = 0.0f; | |
71 } else if (db < -60.0f) { | |
72 def = (db + 70.0f) * 0.25f; | |
73 } else if (db < -50.0f) { | |
74 def = (db + 60.0f) * 0.5f + 5.0f; | |
75 } else if (db < -40.0f) { | |
76 def = (db + 50.0f) * 0.75f + 7.5f; | |
77 } else if (db < -30.0f) { | |
78 def = (db + 40.0f) * 1.5f + 15.0f; | |
79 } else if (db < -20.0f) { | |
80 def = (db + 30.0f) * 2.0f + 30.0f; | |
81 } else { | |
82 def = (db + 20.0f) * 2.5f + 50.0f; | |
83 } | |
84 | |
85 return def; | |
86 } | |
87 | |
88 static float iec_fader_to_dB(float def) // Meter deflection %age | |
89 { | |
90 float db = 0.0f; | |
91 | |
92 if (def >= 50.0f) { | |
93 db = (def - 50.0f) / 2.5f - 20.0f; | |
94 } else if (def >= 30.0f) { | |
95 db = (def - 30.0f) / 2.0f - 30.0f; | |
96 } else if (def >= 15.0f) { | |
97 db = (def - 15.0f) / 1.5f - 40.0f; | |
98 } else if (def >= 7.5f) { | |
99 db = (def - 7.5f) / 0.75f - 50.0f; | |
100 } else if (def >= 5.0f) { | |
101 db = (def - 5.0f) / 0.5f - 60.0f; | |
102 } else { | |
103 db = (def / 0.25f) - 70.0f; | |
104 } | |
105 | |
106 return db; | |
107 } | |
108 | |
109 float | |
110 AudioLevel::fader_to_dB(int level, int maxLevel, FaderType type) | |
111 { | |
112 if (level == 0) return DB_FLOOR; | |
113 | |
114 if (type == IEC268Meter || type == IEC268LongMeter) { | |
115 | |
116 float maxPercent = iec_dB_to_fader(faderTypes[type].maxDb); | |
117 float percent = float(level) * maxPercent / float(maxLevel); | |
118 float dB = iec_fader_to_dB(percent); | |
119 return dB; | |
120 | |
121 } else { // scale proportional to sqrt(fabs(dB)) | |
122 | |
123 int zeroLevel = int(maxLevel * faderTypes[type].zeroPoint); | |
124 | |
125 if (level >= zeroLevel) { | |
126 | |
127 float value = level - zeroLevel; | |
128 float scale = float(maxLevel - zeroLevel) / | |
129 sqrtf(faderTypes[type].maxDb); | |
130 value /= scale; | |
131 float dB = powf(value, 2.0); | |
132 return dB; | |
133 | |
134 } else { | |
135 | |
136 float value = zeroLevel - level; | |
137 float scale = zeroLevel / sqrtf(0.0 - faderTypes[type].minDb); | |
138 value /= scale; | |
139 float dB = powf(value, 2.0); | |
140 return 0.0 - dB; | |
141 } | |
142 } | |
143 } | |
144 | |
145 | |
146 int | |
147 AudioLevel::dB_to_fader(float dB, int maxLevel, FaderType type) | |
148 { | |
149 if (dB == DB_FLOOR) return 0; | |
150 | |
151 if (type == IEC268Meter || type == IEC268LongMeter) { | |
152 | |
153 // The IEC scale gives a "percentage travel" for a given dB | |
154 // level, but it reaches 100% at 0dB. So we want to treat the | |
155 // result not as a percentage, but as a scale between 0 and | |
156 // whatever the "percentage" for our (possibly >0dB) max dB is. | |
157 | |
158 float maxPercent = iec_dB_to_fader(faderTypes[type].maxDb); | |
159 float percent = iec_dB_to_fader(dB); | |
160 int faderLevel = int((maxLevel * percent) / maxPercent + 0.01); | |
161 | |
162 if (faderLevel < 0) faderLevel = 0; | |
163 if (faderLevel > maxLevel) faderLevel = maxLevel; | |
164 return faderLevel; | |
165 | |
166 } else { | |
167 | |
168 int zeroLevel = int(maxLevel * faderTypes[type].zeroPoint); | |
169 | |
170 if (dB >= 0.0) { | |
171 | |
172 float value = sqrtf(dB); | |
173 float scale = (maxLevel - zeroLevel) / sqrtf(faderTypes[type].maxDb); | |
174 value *= scale; | |
175 int level = int(value + 0.01) + zeroLevel; | |
176 if (level > maxLevel) level = maxLevel; | |
177 return level; | |
178 | |
179 } else { | |
180 | |
181 dB = 0.0 - dB; | |
182 float value = sqrtf(dB); | |
183 float scale = zeroLevel / sqrtf(0.0 - faderTypes[type].minDb); | |
184 value *= scale; | |
185 int level = zeroLevel - int(value + 0.01); | |
186 if (level < 0) level = 0; | |
187 return level; | |
188 } | |
189 } | |
190 } | |
191 | |
192 | |
193 float | |
194 AudioLevel::fader_to_multiplier(int level, int maxLevel, FaderType type) | |
195 { | |
196 if (level == 0) return 0.0; | |
197 return dB_to_multiplier(fader_to_dB(level, maxLevel, type)); | |
198 } | |
199 | |
200 int | |
201 AudioLevel::multiplier_to_fader(float multiplier, int maxLevel, FaderType type) | |
202 { | |
203 if (multiplier == 0.0) return 0; | |
204 float dB = multiplier_to_dB(multiplier); | |
205 int fader = dB_to_fader(dB, maxLevel, type); | |
206 return fader; | |
207 } | |
208 | |
209 | |
210 const LevelList & | |
211 getPreviewLevelCache(int levels) | |
212 { | |
213 LevelList &ll = previewLevelCache[levels]; | |
214 if (ll.empty()) { | |
215 for (int i = 0; i <= levels; ++i) { | |
216 float m = AudioLevel::fader_to_multiplier | |
217 (i + levels/4, levels + levels/4, AudioLevel::PreviewLevel); | |
218 if (levels == 1) m /= 100; // noise | |
219 ll.push_back(m); | |
220 } | |
221 } | |
222 return ll; | |
223 } | |
224 | |
225 int | |
226 AudioLevel::multiplier_to_preview(float m, int levels) | |
227 { | |
228 assert(levels > 0); | |
229 if (m < 0.0) return -multiplier_to_preview(-m, levels); | |
230 | |
231 const LevelList &ll = getPreviewLevelCache(levels); | |
232 int result = -1; | |
233 | |
234 int lo = 0, hi = levels; | |
235 | |
236 // binary search | |
237 int level = -1; | |
238 while (result < 0) { | |
239 int newlevel = (lo + hi) / 2; | |
240 if (newlevel == level || | |
241 newlevel == 0 || | |
242 newlevel == levels) { | |
243 result = newlevel; | |
244 break; | |
245 } | |
246 level = newlevel; | |
247 if (ll[level] >= m) { | |
248 hi = level; | |
249 } else if (ll[level+1] >= m) { | |
250 result = level; | |
251 } else { | |
252 lo = level; | |
253 } | |
254 } | |
255 | |
256 return result; | |
257 } | |
258 | |
259 float | |
260 AudioLevel::preview_to_multiplier(int level, int levels) | |
261 { | |
262 assert(levels > 0); | |
263 if (level < 0) return -preview_to_multiplier(-level, levels); | |
264 const LevelList &ll = getPreviewLevelCache(levels); | |
265 return ll[level]; | |
266 } | |
267 | |
268 |