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;