| 53 |
53 |
m_slack(40),
|
| 54 |
54 |
m_sensitivity(10),
|
| 55 |
55 |
m_threshold(0.1),
|
|
56 |
m_fillGaps(false),
|
| 56 |
57 |
m_binFrom(0),
|
| 57 |
58 |
m_binTo(0),
|
| 58 |
59 |
m_bins(0),
|
| ... | ... | |
| 172 |
173 |
d.isQuantized = false;
|
| 173 |
174 |
list.push_back(d);
|
| 174 |
175 |
|
|
176 |
d.identifier = "fill";
|
|
177 |
d.name = "Fill f0 gaps within a note";
|
|
178 |
d.description = "Return an f0 value for every frame within each discovered note, interpolating results into any gaps in the measurement";
|
|
179 |
d.unit = ""; //!!! todo: convert this threshold to a meaningful unit!
|
|
180 |
d.minValue = 0;
|
|
181 |
d.maxValue = 1;
|
|
182 |
d.defaultValue = 0;
|
|
183 |
d.isQuantized = true;
|
|
184 |
d.quantizeStep = 1;
|
|
185 |
list.push_back(d);
|
|
186 |
|
| 175 |
187 |
return list;
|
| 176 |
188 |
}
|
| 177 |
189 |
|
| ... | ... | |
| 181 |
193 |
if (identifier == "sensitivity") return m_sensitivity;
|
| 182 |
194 |
else if (identifier == "slack") return m_slack;
|
| 183 |
195 |
else if (identifier == "threshold") return m_threshold;
|
|
196 |
else if (identifier == "fill") return (m_fillGaps ? 1 : 0);
|
| 184 |
197 |
return 0.f;
|
| 185 |
198 |
}
|
| 186 |
199 |
|
| ... | ... | |
| 190 |
203 |
if (identifier == "sensitivity") m_sensitivity = value;
|
| 191 |
204 |
else if (identifier == "slack") m_slack = value;
|
| 192 |
205 |
else if (identifier == "threshold") m_threshold = value;
|
|
206 |
else if (identifier == "fill") m_fillGaps = (value > 0.5);
|
| 193 |
207 |
}
|
| 194 |
208 |
|
| 195 |
209 |
CepstralPitchTracker::ProgramList
|
| ... | ... | |
| 308 |
322 |
CepstralPitchTracker::addFeaturesFrom(NoteHypothesis h, FeatureSet &fs)
|
| 309 |
323 |
{
|
| 310 |
324 |
NoteHypothesis::Estimates es = h.getAcceptedEstimates();
|
|
325 |
NoteHypothesis::Note n = h.getAveragedNote();
|
| 311 |
326 |
|
| 312 |
|
for (int i = 0; i < (int)es.size(); ++i) {
|
| 313 |
|
Feature f;
|
| 314 |
|
f.hasTimestamp = true;
|
| 315 |
|
f.timestamp = es[i].time;
|
| 316 |
|
f.values.push_back(es[i].freq);
|
| 317 |
|
fs[0].push_back(f);
|
|
327 |
if (!m_fillGaps) {
|
|
328 |
|
|
329 |
for (int i = 0; i < (int)es.size(); ++i) {
|
|
330 |
Feature f;
|
|
331 |
f.hasTimestamp = true;
|
|
332 |
f.timestamp = es[i].time;
|
|
333 |
f.values.push_back(es[i].freq);
|
|
334 |
fs[0].push_back(f);
|
|
335 |
}
|
|
336 |
|
|
337 |
} else {
|
|
338 |
|
|
339 |
int ix = 0;
|
|
340 |
RealTime increment = RealTime::frame2RealTime
|
|
341 |
(m_stepSize, m_inputSampleRate);
|
|
342 |
|
|
343 |
float freq = 0;
|
|
344 |
|
|
345 |
for (RealTime t = n.time; t < n.time + n.duration; t = t + increment) {
|
|
346 |
if (ix < (int)es.size() && t >= es[ix].time) {
|
|
347 |
freq = es[ix].freq;
|
|
348 |
++ix;
|
|
349 |
}
|
|
350 |
if (freq > 0) {
|
|
351 |
Feature f;
|
|
352 |
f.hasTimestamp = true;
|
|
353 |
f.timestamp = t;
|
|
354 |
f.values.push_back(freq);
|
|
355 |
fs[0].push_back(f);
|
|
356 |
}
|
|
357 |
}
|
| 318 |
358 |
}
|
| 319 |
359 |
|
| 320 |
360 |
Feature nf;
|
| 321 |
361 |
nf.hasTimestamp = true;
|
| 322 |
362 |
nf.hasDuration = true;
|
| 323 |
|
NoteHypothesis::Note n = h.getAveragedNote();
|
| 324 |
363 |
nf.timestamp = n.time;
|
| 325 |
364 |
nf.duration = n.duration;
|
| 326 |
365 |
nf.values.push_back(n.freq);
|