fix crash when copy'ing latent plugins
[ardour.git] / libs / vamp-plugins / AmplitudeFollower.cpp
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::getIdentifier() const
70 {
71     return "amplitudefollower";
72 }
73
74 string
75 AmplitudeFollower::getName() const
76 {
77     return "Amplitude Follower";
78 }
79
80 string
81 AmplitudeFollower::getDescription() const
82 {
83     return "Track the amplitude of the audio signal";
84 }
85
86 string
87 AmplitudeFollower::getMaker() const
88 {
89     return "Vamp SDK Example Plugins";
90 }
91
92 int
93 AmplitudeFollower::getPluginVersion() const
94 {
95     return 1;
96 }
97
98 string
99 AmplitudeFollower::getCopyright() const
100 {
101     return "Code copyright 2006 Dan Stowell; method from SuperCollider.  Freely redistributable (BSD license)";
102 }
103
104 bool
105 AmplitudeFollower::initialise(size_t channels, size_t stepSize, size_t blockSize)
106 {
107     if (channels < getMinChannelCount() ||
108         channels > getMaxChannelCount()) return false;
109
110     m_stepSize = std::min(stepSize, blockSize);
111
112     // Translate the coefficients
113     // from their "convenient" 60dB convergence-time values
114     // to real coefficients
115     m_clampcoef = m_clampcoef==0.0 ? 0.0 : exp(log(0.1)/(m_clampcoef * m_inputSampleRate));
116     m_relaxcoef = m_relaxcoef==0.0 ? 0.0 : exp(log(0.1)/(m_relaxcoef * m_inputSampleRate));
117
118     return true;
119 }
120
121 void
122 AmplitudeFollower::reset()
123 {
124     m_previn = 0.0f;
125 }
126
127 AmplitudeFollower::OutputList
128 AmplitudeFollower::getOutputDescriptors() const
129 {
130     OutputList list;
131
132     OutputDescriptor sca;
133     sca.identifier = "amplitude";
134     sca.name = "Amplitude";
135     sca.description = "";
136     sca.unit = "V";
137     sca.hasFixedBinCount = true;
138     sca.binCount = 1;
139     sca.hasKnownExtents = false;
140     sca.isQuantized = false;
141     sca.sampleType = OutputDescriptor::OneSamplePerStep;
142     list.push_back(sca);
143
144     return list;
145 }
146
147 AmplitudeFollower::ParameterList
148 AmplitudeFollower::getParameterDescriptors() const
149 {
150     ParameterList list;
151
152     ParameterDescriptor att;
153     att.identifier = "attack";
154     att.name = "Attack time";
155     att.description = "";
156     att.unit = "s";
157     att.minValue = 0.0f;
158     att.maxValue = 1.f;
159     att.defaultValue = 0.01f;
160     att.isQuantized = false;
161
162     list.push_back(att);
163
164     ParameterDescriptor dec;
165     dec.identifier = "release";
166     dec.name = "Release time";
167     dec.description = "";
168     dec.unit = "s";
169     dec.minValue = 0.0f;
170     dec.maxValue = 1.f;
171     dec.defaultValue = 0.01f;
172     dec.isQuantized = false;
173
174     list.push_back(dec);
175
176     return list;
177 }
178
179 void AmplitudeFollower::setParameter(std::string paramid, float newval)
180 {
181     if (paramid == "attack") {
182         m_clampcoef = newval;
183     } else if (paramid == "release") {
184         m_relaxcoef = newval;
185     }
186 }
187
188 float AmplitudeFollower::getParameter(std::string paramid) const
189 {
190     if (paramid == "attack") {
191         return m_clampcoef;
192     } else if (paramid == "release") {
193         return m_relaxcoef;
194     }
195
196     return 0.0f;
197 }
198
199 AmplitudeFollower::FeatureSet
200 AmplitudeFollower::process(const float *const *inputBuffers,
201                            Vamp::RealTime /*timestamp*/)
202 {
203     if (m_stepSize == 0) {
204         cerr << "ERROR: AmplitudeFollower::process: "
205              << "AmplitudeFollower has not been initialised"
206              << endl;
207         return FeatureSet();
208     }
209
210     float previn = m_previn;
211
212     FeatureSet returnFeatures;
213
214     float val;
215     float peak = 0.0f;
216
217     for (size_t i = 0; i < m_stepSize; ++i) {
218
219         val = fabs(inputBuffers[0][i]);
220
221         if (val < previn) {
222             val = val + (previn - val) * m_relaxcoef;
223         } else {
224             val = val + (previn - val) * m_clampcoef;
225         }
226
227         if (val > peak) peak = val;
228         previn = val;
229     }
230
231     m_previn = previn;
232
233     // Now store the "feature" (peak amp) for this sample
234     Feature feature;
235     feature.hasTimestamp = false;
236     feature.values.push_back(peak);
237     returnFeatures[0].push_back(feature);
238
239     return returnFeatures;
240 }
241
242 AmplitudeFollower::FeatureSet
243 AmplitudeFollower::getRemainingFeatures()
244 {
245     return FeatureSet();
246 }
247