Revision 16:d717911aca3c CepstrumPitchTracker.cpp
| CepstrumPitchTracker.cpp | ||
|---|---|---|
| 31 | 31 |
|
| 32 | 32 |
using std::string; |
| 33 | 33 |
using std::vector; |
| 34 |
using Vamp::RealTime; |
|
| 34 | 35 |
|
| 35 | 36 |
CepstrumPitchTracker::Hypothesis::Hypothesis() |
| 36 | 37 |
{
|
| ... | ... | |
| 48 | 49 |
if (m_pending.empty()) {
|
| 49 | 50 |
return true; |
| 50 | 51 |
} |
| 52 |
|
|
| 53 |
Estimate first = m_pending[0]; |
|
| 51 | 54 |
Estimate last = m_pending[m_pending.size()-1]; |
| 55 |
|
|
| 56 |
// check we are within a relatively close tolerance of the last |
|
| 57 |
// candidate |
|
| 52 | 58 |
double r = s.freq / last.freq; |
| 53 | 59 |
int cents = lrint(1200.0 * (log(r) / log(2.0))); |
| 54 |
return (cents > -100 && cents < 100); |
|
| 60 |
if (cents < -40 || cents > 40) return false; |
|
| 61 |
|
|
| 62 |
// and within a wider tolerance of our starting candidate |
|
| 63 |
r = s.freq / first.freq; |
|
| 64 |
cents = lrint(1200.0 * (log(r) / log(2.0))); |
|
| 65 |
if (cents < -80 || cents > 80) return false; |
|
| 66 |
|
|
| 67 |
return true; |
|
| 55 | 68 |
} |
| 56 | 69 |
|
| 57 | 70 |
bool |
| ... | ... | |
| 145 | 158 |
} |
| 146 | 159 |
} |
| 147 | 160 |
|
| 161 |
CepstrumPitchTracker::Hypothesis::Note |
|
| 162 |
CepstrumPitchTracker::Hypothesis::getAveragedNote() |
|
| 163 |
{
|
|
| 164 |
Note n; |
|
| 165 |
|
|
| 166 |
if (!(m_state == Satisfied || m_state == Expired)) {
|
|
| 167 |
n.freq = 0.0; |
|
| 168 |
n.time = RealTime::zeroTime; |
|
| 169 |
n.duration = RealTime::zeroTime; |
|
| 170 |
return n; |
|
| 171 |
} |
|
| 172 |
|
|
| 173 |
n.time = m_pending.begin()->time; |
|
| 174 |
|
|
| 175 |
Estimates::iterator i = m_pending.end(); |
|
| 176 |
--i; |
|
| 177 |
n.duration = i->time - n.time; |
|
| 178 |
|
|
| 179 |
// just mean frequency for now, but this isn't at all right |
|
| 180 |
double acc = 0.0; |
|
| 181 |
for (int i = 0; i < m_pending.size(); ++i) {
|
|
| 182 |
acc += m_pending[i].freq; |
|
| 183 |
} |
|
| 184 |
acc /= m_pending.size(); |
|
| 185 |
n.freq = acc; |
|
| 186 |
|
|
| 187 |
return n; |
|
| 188 |
} |
|
| 189 |
|
|
| 148 | 190 |
void |
| 149 |
CepstrumPitchTracker::Hypothesis::addFeatures(FeatureList &fl)
|
|
| 191 |
CepstrumPitchTracker::Hypothesis::addFeatures(FeatureSet &fs)
|
|
| 150 | 192 |
{
|
| 151 | 193 |
for (int i = 0; i < m_pending.size(); ++i) {
|
| 152 | 194 |
Feature f; |
| 153 | 195 |
f.hasTimestamp = true; |
| 154 | 196 |
f.timestamp = m_pending[i].time; |
| 155 | 197 |
f.values.push_back(m_pending[i].freq); |
| 156 |
fl.push_back(f);
|
|
| 198 |
fs[0].push_back(f);
|
|
| 157 | 199 |
} |
| 200 |
|
|
| 201 |
Feature nf; |
|
| 202 |
nf.hasTimestamp = true; |
|
| 203 |
nf.hasDuration = true; |
|
| 204 |
Note n = getAveragedNote(); |
|
| 205 |
nf.timestamp = n.time; |
|
| 206 |
nf.duration = n.duration; |
|
| 207 |
nf.values.push_back(n.freq); |
|
| 208 |
fs[1].push_back(nf); |
|
| 158 | 209 |
} |
| 159 | 210 |
|
| 160 | 211 |
CepstrumPitchTracker::CepstrumPitchTracker(float inputSampleRate) : |
| ... | ... | |
| 303 | 354 |
d.hasDuration = false; |
| 304 | 355 |
outputs.push_back(d); |
| 305 | 356 |
|
| 357 |
d.identifier = "notes"; |
|
| 358 |
d.name = "Notes"; |
|
| 359 |
d.description = "Derived fixed-pitch note frequencies"; |
|
| 360 |
d.unit = "Hz"; |
|
| 361 |
d.hasFixedBinCount = true; |
|
| 362 |
d.binCount = 1; |
|
| 363 |
d.hasKnownExtents = true; |
|
| 364 |
d.minValue = m_fmin; |
|
| 365 |
d.maxValue = m_fmax; |
|
| 366 |
d.isQuantized = false; |
|
| 367 |
d.sampleType = OutputDescriptor::FixedSampleRate; |
|
| 368 |
d.sampleRate = (m_inputSampleRate / m_stepSize); |
|
| 369 |
d.hasDuration = true; |
|
| 370 |
outputs.push_back(d); |
|
| 371 |
|
|
| 306 | 372 |
return outputs; |
| 307 | 373 |
} |
| 308 | 374 |
|
| ... | ... | |
| 358 | 424 |
} |
| 359 | 425 |
|
| 360 | 426 |
CepstrumPitchTracker::FeatureSet |
| 361 |
CepstrumPitchTracker::process(const float *const *inputBuffers, Vamp::RealTime timestamp)
|
|
| 427 |
CepstrumPitchTracker::process(const float *const *inputBuffers, RealTime timestamp) |
|
| 362 | 428 |
{
|
| 363 | 429 |
FeatureSet fs; |
| 364 | 430 |
|
| ... | ... | |
| 466 | 532 |
} |
| 467 | 533 |
|
| 468 | 534 |
if (m_accepted.getState() == Hypothesis::Expired) {
|
| 469 |
m_accepted.addFeatures(fs[0]);
|
|
| 535 |
m_accepted.addFeatures(fs); |
|
| 470 | 536 |
} |
| 471 | 537 |
|
| 472 | 538 |
if (m_accepted.getState() == Hypothesis::Expired || |
| ... | ... | |
| 503 | 569 |
{
|
| 504 | 570 |
FeatureSet fs; |
| 505 | 571 |
if (m_accepted.getState() == Hypothesis::Satisfied) {
|
| 506 |
m_accepted.addFeatures(fs[0]);
|
|
| 572 |
m_accepted.addFeatures(fs); |
|
| 507 | 573 |
} |
| 508 | 574 |
return fs; |
| 509 | 575 |
} |
Also available in: Unified diff