c4bc76a425959a0c89597275d0adfd8c20d4c883
[vamp-aubio-plugins.git] / plugins / Onset.cpp
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 "Onset.h"
19
20 using std::string;
21 using std::vector;
22 using std::cerr;
23 using std::endl;
24
25 Onset::Onset(float inputSampleRate) :
26     Plugin(inputSampleRate),
27     m_ibuf(0),
28     m_fftgrain(0),
29     m_onset(0),
30     m_pv(0),
31     m_peakpick(0),
32     m_onsetdet(0),
33     m_onsettype(aubio_onset_complex),
34     m_threshold(0.3),
35     m_silence(-90),
36     m_channelCount(1)
37 {
38 }
39
40 Onset::~Onset()
41 {
42     if (m_onsetdet) aubio_onsetdetection_free(m_onsetdet);
43     if (m_ibuf) del_fvec(m_ibuf);
44     if (m_onset) del_fvec(m_onset);
45     if (m_fftgrain) del_cvec(m_fftgrain);
46     if (m_pv) del_aubio_pvoc(m_pv);
47     if (m_peakpick) del_aubio_peakpicker(m_peakpick);
48 }
49
50 string
51 Onset::getName() const
52 {
53     return "aubioonset";
54 }
55
56 string
57 Onset::getDescription() const
58 {
59     return "Aubio Onset Detector";
60 }
61
62 string
63 Onset::getMaker() const
64 {
65     return "Paul Brossier (plugin by Chris Cannam)";
66 }
67
68 int
69 Onset::getPluginVersion() const
70 {
71     return 1;
72 }
73
74 string
75 Onset::getCopyright() const
76 {
77     return "GPL";
78 }
79
80 bool
81 Onset::initialise(size_t channels, size_t stepSize, size_t blockSize)
82 {
83     m_channelCount = channels;
84     m_stepSize = stepSize;
85     m_blockSize = blockSize;
86
87     m_ibuf = new_fvec(stepSize, channels);
88     m_onset = new_fvec(1, channels);
89     m_fftgrain = new_cvec(blockSize, channels);
90     m_pv = new_aubio_pvoc(blockSize, stepSize, channels);
91     m_peakpick = new_aubio_peakpicker(m_threshold);
92
93     m_onsetdet = new_aubio_onsetdetection(m_onsettype, blockSize, channels);
94
95     return true;
96 }
97
98 void
99 Onset::reset()
100 {
101 }
102
103 size_t
104 Onset::getPreferredStepSize() const
105 {
106     return 512;
107 }
108
109 size_t
110 Onset::getPreferredBlockSize() const
111 {
112     return 2*getPreferredStepSize();
113 }
114
115 Onset::ParameterList
116 Onset::getParameterDescriptors() const
117 {
118     ParameterList list;
119     
120     ParameterDescriptor desc;
121     desc.name = "onsettype";
122     desc.description = "Onset Detection Function Type";
123     desc.minValue = 0;
124     desc.maxValue = 6;
125     desc.defaultValue = (int)aubio_onset_complex;
126     desc.isQuantized = true;
127     desc.quantizeStep = 1;
128     desc.valueNames.push_back("Energy Based");
129     desc.valueNames.push_back("Spectral Difference");
130     desc.valueNames.push_back("High-Frequency Content");
131     desc.valueNames.push_back("Complex Domain");
132     desc.valueNames.push_back("Phase Deviation");
133     desc.valueNames.push_back("Kullback-Liebler");
134     desc.valueNames.push_back("Modified Kullback-Liebler");
135     list.push_back(desc);
136
137     desc = ParameterDescriptor();
138     desc.name = "peakpickthreshold";
139     desc.description = "Peak Picker Threshold";
140     desc.minValue = 0;
141     desc.maxValue = 1;
142     desc.defaultValue = 0.3;
143     desc.isQuantized = false;
144     list.push_back(desc);
145
146     desc = ParameterDescriptor();
147     desc.name = "silencethreshold";
148     desc.description = "Silence Threshold";
149     desc.minValue = -120;
150     desc.maxValue = 0;
151     desc.defaultValue = -90;
152     desc.unit = "dB";
153     desc.isQuantized = false;
154     list.push_back(desc);
155
156     return list;
157 }
158
159 float
160 Onset::getParameter(std::string param) const
161 {
162     if (param == "onsettype") {
163         return m_onsettype;
164     } else if (param == "peakpickthreshold") {
165         return m_threshold;
166     } else if (param == "silencethreshold") {
167         return m_silence;
168     } else {
169         return 0.0;
170     }
171 }
172
173 void
174 Onset::setParameter(std::string param, float value)
175 {
176     if (param == "onsettype") {
177         switch (lrintf(value)) {
178         case 0: m_onsettype = aubio_onset_energy; break;
179         case 1: m_onsettype = aubio_onset_specdiff; break;
180         case 2: m_onsettype = aubio_onset_hfc; break;
181         case 3: m_onsettype = aubio_onset_complex; break;
182         case 4: m_onsettype = aubio_onset_phase; break;
183         case 5: m_onsettype = aubio_onset_kl; break;
184         case 6: m_onsettype = aubio_onset_mkl; break;
185         }
186     } else if (param == "peakpickthreshold") {
187         m_threshold = value;
188     } else if (param == "silencethreshold") {
189         m_silence = value;
190     }
191 }
192
193 Onset::OutputList
194 Onset::getOutputDescriptors() const
195 {
196     OutputList list;
197
198     OutputDescriptor d;
199     d.name = "onsets";
200     d.unit = "";
201     d.description = "Onsets";
202     d.hasFixedBinCount = true;
203     d.binCount = 0;
204     d.sampleType = OutputDescriptor::OneSamplePerStep;
205     list.push_back(d);
206
207     d = OutputDescriptor();
208     d.name = "detectionfunction";
209     d.unit = "";
210     d.description = "Onset Detection Function";
211     d.hasFixedBinCount = true;
212     d.binCount = m_channelCount;
213     d.hasKnownExtents = false;
214     d.isQuantized = false;
215     d.sampleType = OutputDescriptor::OneSamplePerStep;
216     list.push_back(d);
217
218     return list;
219 }
220
221 Onset::FeatureSet
222 Onset::process(float **inputBuffers, Vamp::RealTime /* timestamp */)
223 {
224     for (size_t i = 0; i < m_stepSize; ++i) {
225         for (size_t j = 0; j < m_channelCount; ++j) {
226             fvec_write_sample(m_ibuf, inputBuffers[j][i], j, i);
227         }
228     }
229
230     aubio_pvoc_do(m_pv, m_ibuf, m_fftgrain);
231     aubio_onsetdetection(m_onsetdet, m_fftgrain, m_onset);
232
233     bool isonset = aubio_peakpick_pimrt(m_onset, m_peakpick);
234
235     if (isonset) {
236         if (aubio_silence_detection(m_ibuf, m_silence)) {
237             isonset = false;
238         }
239     }
240
241     FeatureSet returnFeatures;
242
243     if (isonset) {
244         Feature onsettime;
245         onsettime.hasTimestamp = false;
246         returnFeatures[0].push_back(onsettime);
247     }
248     Feature feature;
249     for (size_t j = 0; j < m_channelCount; ++j) {
250         feature.values.push_back(m_onset->data[j][0]);
251     }
252     returnFeatures[1].push_back(feature);
253
254     return returnFeatures;
255 }
256
257 Onset::FeatureSet
258 Onset::getRemainingFeatures()
259 {
260     return FeatureSet();
261 }
262