Mercurial > hg > vamp-aubio-plugins
comparison plugins/Silence.cpp @ 17:b85fbc77677b
* Add silence detector. But I'm not happy with its results: take a look at
the aubio silence detection code and see what's up
author | Chris Cannam <cannam@all-day-breakfast.com> |
---|---|
date | Tue, 09 Oct 2007 15:42:36 +0000 |
parents | |
children | 70472f9558da |
comparison
equal
deleted
inserted
replaced
16:8c154bb55af9 | 17:b85fbc77677b |
---|---|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ | |
2 | |
3 /* | |
4 Vamp feature extraction plugins using Paul Brossier's Aubio library. | |
5 | |
6 Centre for Digital Music, Queen Mary, University of London. | |
7 This file copyright 2006 Chris Cannam. | |
8 | |
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 | |
11 published by the Free Software Foundation; either version 2 of the | |
12 License, or (at your option) any later version. See the file | |
13 COPYING included with this distribution for more information. | |
14 | |
15 */ | |
16 | |
17 #include <math.h> | |
18 #include "Silence.h" | |
19 | |
20 using std::string; | |
21 using std::vector; | |
22 using std::cerr; | |
23 using std::endl; | |
24 | |
25 Silence::Silence(float inputSampleRate) : | |
26 Plugin(inputSampleRate), | |
27 m_ibuf(0), | |
28 m_pbuf(0), | |
29 m_tmpptrs(0), | |
30 m_threshold(-70), | |
31 m_prevSilent(false), | |
32 m_first(true) | |
33 { | |
34 } | |
35 | |
36 Silence::~Silence() | |
37 { | |
38 if (m_ibuf) del_fvec(m_ibuf); | |
39 if (m_pbuf) del_fvec(m_pbuf); | |
40 if (m_tmpptrs) delete[] m_tmpptrs; | |
41 } | |
42 | |
43 string | |
44 Silence::getIdentifier() const | |
45 { | |
46 return "aubiosilence"; | |
47 } | |
48 | |
49 string | |
50 Silence::getName() const | |
51 { | |
52 return "Aubio Silence Detector"; | |
53 } | |
54 | |
55 string | |
56 Silence::getDescription() const | |
57 { | |
58 return "Detect levels below a certain threshold"; | |
59 } | |
60 | |
61 string | |
62 Silence::getMaker() const | |
63 { | |
64 return "Paul Brossier (plugin by Chris Cannam)"; | |
65 } | |
66 | |
67 int | |
68 Silence::getPluginVersion() const | |
69 { | |
70 return 1; | |
71 } | |
72 | |
73 string | |
74 Silence::getCopyright() const | |
75 { | |
76 return "GPL"; | |
77 } | |
78 | |
79 bool | |
80 Silence::initialise(size_t channels, size_t stepSize, size_t blockSize) | |
81 { | |
82 m_channelCount = channels; | |
83 m_stepSize = stepSize; | |
84 m_blockSize = blockSize; | |
85 | |
86 m_ibuf = new_fvec(stepSize, channels); | |
87 m_pbuf = new_fvec(stepSize, channels); | |
88 m_tmpptrs = new smpl_t *[channels]; | |
89 | |
90 return true; | |
91 } | |
92 | |
93 void | |
94 Silence::reset() | |
95 { | |
96 m_first = true; | |
97 } | |
98 | |
99 size_t | |
100 Silence::getPreferredStepSize() const | |
101 { | |
102 return 1024; | |
103 } | |
104 | |
105 size_t | |
106 Silence::getPreferredBlockSize() const | |
107 { | |
108 return 1024; | |
109 } | |
110 | |
111 Silence::ParameterList | |
112 Silence::getParameterDescriptors() const | |
113 { | |
114 ParameterList list; | |
115 ParameterDescriptor desc; | |
116 | |
117 desc = ParameterDescriptor(); | |
118 desc.identifier = "silencethreshold"; | |
119 desc.name = "Silence Threshold"; | |
120 desc.minValue = -120; | |
121 desc.maxValue = 0; | |
122 desc.defaultValue = -70; | |
123 desc.unit = "dB"; | |
124 desc.isQuantized = false; | |
125 list.push_back(desc); | |
126 | |
127 return list; | |
128 } | |
129 | |
130 float | |
131 Silence::getParameter(std::string param) const | |
132 { | |
133 if (param == "silencethreshold") { | |
134 return m_threshold; | |
135 } else { | |
136 return 0.0; | |
137 } | |
138 } | |
139 | |
140 void | |
141 Silence::setParameter(std::string param, float value) | |
142 { | |
143 if (param == "silencethreshold") { | |
144 m_threshold = value; | |
145 } | |
146 } | |
147 | |
148 Silence::OutputList | |
149 Silence::getOutputDescriptors() const | |
150 { | |
151 OutputList list; | |
152 | |
153 OutputDescriptor d; | |
154 d.identifier = "silencestart"; | |
155 d.name = "Starts of Silent Regions"; | |
156 d.description = "Return a single instant at the point where each silent region begins"; | |
157 d.hasFixedBinCount = true; | |
158 d.binCount = 0; | |
159 d.sampleType = OutputDescriptor::VariableSampleRate; | |
160 list.push_back(d); | |
161 | |
162 d.identifier = "silenceend"; | |
163 d.name = "Ends of Silent Regions"; | |
164 d.description = "Return a single instant at the point where each silent region ends"; | |
165 d.hasFixedBinCount = true; | |
166 d.binCount = 0; | |
167 d.sampleType = OutputDescriptor::VariableSampleRate; | |
168 list.push_back(d); | |
169 | |
170 d.identifier = "silencelevel"; | |
171 d.name = "Silence Test"; | |
172 d.description = "Return a function that switches from 1 to 0 when silence falls, and back again when it ends"; | |
173 d.hasFixedBinCount = true; | |
174 d.binCount = 1; | |
175 d.hasKnownExtents = true; | |
176 d.minValue = 0; | |
177 d.maxValue = 1; | |
178 d.isQuantized = true; | |
179 d.quantizeStep = 1; | |
180 d.sampleType = OutputDescriptor::VariableSampleRate; | |
181 list.push_back(d); | |
182 | |
183 return list; | |
184 } | |
185 | |
186 Silence::FeatureSet | |
187 Silence::process(const float *const *inputBuffers, | |
188 Vamp::RealTime timestamp) | |
189 { | |
190 for (size_t i = 0; i < m_stepSize; ++i) { | |
191 for (size_t j = 0; j < m_channelCount; ++j) { | |
192 fvec_write_sample(m_ibuf, inputBuffers[j][i], j, i); | |
193 } | |
194 } | |
195 | |
196 bool silent = aubio_silence_detection(m_ibuf, m_threshold); | |
197 FeatureSet returnFeatures; | |
198 | |
199 if (m_first || m_prevSilent != silent) { | |
200 | |
201 Vamp::RealTime featureStamp = timestamp; | |
202 | |
203 if ((silent && !m_first) || !silent) { | |
204 | |
205 // refine our result | |
206 | |
207 long off = 0; | |
208 size_t incr = 16; | |
209 if (incr > m_stepSize/8) incr = m_stepSize/8; | |
210 | |
211 fvec_t vec; | |
212 vec.length = incr * 4; | |
213 vec.channels = m_channelCount; | |
214 vec.data = m_tmpptrs; | |
215 | |
216 if (silent) { | |
217 std::cerr << "silence at " << timestamp << std::endl; | |
218 } | |
219 | |
220 for (size_t i = 0; i < m_stepSize - incr * 4; i += incr) { | |
221 for (size_t j = 0; j < m_channelCount; ++j) { | |
222 m_tmpptrs[j] = m_ibuf->data[j] + i; | |
223 } | |
224 bool subsilent = aubio_silence_detection(&vec, m_threshold); | |
225 if (silent == subsilent) { | |
226 std::cerr << "silent == subsilent at " << i << " after" << std::endl; | |
227 off = i; | |
228 break; | |
229 } | |
230 } | |
231 | |
232 if (silent && (off == 0)) { | |
233 for (size_t i = 0; i < m_stepSize - incr; i += incr) { | |
234 for (size_t j = 0; j < m_channelCount; ++j) { | |
235 m_tmpptrs[j] = m_pbuf->data[j] + m_stepSize - i - incr; | |
236 } | |
237 bool subsilent = aubio_silence_detection(&vec, m_threshold); | |
238 if (!subsilent) { | |
239 std::cerr << "non-silence at " << i << " samples before" << std::endl; | |
240 off = -(long)i; | |
241 break; | |
242 } else { | |
243 std::cerr << "silence at " << i << " samples before" << std::endl; | |
244 } | |
245 } | |
246 } else { | |
247 } | |
248 | |
249 featureStamp = timestamp + Vamp::RealTime::frame2RealTime | |
250 (off, lrintf(m_inputSampleRate)); | |
251 } | |
252 | |
253 Feature feature; | |
254 feature.hasTimestamp = true; | |
255 feature.timestamp = featureStamp; | |
256 feature.values.push_back(silent ? 0 : 1); | |
257 returnFeatures[2].push_back(feature); | |
258 feature.values.clear(); | |
259 | |
260 if (silent) { | |
261 returnFeatures[0].push_back(feature); | |
262 } else { | |
263 returnFeatures[1].push_back(feature); | |
264 } | |
265 | |
266 m_prevSilent = silent; | |
267 m_first = false; | |
268 } | |
269 | |
270 // swap ibuf and pbuf data pointers, so that this block's data is | |
271 // available in pbuf when processing the next block, without | |
272 // having to allocate new storage for it | |
273 smpl_t **tmpdata = m_ibuf->data; | |
274 m_ibuf->data = m_pbuf->data; | |
275 m_pbuf->data = tmpdata; | |
276 | |
277 return returnFeatures; | |
278 } | |
279 | |
280 Silence::FeatureSet | |
281 Silence::getRemainingFeatures() | |
282 { | |
283 return FeatureSet(); | |
284 } | |
285 |