comparison plugins/Silence.cpp @ 20:8c939fff7ee1

* First bit of Vamp v2 work -- add an optional duration to features in a backward compatible way. Warning: this code is unstable and experimental and may change significantly in the coming weeks.
author Chris Cannam <cannam@all-day-breakfast.com>
date Thu, 17 Jul 2008 08:51:13 +0000
parents 70472f9558da
children a83125c623f0
comparison
equal deleted inserted replaced
19:713c8b6fbf81 20:8c939fff7ee1
2 2
3 /* 3 /*
4 Vamp feature extraction plugins using Paul Brossier's Aubio library. 4 Vamp feature extraction plugins using Paul Brossier's Aubio library.
5 5
6 Centre for Digital Music, Queen Mary, University of London. 6 Centre for Digital Music, Queen Mary, University of London.
7 This file copyright 2006 Chris Cannam. 7 This file copyright 2006-2008 Chris Cannam and QMUL.
8 8
9 This program is free software; you can redistribute it and/or 9 This program is free software; you can redistribute it and/or
10 modify it under the terms of the GNU General Public License as 10 modify it under the terms of the GNU General Public License as
11 published by the Free Software Foundation; either version 2 of the 11 published by the Free Software Foundation; either version 2 of the
12 License, or (at your option) any later version. See the file 12 License, or (at your option) any later version. See the file
19 using std::string; 19 using std::string;
20 using std::vector; 20 using std::vector;
21 using std::cerr; 21 using std::cerr;
22 using std::endl; 22 using std::endl;
23 23
24 Silence::Silence(float inputSampleRate) : 24 Silence::Silence(float inputSampleRate, unsigned int apiVersion) :
25 Plugin(inputSampleRate), 25 Plugin(inputSampleRate),
26 m_apiVersion(apiVersion),
26 m_ibuf(0), 27 m_ibuf(0),
27 m_pbuf(0), 28 m_pbuf(0),
28 m_tmpptrs(0), 29 m_tmpptrs(0),
29 m_threshold(-80), 30 m_threshold(-80),
30 m_prevSilent(false), 31 m_prevSilent(false),
31 m_first(true) 32 m_first(true)
32 { 33 {
34 if (m_apiVersion == 1) {
35 cerr << "vamp-aubio: WARNING: using compatibility version 1 of the Vamp API for silence\n"
36 << "detector plugin: upgrade your host to v2 for proper duration support" << endl;
37 }
33 } 38 }
34 39
35 Silence::~Silence() 40 Silence::~Silence()
36 { 41 {
37 if (m_ibuf) del_fvec(m_ibuf); 42 if (m_ibuf) del_fvec(m_ibuf);
64 } 69 }
65 70
66 int 71 int
67 Silence::getPluginVersion() const 72 Silence::getPluginVersion() const
68 { 73 {
69 return 1; 74 if (m_apiVersion == 1) return 2;
75 return 3;
70 } 76 }
71 77
72 string 78 string
73 Silence::getCopyright() const 79 Silence::getCopyright() const
74 { 80 {
148 Silence::getOutputDescriptors() const 154 Silence::getOutputDescriptors() const
149 { 155 {
150 OutputList list; 156 OutputList list;
151 157
152 OutputDescriptor d; 158 OutputDescriptor d;
153 d.identifier = "silencestart"; 159
154 d.name = "Beginnings of Silent Regions"; 160 if (m_apiVersion == 1) {
155 d.description = "Return a single instant at the point where each silent region begins"; 161
156 d.hasFixedBinCount = true; 162 d.identifier = "silencestart";
157 d.binCount = 0; 163 d.name = "Beginnings of Silent Regions";
158 d.sampleType = OutputDescriptor::VariableSampleRate; 164 d.description = "Return a single instant at the point where each silent region begins";
159 d.sampleRate = 0; 165 d.hasFixedBinCount = true;
160 list.push_back(d); 166 d.binCount = 0;
161 167 d.hasKnownExtents = false;
162 d.identifier = "silenceend"; 168 d.sampleType = OutputDescriptor::VariableSampleRate;
163 d.name = "Ends of Silent Regions"; 169 d.sampleRate = 0;
164 d.description = "Return a single instant at the point where each silent region ends"; 170 list.push_back(d);
165 d.hasFixedBinCount = true; 171
166 d.binCount = 0; 172 d.identifier = "silenceend";
167 d.sampleType = OutputDescriptor::VariableSampleRate; 173 d.name = "Ends of Silent Regions";
168 d.sampleRate = 0; 174 d.description = "Return a single instant at the point where each silent region ends";
169 list.push_back(d); 175 d.hasFixedBinCount = true;
176 d.binCount = 0;
177 d.hasKnownExtents = false;
178 d.sampleType = OutputDescriptor::VariableSampleRate;
179 d.sampleRate = 0;
180 list.push_back(d);
181
182 } else {
183
184 d.identifier = "silent";
185 d.name = "Silent Regions";
186 d.description = "Return an interval covering each silent region";
187 d.hasFixedBinCount = true;
188 d.binCount = 0;
189 d.hasKnownExtents = false;
190 d.sampleType = OutputDescriptor::VariableSampleRate;
191 d.sampleRate = 0;
192 list.push_back(d);
193
194 d.identifier = "noisy";
195 d.name = "Non-Silent Regions";
196 d.description = "Return an interval covering each non-silent region";
197 d.hasFixedBinCount = true;
198 d.binCount = 0;
199 d.hasKnownExtents = false;
200 d.sampleType = OutputDescriptor::VariableSampleRate;
201 d.sampleRate = 0;
202 list.push_back(d);
203 }
170 204
171 d.identifier = "silencelevel"; 205 d.identifier = "silencelevel";
172 d.name = "Silence Test"; 206 d.name = "Silence Test";
173 d.description = "Return a function that switches from 1 to 0 when silence falls, and back again when it ends"; 207 d.description = "Return a function that switches from 1 to 0 when silence falls, and back again when it ends";
174 d.hasFixedBinCount = true; 208 d.hasFixedBinCount = true;
247 Feature feature; 281 Feature feature;
248 feature.hasTimestamp = true; 282 feature.hasTimestamp = true;
249 feature.timestamp = featureStamp; 283 feature.timestamp = featureStamp;
250 feature.values.push_back(silent ? 0 : 1); 284 feature.values.push_back(silent ? 0 : 1);
251 returnFeatures[2].push_back(feature); 285 returnFeatures[2].push_back(feature);
286
252 feature.values.clear(); 287 feature.values.clear();
253 288
254 if (silent) { 289 if (m_apiVersion == 1) {
255 returnFeatures[0].push_back(feature); 290 if (silent) {
291 returnFeatures[0].push_back(feature);
292 } else {
293 returnFeatures[1].push_back(feature);
294 }
256 } else { 295 } else {
257 returnFeatures[1].push_back(feature); 296 if (!m_first) {
258 } 297 feature.timestamp = m_lastChange;
298 feature.hasDuration = true;
299 feature.duration = featureStamp - m_lastChange;
300 if (silent) {
301 // becoming silent, so this is a non-silent region
302 returnFeatures[1].push_back(feature);
303 } else {
304 // becoming non-silent, so this is a silent region
305 returnFeatures[0].push_back(feature);
306 }
307 }
308 m_lastChange = featureStamp;
309 }
259 310
260 m_prevSilent = silent; 311 m_prevSilent = silent;
261 m_first = false; 312 m_first = false;
262 } 313 }
263 314
266 // having to allocate new storage for it 317 // having to allocate new storage for it
267 smpl_t **tmpdata = m_ibuf->data; 318 smpl_t **tmpdata = m_ibuf->data;
268 m_ibuf->data = m_pbuf->data; 319 m_ibuf->data = m_pbuf->data;
269 m_pbuf->data = tmpdata; 320 m_pbuf->data = tmpdata;
270 321
322 m_lastTimestamp = timestamp;
323
271 return returnFeatures; 324 return returnFeatures;
272 } 325 }
273 326
274 Silence::FeatureSet 327 Silence::FeatureSet
275 Silence::getRemainingFeatures() 328 Silence::getRemainingFeatures()
276 { 329 {
330 FeatureSet returnFeatures;
331
332 if (m_prevSilent) {
333 if (m_lastTimestamp > m_lastChange) {
334 Feature feature;
335 feature.hasTimestamp = true;
336 feature.timestamp = m_lastChange;
337 feature.hasDuration = true;
338 feature.duration = m_lastTimestamp - m_lastChange;
339 if (m_prevSilent) {
340 returnFeatures[0].push_back(feature);
341 } else {
342 returnFeatures[1].push_back(feature);
343 }
344 }
345 }
346
277 return FeatureSet(); 347 return FeatureSet();
278 } 348 }
279 349