svcore  1.9
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 #include "system/System.h"
00028 
00029 const float AudioLevel::DB_FLOOR = -1000.f;
00030 
00031 struct FaderDescription
00032 {
00033     FaderDescription(float _minDb, float _maxDb, float _zeroPoint) :
00034         minDb(_minDb), maxDb(_maxDb), zeroPoint(_zeroPoint) { }
00035 
00036     float minDb;
00037     float maxDb;
00038     float zeroPoint; // as fraction of total throw
00039 };
00040 
00041 static const FaderDescription faderTypes[] = {
00042     FaderDescription(-40.f,  +6.f, 0.75f), // short
00043     FaderDescription(-70.f, +10.f, 0.80f), // long
00044     FaderDescription(-70.f,   0.f, 1.00f), // IEC268
00045     FaderDescription(-70.f, +10.f, 0.80f), // IEC268 long
00046     FaderDescription(-40.f,   0.f, 1.00f), // preview
00047 };
00048 
00049 //typedef std::vector<float> LevelList;
00050 //static std::map<int, LevelList> previewLevelCache;
00051 //static const LevelList &getPreviewLevelCache(int levels);
00052 
00053 float
00054 AudioLevel::multiplier_to_dB(float multiplier)
00055 {
00056     if (multiplier == 0.f) return DB_FLOOR;
00057     else if (multiplier < 0.f) return multiplier_to_dB(-multiplier);
00058     float dB = 10 * log10f(multiplier);
00059     return dB;
00060 }
00061 
00062 float
00063 AudioLevel::dB_to_multiplier(float dB)
00064 {
00065     if (dB == DB_FLOOR) return 0.f;
00066     float m = powf(10.f, dB / 10.f);
00067     return m;
00068 }
00069 
00070 /* IEC 60-268-18 fader levels.  Thanks to Steve Harris. */
00071 
00072 static float iec_dB_to_fader(float db)
00073 {
00074     float def = 0.0f; // Meter deflection %age
00075 
00076     if (db < -70.0f) {
00077         def = 0.0f;
00078     } else if (db < -60.0f) {
00079         def = (db + 70.0f) * 0.25f;
00080     } else if (db < -50.0f) {
00081         def = (db + 60.0f) * 0.5f + 2.5f; // corrected from 5.0f base, thanks Robin Gareus
00082     } else if (db < -40.0f) {
00083         def = (db + 50.0f) * 0.75f + 7.5f;
00084     } else if (db < -30.0f) {
00085         def = (db + 40.0f) * 1.5f + 15.0f;
00086     } else if (db < -20.0f) {
00087         def = (db + 30.0f) * 2.0f + 30.0f;
00088     } else {
00089         def = (db + 20.0f) * 2.5f + 50.0f;
00090     }
00091 
00092     return def;
00093 }
00094 
00095 static float iec_fader_to_dB(float def)  // Meter deflection %age
00096 {
00097     float db = 0.0f;
00098 
00099     if (def >= 50.0f) {
00100         db = (def - 50.0f) / 2.5f - 20.0f;
00101     } else if (def >= 30.0f) {
00102         db = (def - 30.0f) / 2.0f - 30.0f;
00103     } else if (def >= 15.0f) {
00104         db = (def - 15.0f) / 1.5f - 40.0f;
00105     } else if (def >= 7.5f) {
00106         db = (def - 7.5f) / 0.75f - 50.0f;
00107     } else if (def >= 2.5f) {
00108         db = (def - 2.5f) / 0.5f - 60.0f;
00109     } else {
00110         db = (def / 0.25f) - 70.0f;
00111     }
00112 
00113     return db;
00114 }
00115 
00116 float
00117 AudioLevel::fader_to_dB(int level, int maxLevel, FaderType type)
00118 {
00119     if (level == 0) return DB_FLOOR;
00120 
00121     if (type == IEC268Meter || type == IEC268LongMeter) {
00122 
00123         float maxPercent = iec_dB_to_fader(faderTypes[type].maxDb);
00124         float percent = float(level) * maxPercent / float(maxLevel);
00125         float dB = iec_fader_to_dB(percent);
00126         return dB;
00127 
00128     } else { // scale proportional to sqrt(fabs(dB))
00129 
00130         int zeroLevel = int(maxLevel * faderTypes[type].zeroPoint);
00131     
00132         if (level >= zeroLevel) {
00133             
00134             float value = level - zeroLevel;
00135             float scale = float(maxLevel - zeroLevel) /
00136                 sqrtf(faderTypes[type].maxDb);
00137             value /= scale;
00138             float dB = powf(value, 2.f);
00139             return dB;
00140             
00141         } else {
00142             
00143             float value = zeroLevel - level;
00144             float scale = zeroLevel / sqrtf(0.f - faderTypes[type].minDb);
00145             value /= scale;
00146             float dB = powf(value, 2.f);
00147             return 0.f - dB;
00148         }
00149     }
00150 }
00151 
00152 
00153 int
00154 AudioLevel::dB_to_fader(float dB, int maxLevel, FaderType type)
00155 {
00156     if (dB == DB_FLOOR) return 0;
00157 
00158     if (type == IEC268Meter || type == IEC268LongMeter) {
00159 
00160         // The IEC scale gives a "percentage travel" for a given dB
00161         // level, but it reaches 100% at 0dB.  So we want to treat the
00162         // result not as a percentage, but as a scale between 0 and
00163         // whatever the "percentage" for our (possibly >0dB) max dB is.
00164         
00165         float maxPercent = iec_dB_to_fader(faderTypes[type].maxDb);
00166         float percent = iec_dB_to_fader(dB);
00167         int faderLevel = int((maxLevel * percent) / maxPercent + 0.01f);
00168         
00169         if (faderLevel < 0) faderLevel = 0;
00170         if (faderLevel > maxLevel) faderLevel = maxLevel;
00171         return faderLevel;
00172 
00173     } else {
00174 
00175         int zeroLevel = int(maxLevel * faderTypes[type].zeroPoint);
00176 
00177         if (dB >= 0.f) {
00178             
00179             if (faderTypes[type].maxDb <= 0.f) {
00180                 
00181                 return maxLevel;
00182 
00183             } else {
00184 
00185                 float value = sqrtf(dB);
00186                 float scale = (maxLevel - zeroLevel) / sqrtf(faderTypes[type].maxDb);
00187                 value *= scale;
00188                 int level = int(value + 0.01f) + zeroLevel;
00189                 if (level > maxLevel) level = maxLevel;
00190                 return level;
00191             }
00192             
00193         } else {
00194 
00195             dB = 0.f - dB;
00196             float value = sqrtf(dB);
00197             float scale = zeroLevel / sqrtf(0.f - faderTypes[type].minDb);
00198             value *= scale;
00199             int level = zeroLevel - int(value + 0.01f);
00200             if (level < 0) level = 0;
00201             return level;
00202         }
00203     }
00204 }
00205 
00206         
00207 float
00208 AudioLevel::fader_to_multiplier(int level, int maxLevel, FaderType type)
00209 {
00210     if (level == 0) return 0.f;
00211     return dB_to_multiplier(fader_to_dB(level, maxLevel, type));
00212 }
00213 
00214 int
00215 AudioLevel::multiplier_to_fader(float multiplier, int maxLevel, FaderType type)
00216 {
00217     if (multiplier == 0.f) return 0;
00218     float dB = multiplier_to_dB(multiplier);
00219     int fader = dB_to_fader(dB, maxLevel, type);
00220     return fader;
00221 }
00222 
00223 /*
00224 const LevelList &
00225 getPreviewLevelCache(int levels)
00226 {
00227     LevelList &ll = previewLevelCache[levels];
00228     if (ll.empty()) {
00229         for (int i = 0; i <= levels; ++i) {
00230             float m = AudioLevel::fader_to_multiplier
00231                 (i + levels/4, levels + levels/4, AudioLevel::PreviewLevel);
00232             if (levels == 1) m /= 100; // noise
00233             ll.push_back(m);
00234         }
00235     }
00236     return ll;
00237 }
00238 */
00239 
00240 int
00241 AudioLevel::multiplier_to_preview(float m, int levels)
00242 {
00243     assert(levels > 0);
00244     return multiplier_to_fader(m, levels, PreviewLevel);
00245 
00246     /* The original multiplier_to_preview which follows is not thread-safe.
00247 
00248     if (m < 0.f) return -multiplier_to_preview(-m, levels);
00249 
00250     const LevelList &ll = getPreviewLevelCache(levels);
00251     int result = -1;
00252 
00253     int lo = 0, hi = levels;
00254 
00255     // binary search
00256     int level = -1;
00257     while (result < 0) {
00258         int newlevel = (lo + hi) / 2;
00259         if (newlevel == level ||
00260             newlevel == 0 ||
00261             newlevel == levels) {
00262             result = newlevel;
00263             break;
00264         }
00265         level = newlevel;
00266         if (ll[level] >= m) {
00267             hi = level;
00268         } else if (ll[level+1] >= m) {
00269             result = level;
00270         } else {
00271             lo = level;
00272         }
00273     }
00274                    
00275     return result;
00276 
00277     */
00278 }
00279 
00280 float
00281 AudioLevel::preview_to_multiplier(int level, int levels)
00282 {
00283     assert(levels > 0);
00284     return fader_to_multiplier(level, levels, PreviewLevel);
00285 /*
00286     if (level < 0) return -preview_to_multiplier(-level, levels);
00287     const LevelList &ll = getPreviewLevelCache(levels);
00288     return ll[level];
00289 */
00290 }
00291         
00292