comparison examples/AmplitudeFollower.cpp @ 41:31cd55174467

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