Mercurial > hg > pyin
comparison PYIN.cpp @ 108:ae827f6c46c8 notes_refinement
introduced a variable for minimum note length
author | matthiasm |
---|---|
date | Mon, 26 Jan 2015 15:07:05 +0000 |
parents | 314c2d56625d |
children |
comparison
equal
deleted
inserted
replaced
107:314c2d56625d | 108:ae827f6c46c8 |
---|---|
43 m_oCandidateSalience(0), | 43 m_oCandidateSalience(0), |
44 m_oSmoothedPitchTrack(0), | 44 m_oSmoothedPitchTrack(0), |
45 m_oNotes(0), | 45 m_oNotes(0), |
46 m_threshDistr(2.0f), | 46 m_threshDistr(2.0f), |
47 m_outputUnvoiced(0.0f), | 47 m_outputUnvoiced(0.0f), |
48 m_onsetSensitivity(0.0), | 48 m_onsetSensitivity(0.6f), |
49 m_pruneThresh(0.07f), | |
49 m_pitchProb(0), | 50 m_pitchProb(0), |
50 m_timestamp(0), | 51 m_timestamp(0), |
51 m_level(0) | 52 m_level(0) |
52 { | 53 { |
53 } | 54 } |
170 d.name = "Onset sensitivity"; | 171 d.name = "Onset sensitivity"; |
171 d.description = "Adds additional note onsets when RMS increases."; | 172 d.description = "Adds additional note onsets when RMS increases."; |
172 d.unit = ""; | 173 d.unit = ""; |
173 d.minValue = 0.0f; | 174 d.minValue = 0.0f; |
174 d.maxValue = 1.0f; | 175 d.maxValue = 1.0f; |
175 d.defaultValue = 0.0f; | 176 d.defaultValue = 0.5f; |
177 d.isQuantized = false; | |
178 list.push_back(d); | |
179 | |
180 d.identifier = "prunethresh"; | |
181 d.valueNames.clear(); | |
182 d.name = "Duration pruning threshold."; | |
183 d.description = "Prune notes that are shorter than this value."; | |
184 d.unit = ""; | |
185 d.minValue = 0.0f; | |
186 d.maxValue = 0.2f; | |
187 d.defaultValue = 0.05f; | |
176 d.isQuantized = false; | 188 d.isQuantized = false; |
177 list.push_back(d); | 189 list.push_back(d); |
178 | 190 |
179 return list; | 191 return list; |
180 } | 192 } |
189 return m_outputUnvoiced; | 201 return m_outputUnvoiced; |
190 } | 202 } |
191 if (identifier == "onsetsensitivity") { | 203 if (identifier == "onsetsensitivity") { |
192 return m_onsetSensitivity; | 204 return m_onsetSensitivity; |
193 } | 205 } |
206 if (identifier == "prunethresh") { | |
207 return m_pruneThresh; | |
208 } | |
194 return 0.f; | 209 return 0.f; |
195 } | 210 } |
196 | 211 |
197 void | 212 void |
198 PYIN::setParameter(string identifier, float value) | 213 PYIN::setParameter(string identifier, float value) |
206 m_outputUnvoiced = value; | 221 m_outputUnvoiced = value; |
207 } | 222 } |
208 if (identifier == "onsetsensitivity") | 223 if (identifier == "onsetsensitivity") |
209 { | 224 { |
210 m_onsetSensitivity = value; | 225 m_onsetSensitivity = value; |
226 } | |
227 if (identifier == "prunethresh") | |
228 { | |
229 m_pruneThresh = value; | |
211 } | 230 } |
212 } | 231 } |
213 | 232 |
214 PYIN::ProgramList | 233 PYIN::ProgramList |
215 PYIN::getPrograms() const | 234 PYIN::getPrograms() const |
486 | 505 |
487 int onsetFrame = 0; | 506 int onsetFrame = 0; |
488 bool isVoiced = 0; | 507 bool isVoiced = 0; |
489 bool oldIsVoiced = 0; | 508 bool oldIsVoiced = 0; |
490 size_t nFrame = m_pitchProb.size(); | 509 size_t nFrame = m_pitchProb.size(); |
510 | |
511 float minNoteFrames = (m_inputSampleRate*m_pruneThresh) / m_stepSize; | |
491 | 512 |
492 std::vector<float> notePitchTrack; // collects pitches for one note at a time | 513 std::vector<float> notePitchTrack; // collects pitches for one note at a time |
493 for (size_t iFrame = 0; iFrame < nFrame; ++iFrame) | 514 for (size_t iFrame = 0; iFrame < nFrame; ++iFrame) |
494 { | 515 { |
495 isVoiced = mnOut[iFrame].noteState < 3 | 516 isVoiced = mnOut[iFrame].noteState < 3 |
496 && smoothedPitch[iFrame].size() > 0 | 517 && smoothedPitch[iFrame].size() > 0 |
497 && (iFrame >= nFrame-2 | 518 && (iFrame >= nFrame-2 |
498 || ((m_level[iFrame]/m_level[iFrame+2]) > m_onsetSensitivity)); | 519 || ((m_level[iFrame]/m_level[iFrame+2]) > m_onsetSensitivity)); |
499 // std::cerr << m_level[iFrame]/m_level[iFrame-1] << std::endl; | 520 // std::cerr << m_level[iFrame]/m_level[iFrame-1] << " " << isVoiced << std::endl; |
500 if (isVoiced && iFrame != nFrame-1) | 521 if (isVoiced && iFrame != nFrame-1) |
501 { | 522 { |
502 if (oldIsVoiced == 0) // beginning of a note | 523 if (oldIsVoiced == 0) // beginning of a note |
503 { | 524 { |
504 onsetFrame = iFrame; | 525 onsetFrame = iFrame; |
505 notePitchTrack.clear(); | |
506 } | 526 } |
507 float pitch = smoothedPitch[iFrame][0].first; | 527 float pitch = smoothedPitch[iFrame][0].first; |
508 notePitchTrack.push_back(pitch); // add to the note's pitch track | 528 notePitchTrack.push_back(pitch); // add to the note's pitch track |
509 } else { // not currently voiced | 529 } else { // not currently voiced |
510 if (oldIsVoiced == 1 && notePitchTrack.size() > 17) // end of note | 530 if (oldIsVoiced == 1) // end of note |
511 { | 531 { |
512 std::sort(notePitchTrack.begin(), notePitchTrack.end()); | 532 // std::cerr << notePitchTrack.size() << " " << minNoteFrames << std::endl; |
513 float medianPitch = notePitchTrack[notePitchTrack.size()/2]; | 533 if (notePitchTrack.size() >= minNoteFrames) |
514 float medianFreq = std::pow(2,(medianPitch - 69) / 12) * 440; | 534 { |
515 f.values.clear(); | 535 std::sort(notePitchTrack.begin(), notePitchTrack.end()); |
516 f.values.push_back(medianFreq); | 536 float medianPitch = notePitchTrack[notePitchTrack.size()/2]; |
517 f.timestamp = m_timestamp[onsetFrame]; | 537 float medianFreq = std::pow(2,(medianPitch - 69) / 12) * 440; |
518 f.duration = m_timestamp[iFrame] - m_timestamp[onsetFrame]; | 538 f.values.clear(); |
519 fs[m_oNotes].push_back(f); | 539 f.values.push_back(medianFreq); |
540 f.timestamp = m_timestamp[onsetFrame]; | |
541 f.duration = m_timestamp[iFrame] - m_timestamp[onsetFrame]; | |
542 fs[m_oNotes].push_back(f); | |
543 } | |
544 notePitchTrack.clear(); | |
520 } | 545 } |
521 } | 546 } |
522 oldIsVoiced = isVoiced; | 547 oldIsVoiced = isVoiced; |
523 } | 548 } |
524 return fs; | 549 return fs; |