annotate examples/AmplitudeFollower.cpp @ 525:8c18bdaad04f c++11-mutex

Avoid simple static allocation of mutex, as it could lead to mutex being destroyed before last adapter that needs to use it (since adapters are usually also static)
author Chris Cannam
date Mon, 09 Sep 2019 10:24:13 +0100
parents 90571dcc371a
children
rev   line source
cannam@41 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
cannam@41 2
cannam@41 3 /*
cannam@41 4 Vamp
cannam@41 5
cannam@41 6 An API for audio analysis and feature extraction plugins.
cannam@41 7
cannam@41 8 Centre for Digital Music, Queen Mary, University of London.
cannam@41 9 This file copyright 2006 Dan Stowell.
cannam@41 10
cannam@41 11 Permission is hereby granted, free of charge, to any person
cannam@41 12 obtaining a copy of this software and associated documentation
cannam@41 13 files (the "Software"), to deal in the Software without
cannam@41 14 restriction, including without limitation the rights to use, copy,
cannam@41 15 modify, merge, publish, distribute, sublicense, and/or sell copies
cannam@41 16 of the Software, and to permit persons to whom the Software is
cannam@41 17 furnished to do so, subject to the following conditions:
cannam@41 18
cannam@41 19 The above copyright notice and this permission notice shall be
cannam@41 20 included in all copies or substantial portions of the Software.
cannam@41 21
cannam@41 22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
cannam@41 23 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
cannam@41 24 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
cannam@41 25 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
cannam@41 26 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
cannam@41 27 CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
cannam@41 28 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
cannam@41 29
cannam@41 30 Except as contained in this notice, the names of the Centre for
cannam@41 31 Digital Music; Queen Mary, University of London; and Chris Cannam
cannam@41 32 shall not be used in advertising or otherwise to promote the sale,
cannam@41 33 use or other dealings in this Software without prior written
cannam@41 34 authorization.
cannam@41 35 */
cannam@41 36
cannam@41 37 #include "AmplitudeFollower.h"
cannam@41 38
cannam@41 39 #include <cmath>
cannam@41 40
cannam@41 41 #include <string>
cannam@41 42 #include <vector>
cannam@41 43 #include <iostream>
Chris@394 44 #include <algorithm>
cannam@41 45
cannam@41 46 using std::string;
cannam@41 47 using std::vector;
cannam@41 48 using std::cerr;
cannam@41 49 using std::endl;
cannam@41 50
cannam@54 51 /**
cannam@41 52 * An implementation of SuperCollider's amplitude-follower algorithm
cannam@41 53 * as a simple Vamp plugin.
cannam@41 54 */
cannam@41 55
cannam@41 56 AmplitudeFollower::AmplitudeFollower(float inputSampleRate) :
cannam@41 57 Plugin(inputSampleRate),
cannam@41 58 m_stepSize(0),
cannam@41 59 m_previn(0.0f),
cannam@41 60 m_clampcoef(0.01f),
cannam@41 61 m_relaxcoef(0.01f)
cannam@41 62 {
cannam@41 63 }
cannam@41 64
cannam@41 65 AmplitudeFollower::~AmplitudeFollower()
cannam@41 66 {
cannam@41 67 }
cannam@41 68
cannam@41 69 string
cannam@49 70 AmplitudeFollower::getIdentifier() const
cannam@41 71 {
cannam@41 72 return "amplitudefollower";
cannam@41 73 }
cannam@41 74
cannam@41 75 string
cannam@49 76 AmplitudeFollower::getName() const
cannam@49 77 {
cannam@49 78 return "Amplitude Follower";
cannam@49 79 }
cannam@49 80
cannam@49 81 string
cannam@41 82 AmplitudeFollower::getDescription() const
cannam@41 83 {
cannam@49 84 return "Track the amplitude of the audio signal";
cannam@41 85 }
cannam@41 86
cannam@41 87 string
cannam@41 88 AmplitudeFollower::getMaker() const
cannam@41 89 {
cannam@43 90 return "Vamp SDK Example Plugins";
cannam@41 91 }
cannam@41 92
cannam@41 93 int
cannam@41 94 AmplitudeFollower::getPluginVersion() const
cannam@41 95 {
cannam@41 96 return 1;
cannam@41 97 }
cannam@41 98
cannam@41 99 string
cannam@41 100 AmplitudeFollower::getCopyright() const
cannam@41 101 {
cannam@41 102 return "Code copyright 2006 Dan Stowell; method from SuperCollider. Freely redistributable (BSD license)";
cannam@41 103 }
cannam@41 104
cannam@41 105 bool
cannam@41 106 AmplitudeFollower::initialise(size_t channels, size_t stepSize, size_t blockSize)
cannam@41 107 {
cannam@41 108 if (channels < getMinChannelCount() ||
Chris@501 109 channels > getMaxChannelCount()) {
Chris@501 110 cerr << "ERROR: AmplitudeFollower::initialise: "
Chris@501 111 << "channel count " << channels << " out of supported range"
Chris@501 112 << endl;
Chris@501 113 return false;
Chris@501 114 }
cannam@41 115
cannam@41 116 m_stepSize = std::min(stepSize, blockSize);
Chris@501 117
cannam@41 118 // Translate the coefficients
cannam@41 119 // from their "convenient" 60dB convergence-time values
cannam@41 120 // to real coefficients
cannam@41 121 m_clampcoef = m_clampcoef==0.0 ? 0.0 : exp(log(0.1)/(m_clampcoef * m_inputSampleRate));
cannam@41 122 m_relaxcoef = m_relaxcoef==0.0 ? 0.0 : exp(log(0.1)/(m_relaxcoef * m_inputSampleRate));
cannam@41 123
cannam@41 124 return true;
cannam@41 125 }
cannam@41 126
cannam@41 127 void
cannam@41 128 AmplitudeFollower::reset()
cannam@41 129 {
cannam@41 130 m_previn = 0.0f;
cannam@41 131 }
cannam@41 132
cannam@41 133 AmplitudeFollower::OutputList
cannam@41 134 AmplitudeFollower::getOutputDescriptors() const
cannam@41 135 {
cannam@41 136 OutputList list;
cannam@41 137
cannam@41 138 OutputDescriptor sca;
cannam@49 139 sca.identifier = "amplitude";
cannam@49 140 sca.name = "Amplitude";
cannam@281 141 sca.description = "The peak tracked amplitude for the current processing block";
cannam@41 142 sca.unit = "V";
cannam@41 143 sca.hasFixedBinCount = true;
cannam@41 144 sca.binCount = 1;
cannam@41 145 sca.hasKnownExtents = false;
cannam@41 146 sca.isQuantized = false;
cannam@41 147 sca.sampleType = OutputDescriptor::OneSamplePerStep;
cannam@41 148 list.push_back(sca);
cannam@41 149
cannam@41 150 return list;
cannam@41 151 }
cannam@41 152
cannam@41 153 AmplitudeFollower::ParameterList
cannam@41 154 AmplitudeFollower::getParameterDescriptors() const
cannam@41 155 {
cannam@41 156 ParameterList list;
cannam@41 157
cannam@41 158 ParameterDescriptor att;
cannam@49 159 att.identifier = "attack";
cannam@49 160 att.name = "Attack time";
cannam@281 161 att.description = "The 60dB convergence time for an increase in amplitude";
cannam@41 162 att.unit = "s";
cannam@41 163 att.minValue = 0.0f;
cannam@41 164 att.maxValue = 1.f;
cannam@41 165 att.defaultValue = 0.01f;
cannam@41 166 att.isQuantized = false;
cannam@41 167
cannam@41 168 list.push_back(att);
cannam@41 169
cannam@41 170 ParameterDescriptor dec;
cannam@49 171 dec.identifier = "release";
cannam@49 172 dec.name = "Release time";
cannam@281 173 dec.description = "The 60dB convergence time for a decrease in amplitude";
cannam@41 174 dec.unit = "s";
cannam@41 175 dec.minValue = 0.0f;
cannam@41 176 dec.maxValue = 1.f;
cannam@41 177 dec.defaultValue = 0.01f;
cannam@41 178 dec.isQuantized = false;
cannam@41 179
cannam@41 180 list.push_back(dec);
cannam@41 181
cannam@41 182 return list;
cannam@41 183 }
cannam@41 184
cannam@49 185 void AmplitudeFollower::setParameter(std::string paramid, float newval)
cannam@41 186 {
cannam@49 187 if (paramid == "attack") {
cannam@41 188 m_clampcoef = newval;
cannam@49 189 } else if (paramid == "release") {
cannam@41 190 m_relaxcoef = newval;
cannam@41 191 }
cannam@41 192 }
cannam@41 193
cannam@49 194 float AmplitudeFollower::getParameter(std::string paramid) const
cannam@41 195 {
cannam@49 196 if (paramid == "attack") {
cannam@41 197 return m_clampcoef;
cannam@49 198 } else if (paramid == "release") {
cannam@41 199 return m_relaxcoef;
cannam@41 200 }
cannam@41 201
cannam@41 202 return 0.0f;
cannam@41 203 }
cannam@41 204
cannam@41 205 AmplitudeFollower::FeatureSet
cannam@47 206 AmplitudeFollower::process(const float *const *inputBuffers,
Chris@437 207 Vamp::RealTime /* timestamp */)
cannam@41 208 {
cannam@41 209 if (m_stepSize == 0) {
cannam@41 210 cerr << "ERROR: AmplitudeFollower::process: "
cannam@41 211 << "AmplitudeFollower has not been initialised"
cannam@41 212 << endl;
cannam@41 213 return FeatureSet();
cannam@41 214 }
cannam@41 215
cannam@41 216 float previn = m_previn;
cannam@41 217
cannam@41 218 FeatureSet returnFeatures;
cannam@41 219
cannam@41 220 float val;
cannam@41 221 float peak = 0.0f;
cannam@41 222
cannam@41 223 for (size_t i = 0; i < m_stepSize; ++i) {
cannam@41 224
cannam@41 225 val = fabs(inputBuffers[0][i]);
cannam@41 226
cannam@41 227 if (val < previn) {
cannam@41 228 val = val + (previn - val) * m_relaxcoef;
cannam@41 229 } else {
cannam@41 230 val = val + (previn - val) * m_clampcoef;
cannam@41 231 }
cannam@41 232
cannam@41 233 if (val > peak) peak = val;
cannam@41 234 previn = val;
cannam@41 235 }
cannam@41 236
cannam@41 237 m_previn = previn;
cannam@41 238
cannam@41 239 // Now store the "feature" (peak amp) for this sample
cannam@41 240 Feature feature;
cannam@41 241 feature.hasTimestamp = false;
cannam@41 242 feature.values.push_back(peak);
cannam@41 243 returnFeatures[0].push_back(feature);
cannam@41 244
cannam@41 245 return returnFeatures;
cannam@41 246 }
cannam@41 247
cannam@41 248 AmplitudeFollower::FeatureSet
cannam@41 249 AmplitudeFollower::getRemainingFeatures()
cannam@41 250 {
cannam@41 251 return FeatureSet();
cannam@41 252 }
cannam@41 253