annotate base/AudioLevel.cpp @ 1879:652c5360e682

Ensure transforms are populated before instantiateDefaultPluginFor runs - otherwise if we have prior knowledge of a transform id, we can find ourselves trying to instantiate it before the plugin factory has heard of it and e.g. knows which server to use
author Chris Cannam
date Thu, 25 Jun 2020 12:20:06 +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