libmain.cpp, plugins/: update to GPLv3
[vamp-aubio-plugins.git] / plugins / Pitch.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 file is part of vamp-aubio-plugins.
10
11     vamp-aubio is free software: you can redistribute it and/or modify
12     it under the terms of the GNU General Public License as published by
13     the Free Software Foundation, either version 3 of the License, or
14     (at your option) any later version.
15
16     vamp-aubio is distributed in the hope that it will be useful,
17     but WITHOUT ANY WARRANTY; without even the implied warranty of
18     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19     GNU General Public License for more details.
20
21     You should have received a copy of the GNU General Public License
22     along with aubio.  If not, see <http://www.gnu.org/licenses/>.
23
24 */
25
26 #include <math.h>
27 #include "Pitch.h"
28
29 using std::string;
30 using std::vector;
31 using std::cerr;
32 using std::endl;
33
34 Pitch::Pitch(float inputSampleRate) :
35     Plugin(inputSampleRate),
36     m_ibuf(0),
37     m_obuf(0),
38     m_pitchdet(0),
39     m_pitchtype(PitchYinFFT),
40     m_minfreq(aubio_miditofreq(32)),
41     m_maxfreq(aubio_miditofreq(95)),
42     m_silence(-90),
43     m_wrapRange(false),
44     m_stepSize(0),
45     m_blockSize(0)
46 {
47 }
48
49 Pitch::~Pitch()
50 {
51     if (m_pitchdet) del_aubio_pitch(m_pitchdet);
52     if (m_ibuf) del_fvec(m_ibuf);
53     if (m_obuf) del_fvec(m_obuf);
54 }
55
56 string
57 Pitch::getIdentifier() const
58 {
59     return "aubiopitch";
60 }
61
62 string
63 Pitch::getName() const
64 {
65     return "Aubio Pitch Detector";
66 }
67
68 string
69 Pitch::getDescription() const
70 {
71     return "Track estimated note pitches";
72 }
73
74 string
75 Pitch::getMaker() const
76 {
77     return "Paul Brossier (plugin by Chris Cannam)";
78 }
79
80 int
81 Pitch::getPluginVersion() const
82 {
83     return 3;
84 }
85
86 string
87 Pitch::getCopyright() const
88 {
89     return "GPL";
90 }
91
92 bool
93 Pitch::initialise(size_t channels, size_t stepSize, size_t blockSize)
94 {
95     if (channels != 1) {
96         std::cerr << "Pitch::initialise: channels must be 1" << std::endl;
97         return false;
98     }
99
100     m_stepSize = stepSize;
101     m_blockSize = blockSize;
102
103     m_ibuf = new_fvec(stepSize);
104     m_obuf = new_fvec(1);
105
106     reset();
107
108     return true;
109 }
110
111 void
112 Pitch::reset()
113 {
114     if (m_pitchdet) del_aubio_pitch(m_pitchdet);
115
116     m_pitchdet = new_aubio_pitch
117         (const_cast<char *>(getAubioNameForPitchType(m_pitchtype)),
118          m_blockSize,
119          m_stepSize,
120          lrintf(m_inputSampleRate));
121
122     aubio_pitch_set_unit(m_pitchdet, const_cast<char *>("freq"));
123 }
124
125 size_t
126 Pitch::getPreferredStepSize() const
127 {
128     return 512;
129 }
130
131 size_t
132 Pitch::getPreferredBlockSize() const
133 {
134     return 2048;
135 }
136
137 Pitch::ParameterList
138 Pitch::getParameterDescriptors() const
139 {
140     ParameterList list;
141     
142     ParameterDescriptor desc;
143     desc.identifier = "pitchtype";
144     desc.name = "Pitch Detection Function Type";
145     desc.description = "Type of pitch detection function to use";
146     desc.minValue = 0;
147     desc.maxValue = 4;
148     desc.defaultValue = (int)PitchYinFFT;
149     desc.isQuantized = true;
150     desc.quantizeStep = 1;
151     desc.valueNames.push_back("YIN Frequency Estimator");
152     desc.valueNames.push_back("Spectral Comb");
153     desc.valueNames.push_back("Schmitt");
154     desc.valueNames.push_back("Fast Harmonic Comb");
155     desc.valueNames.push_back("YIN with FFT");
156     list.push_back(desc);
157
158     desc = ParameterDescriptor();
159     desc.identifier = "minfreq";
160     desc.name = "Minimum Fundamental Frequency";
161     desc.description = "Lowest frequency to look for";
162     desc.minValue = 1;
163     desc.maxValue = m_inputSampleRate/2;
164     desc.defaultValue = aubio_miditofreq(32);
165     desc.unit = "Hz";
166     desc.isQuantized = false;
167     list.push_back(desc);
168
169     desc = ParameterDescriptor();
170     desc.identifier = "maxfreq";
171     desc.name = "Maximum Fundamental Frequency";
172     desc.description = "Highest frequency to look for";
173     desc.minValue = 1;
174     desc.maxValue = m_inputSampleRate/2;
175     desc.defaultValue = aubio_miditofreq(95);
176     desc.unit = "Hz";
177     desc.isQuantized = false;
178     list.push_back(desc);
179
180     desc = ParameterDescriptor();
181     desc.identifier = "wraprange";
182     desc.name = "Fold Higher or Lower Frequencies into Range";
183     desc.description = "Frequencies detected outside the range will be transposed to higher or lower octaves";
184     desc.minValue = 0;
185     desc.maxValue = 1;
186     desc.defaultValue = 0;
187     desc.isQuantized = true;
188     desc.quantizeStep = 1;
189     list.push_back(desc);
190
191     desc = ParameterDescriptor();
192     desc.identifier = "silencethreshold";
193     desc.name = "Silence Threshold";
194     desc.description = "Silence threshold, the higher the least detection";
195     desc.minValue = -120;
196     desc.maxValue = 0;
197     desc.defaultValue = -90;
198     desc.unit = "dB";
199     desc.isQuantized = false;
200     list.push_back(desc);
201
202     return list;
203 }
204
205 float
206 Pitch::getParameter(std::string param) const
207 {
208     if (param == "pitchtype") {
209         return m_pitchtype;
210     } else if (param == "minfreq") {
211         return m_minfreq;
212     } else if (param == "maxfreq") {
213         return m_maxfreq;
214     } else if (param == "wraprange") {
215         return m_wrapRange ? 1.0 : 0.0;
216     } else if (param == "silencethreshold") {
217         return m_silence;
218     } else {
219         return 0.0;
220     }
221 }
222
223 void
224 Pitch::setParameter(std::string param, float value)
225 {
226     if (param == "pitchtype") {
227         switch (lrintf(value)) {
228         case 0: m_pitchtype = PitchYin; break;
229         case 1: m_pitchtype = PitchMComb; break;
230         case 2: m_pitchtype = PitchSchmitt; break;
231         case 3: m_pitchtype = PitchFComb; break;
232         case 4: m_pitchtype = PitchYinFFT; break;
233         }
234     } else if (param == "minfreq") {
235         m_minfreq = value;
236     } else if (param == "maxfreq") {
237         m_maxfreq = value;
238     } else if (param == "wraprange") {
239         m_wrapRange = (value > 0.5);
240     } else if (param == "silencethreshold") {
241         m_silence = value;
242     }
243 }
244
245 Pitch::OutputList
246 Pitch::getOutputDescriptors() const
247 {
248     OutputList list;
249
250     OutputDescriptor d;
251     d.identifier = "frequency";
252     d.name = "Fundamental Frequency";
253     d.description = "List of detected frequencies";
254     d.unit = "Hz";
255     d.hasFixedBinCount = true;
256     d.binCount = 1;
257     d.hasKnownExtents = false;
258     d.isQuantized = false;
259     d.sampleType = OutputDescriptor::VariableSampleRate;
260     d.sampleRate = 0;
261     if (m_stepSize != 0) {
262         d.sampleRate = m_inputSampleRate / m_stepSize;
263     }
264     list.push_back(d);
265
266     return list;
267 }
268
269 Pitch::FeatureSet
270 Pitch::process(const float *const *inputBuffers,
271                Vamp::RealTime timestamp)
272 {
273     FeatureSet returnFeatures;
274
275     if (m_stepSize == 0) {
276         std::cerr << "Pitch::process: Pitch plugin not initialised" << std::endl;
277         return returnFeatures;
278     }
279
280     for (size_t i = 0; i < m_stepSize; ++i) {
281         fvec_set_sample(m_ibuf, inputBuffers[0][i], i);
282     }
283
284     aubio_pitch_do(m_pitchdet, m_ibuf, m_obuf);
285     
286     float freq = m_obuf->data[0];
287
288     bool silent = aubio_silence_detection(m_ibuf, m_silence);
289     if (silent) {
290 //        std::cerr << "(silent)" << std::endl;
291         return returnFeatures;
292     }
293
294     if (m_wrapRange) {
295         while (freq > 0 && freq < m_minfreq) {
296             freq = freq * 2.0;
297         }
298         while (freq > m_maxfreq) {
299             freq = freq / 2.0;
300         }
301     }
302
303     if (freq < m_minfreq || freq > m_maxfreq) {
304         return returnFeatures;
305     }
306
307     Feature feature;
308     feature.hasTimestamp = true;
309     feature.timestamp = timestamp;
310     feature.values.push_back(freq);
311
312     returnFeatures[0].push_back(feature);
313     return returnFeatures;
314 }
315
316 Pitch::FeatureSet
317 Pitch::getRemainingFeatures()
318 {
319     return FeatureSet();
320 }
321