AudioLevel.cpp

Go to the documentation of this file.
00001 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
00002 
00003 /*
00004     Sonic Visualiser
00005     An audio file viewer and annotation editor.
00006     Centre for Digital Music, Queen Mary, University of London.
00007     
00008     This program is free software; you can redistribute it and/or
00009     modify it under the terms of the GNU General Public License as
00010     published by the Free Software Foundation; either version 2 of the
00011     License, or (at your option) any later version.  See the file
00012     COPYING included with this distribution for more information.
00013 */
00014 
00015 /*
00016    This is a modified version of a source file from the 
00017    Rosegarden MIDI and audio sequencer and notation editor.
00018    This file copyright 2000-2006 Chris Cannam.
00019 */
00020 
00021 #include "AudioLevel.h"
00022 #include <cmath>
00023 #include <iostream>
00024 #include <map>
00025 #include <vector>
00026 #include <cassert>
00027 
00028 const float AudioLevel::DB_FLOOR = -1000.f;
00029 
00030 struct FaderDescription
00031 {
00032     FaderDescription(float _minDb, float _maxDb, float _zeroPoint) :
00033         minDb(_minDb), maxDb(_maxDb), zeroPoint(_zeroPoint) { }
00034 
00035     float minDb;
00036     float maxDb;
00037     float zeroPoint; // as fraction of total throw
00038 };
00039 
00040 static const FaderDescription faderTypes[] = {
00041     FaderDescription(-40.f,  +6.f, 0.75f), // short
00042     FaderDescription(-70.f, +10.f, 0.80f), // long
00043     FaderDescription(-70.f,   0.f, 1.00f), // IEC268
00044     FaderDescription(-70.f, +10.f, 0.80f), // IEC268 long
00045     FaderDescription(-40.f,   0.f, 1.00f), // preview
00046 };
00047 
00048 //typedef std::vector<float> LevelList;
00049 //static std::map<int, LevelList> previewLevelCache;
00050 //static const LevelList &getPreviewLevelCache(int levels);
00051 
00052 float
00053 AudioLevel::multiplier_to_dB(float multiplier)
00054 {
00055     if (multiplier == 0.f) return DB_FLOOR;
00056     else if (multiplier < 0.f) return multiplier_to_dB(-multiplier);
00057     float dB = 10 * log10f(multiplier);
00058     return dB;
00059 }
00060 
00061 float
00062 AudioLevel::dB_to_multiplier(float dB)
00063 {
00064     if (dB == DB_FLOOR) return 0.f;
00065     float m = powf(10.f, dB / 10.f);
00066     return m;
00067 }
00068 
00069 /* IEC 60-268-18 fader levels.  Thanks to Steve Harris. */
00070 
00071 static float iec_dB_to_fader(float db)
00072 {
00073     float def = 0.0f; // Meter deflection %age
00074 
00075     if (db < -70.0f) {
00076         def = 0.0f;
00077     } else if (db < -60.0f) {
00078         def = (db + 70.0f) * 0.25f;
00079     } else if (db < -50.0f) {
00080         def = (db + 60.0f) * 0.5f + 5.0f;
00081     } else if (db < -40.0f) {
00082         def = (db + 50.0f) * 0.75f + 7.5f;
00083     } else if (db < -30.0f) {
00084         def = (db + 40.0f) * 1.5f + 15.0f;
00085     } else if (db < -20.0f) {
00086         def = (db + 30.0f) * 2.0f + 30.0f;
00087     } else {
00088         def = (db + 20.0f) * 2.5f + 50.0f;
00089     }
00090 
00091     return def;
00092 }
00093 
00094 static float iec_fader_to_dB(float def)  // Meter deflection %age
00095 {
00096     float db = 0.0f;
00097 
00098     if (def >= 50.0f) {
00099         db = (def - 50.0f) / 2.5f - 20.0f;
00100     } else if (def >= 30.0f) {
00101         db = (def - 30.0f) / 2.0f - 30.0f;
00102     } else if (def >= 15.0f) {
00103         db = (def - 15.0f) / 1.5f - 40.0f;
00104     } else if (def >= 7.5f) {
00105         db = (def - 7.5f) / 0.75f - 50.0f;
00106     } else if (def >= 5.0f) {
00107         db = (def - 5.0f) / 0.5f - 60.0f;
00108     } else {
00109         db = (def / 0.25f) - 70.0f;
00110     }
00111 
00112     return db;
00113 }
00114 
00115 float
00116 AudioLevel::fader_to_dB(int level, int maxLevel, FaderType type)
00117 {
00118     if (level == 0) return DB_FLOOR;
00119 
00120     if (type == IEC268Meter || type == IEC268LongMeter) {
00121 
00122         float maxPercent = iec_dB_to_fader(faderTypes[type].maxDb);
00123         float percent = float(level) * maxPercent / float(maxLevel);
00124         float dB = iec_fader_to_dB(percent);
00125         return dB;
00126 
00127     } else { // scale proportional to sqrt(fabs(dB))
00128 
00129         int zeroLevel = int(maxLevel * faderTypes[type].zeroPoint);
00130     
00131         if (level >= zeroLevel) {
00132             
00133             float value = level - zeroLevel;
00134             float scale = float(maxLevel - zeroLevel) /
00135                 sqrtf(faderTypes[type].maxDb);
00136             value /= scale;
00137             float dB = powf(value, 2.f);
00138             return dB;
00139             
00140         } else {
00141             
00142             float value = zeroLevel - level;
00143             float scale = zeroLevel / sqrtf(0.f - faderTypes[type].minDb);
00144             value /= scale;
00145             float dB = powf(value, 2.f);
00146             return 0.f - dB;
00147         }
00148     }
00149 }
00150 
00151 
00152 int
00153 AudioLevel::dB_to_fader(float dB, int maxLevel, FaderType type)
00154 {
00155     if (dB == DB_FLOOR) return 0;
00156 
00157     if (type == IEC268Meter || type == IEC268LongMeter) {
00158 
00159         // The IEC scale gives a "percentage travel" for a given dB
00160         // level, but it reaches 100% at 0dB.  So we want to treat the
00161         // result not as a percentage, but as a scale between 0 and
00162         // whatever the "percentage" for our (possibly >0dB) max dB is.
00163         
00164         float maxPercent = iec_dB_to_fader(faderTypes[type].maxDb);
00165         float percent = iec_dB_to_fader(dB);
00166         int faderLevel = int((maxLevel * percent) / maxPercent + 0.01f);
00167         
00168         if (faderLevel < 0) faderLevel = 0;
00169         if (faderLevel > maxLevel) faderLevel = maxLevel;
00170         return faderLevel;
00171 
00172     } else {
00173 
00174         int zeroLevel = int(maxLevel * faderTypes[type].zeroPoint);
00175 
00176         if (dB >= 0.f) {
00177             
00178             if (faderTypes[type].maxDb <= 0.f) {
00179                 
00180                 return maxLevel;
00181 
00182             } else {
00183 
00184                 float value = sqrtf(dB);
00185                 float scale = (maxLevel - zeroLevel) / sqrtf(faderTypes[type].maxDb);
00186                 value *= scale;
00187                 int level = int(value + 0.01f) + zeroLevel;
00188                 if (level > maxLevel) level = maxLevel;
00189                 return level;
00190             }
00191             
00192         } else {
00193 
00194             dB = 0.f - dB;
00195             float value = sqrtf(dB);
00196             float scale = zeroLevel / sqrtf(0.f - faderTypes[type].minDb);
00197             value *= scale;
00198             int level = zeroLevel - int(value + 0.01f);
00199             if (level < 0) level = 0;
00200             return level;
00201         }
00202     }
00203 }
00204 
00205         
00206 float
00207 AudioLevel::fader_to_multiplier(int level, int maxLevel, FaderType type)
00208 {
00209     if (level == 0) return 0.f;
00210     return dB_to_multiplier(fader_to_dB(level, maxLevel, type));
00211 }
00212 
00213 int
00214 AudioLevel::multiplier_to_fader(float multiplier, int maxLevel, FaderType type)
00215 {
00216     if (multiplier == 0.f) return 0;
00217     float dB = multiplier_to_dB(multiplier);
00218     int fader = dB_to_fader(dB, maxLevel, type);
00219     return fader;
00220 }
00221 
00222 /*
00223 const LevelList &
00224 getPreviewLevelCache(int levels)
00225 {
00226     LevelList &ll = previewLevelCache[levels];
00227     if (ll.empty()) {
00228         for (int i = 0; i <= levels; ++i) {
00229             float m = AudioLevel::fader_to_multiplier
00230                 (i + levels/4, levels + levels/4, AudioLevel::PreviewLevel);
00231             if (levels == 1) m /= 100; // noise
00232             ll.push_back(m);
00233         }
00234     }
00235     return ll;
00236 }
00237 */
00238 
00239 int
00240 AudioLevel::multiplier_to_preview(float m, int levels)
00241 {
00242     assert(levels > 0);
00243     return multiplier_to_fader(m, levels, PreviewLevel);
00244 
00245     /* The original multiplier_to_preview which follows is not thread-safe.
00246 
00247     if (m < 0.f) return -multiplier_to_preview(-m, levels);
00248 
00249     const LevelList &ll = getPreviewLevelCache(levels);
00250     int result = -1;
00251 
00252     int lo = 0, hi = levels;
00253 
00254     // binary search
00255     int level = -1;
00256     while (result < 0) {
00257         int newlevel = (lo + hi) / 2;
00258         if (newlevel == level ||
00259             newlevel == 0 ||
00260             newlevel == levels) {
00261             result = newlevel;
00262             break;
00263         }
00264         level = newlevel;
00265         if (ll[level] >= m) {
00266             hi = level;
00267         } else if (ll[level+1] >= m) {
00268             result = level;
00269         } else {
00270             lo = level;
00271         }
00272     }
00273                    
00274     return result;
00275 
00276     */
00277 }
00278 
00279 float
00280 AudioLevel::preview_to_multiplier(int level, int levels)
00281 {
00282     assert(levels > 0);
00283     return fader_to_multiplier(level, levels, PreviewLevel);
00284 /*
00285     if (level < 0) return -preview_to_multiplier(-level, levels);
00286     const LevelList &ll = getPreviewLevelCache(levels);
00287     return ll[level];
00288 */
00289 }
00290         
00291 

Generated on Wed Feb 20 15:45:25 2008 for SonicVisualiser by  doxygen 1.5.1