annotate examples/AmplitudeFollower.cpp @ 98:896a97349ac5

* Add a static wrapper object to wrap the static instance pointer, so that it can be properly deleted on program exit instead of showing up in certain tools as leaked
author cannam
date Mon, 03 Dec 2007 12:57:27 +0000
parents 933fee59d33a
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>
cannam@41 44
cannam@41 45 using std::string;
cannam@41 46 using std::vector;
cannam@41 47 using std::cerr;
cannam@41 48 using std::endl;
cannam@41 49
cannam@54 50 /**
cannam@41 51 * An implementation of SuperCollider's amplitude-follower algorithm
cannam@41 52 * as a simple Vamp plugin.
cannam@41 53 */
cannam@41 54
cannam@41 55 AmplitudeFollower::AmplitudeFollower(float inputSampleRate) :
cannam@41 56 Plugin(inputSampleRate),
cannam@41 57 m_stepSize(0),
cannam@41 58 m_previn(0.0f),
cannam@41 59 m_clampcoef(0.01f),
cannam@41 60 m_relaxcoef(0.01f)
cannam@41 61 {
cannam@41 62 }
cannam@41 63
cannam@41 64 AmplitudeFollower::~AmplitudeFollower()
cannam@41 65 {
cannam@41 66 }
cannam@41 67
cannam@41 68 string
cannam@49 69 AmplitudeFollower::getIdentifier() const
cannam@41 70 {
cannam@41 71 return "amplitudefollower";
cannam@41 72 }
cannam@41 73
cannam@41 74 string
cannam@49 75 AmplitudeFollower::getName() const
cannam@49 76 {
cannam@49 77 return "Amplitude Follower";
cannam@49 78 }
cannam@49 79
cannam@49 80 string
cannam@41 81 AmplitudeFollower::getDescription() const
cannam@41 82 {
cannam@49 83 return "Track the amplitude of the audio signal";
cannam@41 84 }
cannam@41 85
cannam@41 86 string
cannam@41 87 AmplitudeFollower::getMaker() const
cannam@41 88 {
cannam@43 89 return "Vamp SDK Example Plugins";
cannam@41 90 }
cannam@41 91
cannam@41 92 int
cannam@41 93 AmplitudeFollower::getPluginVersion() const
cannam@41 94 {
cannam@41 95 return 1;
cannam@41 96 }
cannam@41 97
cannam@41 98 string
cannam@41 99 AmplitudeFollower::getCopyright() const
cannam@41 100 {
cannam@41 101 return "Code copyright 2006 Dan Stowell; method from SuperCollider. Freely redistributable (BSD license)";
cannam@41 102 }
cannam@41 103
cannam@41 104 bool
cannam@41 105 AmplitudeFollower::initialise(size_t channels, size_t stepSize, size_t blockSize)
cannam@41 106 {
cannam@41 107 if (channels < getMinChannelCount() ||
cannam@41 108 channels > getMaxChannelCount()) return false;
cannam@41 109
cannam@41 110 m_stepSize = std::min(stepSize, blockSize);
cannam@41 111
cannam@41 112 // Translate the coefficients
cannam@41 113 // from their "convenient" 60dB convergence-time values
cannam@41 114 // to real coefficients
cannam@41 115 m_clampcoef = m_clampcoef==0.0 ? 0.0 : exp(log(0.1)/(m_clampcoef * m_inputSampleRate));
cannam@41 116 m_relaxcoef = m_relaxcoef==0.0 ? 0.0 : exp(log(0.1)/(m_relaxcoef * m_inputSampleRate));
cannam@41 117
cannam@41 118 return true;
cannam@41 119 }
cannam@41 120
cannam@41 121 void
cannam@41 122 AmplitudeFollower::reset()
cannam@41 123 {
cannam@41 124 m_previn = 0.0f;
cannam@41 125 }
cannam@41 126
cannam@41 127 AmplitudeFollower::OutputList
cannam@41 128 AmplitudeFollower::getOutputDescriptors() const
cannam@41 129 {
cannam@41 130 OutputList list;
cannam@41 131
cannam@41 132 OutputDescriptor sca;
cannam@49 133 sca.identifier = "amplitude";
cannam@49 134 sca.name = "Amplitude";
cannam@49 135 sca.description = "";
cannam@41 136 sca.unit = "V";
cannam@41 137 sca.hasFixedBinCount = true;
cannam@41 138 sca.binCount = 1;
cannam@41 139 sca.hasKnownExtents = false;
cannam@41 140 sca.isQuantized = false;
cannam@41 141 sca.sampleType = OutputDescriptor::OneSamplePerStep;
cannam@41 142 list.push_back(sca);
cannam@41 143
cannam@41 144 return list;
cannam@41 145 }
cannam@41 146
cannam@41 147 AmplitudeFollower::ParameterList
cannam@41 148 AmplitudeFollower::getParameterDescriptors() const
cannam@41 149 {
cannam@41 150 ParameterList list;
cannam@41 151
cannam@41 152 ParameterDescriptor att;
cannam@49 153 att.identifier = "attack";
cannam@49 154 att.name = "Attack time";
cannam@49 155 att.description = "";
cannam@41 156 att.unit = "s";
cannam@41 157 att.minValue = 0.0f;
cannam@41 158 att.maxValue = 1.f;
cannam@41 159 att.defaultValue = 0.01f;
cannam@41 160 att.isQuantized = false;
cannam@41 161
cannam@41 162 list.push_back(att);
cannam@41 163
cannam@41 164 ParameterDescriptor dec;
cannam@49 165 dec.identifier = "release";
cannam@49 166 dec.name = "Release time";
cannam@49 167 dec.description = "";
cannam@41 168 dec.unit = "s";
cannam@41 169 dec.minValue = 0.0f;
cannam@41 170 dec.maxValue = 1.f;
cannam@41 171 dec.defaultValue = 0.01f;
cannam@41 172 dec.isQuantized = false;
cannam@41 173
cannam@41 174 list.push_back(dec);
cannam@41 175
cannam@41 176 return list;
cannam@41 177 }
cannam@41 178
cannam@49 179 void AmplitudeFollower::setParameter(std::string paramid, float newval)
cannam@41 180 {
cannam@49 181 if (paramid == "attack") {
cannam@41 182 m_clampcoef = newval;
cannam@49 183 } else if (paramid == "release") {
cannam@41 184 m_relaxcoef = newval;
cannam@41 185 }
cannam@41 186 }
cannam@41 187
cannam@49 188 float AmplitudeFollower::getParameter(std::string paramid) const
cannam@41 189 {
cannam@49 190 if (paramid == "attack") {
cannam@41 191 return m_clampcoef;
cannam@49 192 } else if (paramid == "release") {
cannam@41 193 return m_relaxcoef;
cannam@41 194 }
cannam@41 195
cannam@41 196 return 0.0f;
cannam@41 197 }
cannam@41 198
cannam@41 199 AmplitudeFollower::FeatureSet
cannam@47 200 AmplitudeFollower::process(const float *const *inputBuffers,
cannam@47 201 Vamp::RealTime timestamp)
cannam@41 202 {
cannam@41 203 if (m_stepSize == 0) {
cannam@41 204 cerr << "ERROR: AmplitudeFollower::process: "
cannam@41 205 << "AmplitudeFollower has not been initialised"
cannam@41 206 << endl;
cannam@41 207 return FeatureSet();
cannam@41 208 }
cannam@41 209
cannam@41 210 float previn = m_previn;
cannam@41 211
cannam@41 212 FeatureSet returnFeatures;
cannam@41 213
cannam@41 214 float val;
cannam@41 215 float peak = 0.0f;
cannam@41 216
cannam@41 217 for (size_t i = 0; i < m_stepSize; ++i) {
cannam@41 218
cannam@41 219 val = fabs(inputBuffers[0][i]);
cannam@41 220
cannam@41 221 if (val < previn) {
cannam@41 222 val = val + (previn - val) * m_relaxcoef;
cannam@41 223 } else {
cannam@41 224 val = val + (previn - val) * m_clampcoef;
cannam@41 225 }
cannam@41 226
cannam@41 227 if (val > peak) peak = val;
cannam@41 228 previn = val;
cannam@41 229 }
cannam@41 230
cannam@41 231 m_previn = previn;
cannam@41 232
cannam@41 233 // Now store the "feature" (peak amp) for this sample
cannam@41 234 Feature feature;
cannam@41 235 feature.hasTimestamp = false;
cannam@41 236 feature.values.push_back(peak);
cannam@41 237 returnFeatures[0].push_back(feature);
cannam@41 238
cannam@41 239 return returnFeatures;
cannam@41 240 }
cannam@41 241
cannam@41 242 AmplitudeFollower::FeatureSet
cannam@41 243 AmplitudeFollower::getRemainingFeatures()
cannam@41 244 {
cannam@41 245 return FeatureSet();
cannam@41 246 }
cannam@41 247