annotate base/AudioLevel.cpp @ 1858:14747f24ad04

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