Mercurial > hg > silvet
comparison src/Silvet.cpp @ 165:f73be84f5c90
Use 20ms resolution in hq mode, 40ms only in draft mode
author | Chris Cannam |
---|---|
date | Tue, 20 May 2014 16:48:33 +0100 |
parents | 629c9525b815 |
children | 7979fa40c9f7 |
comparison
equal
deleted
inserted
replaced
164:629c9525b815 | 165:f73be84f5c90 |
---|---|
140 desc.minValue = 0; | 140 desc.minValue = 0; |
141 desc.maxValue = 1; | 141 desc.maxValue = 1; |
142 desc.defaultValue = 1; | 142 desc.defaultValue = 1; |
143 desc.isQuantized = true; | 143 desc.isQuantized = true; |
144 desc.quantizeStep = 1; | 144 desc.quantizeStep = 1; |
145 desc.valueNames.push_back("Draft: faster"); | 145 desc.valueNames.push_back("Draft (faster)"); |
146 desc.valueNames.push_back("Intensive: usually higher quality"); | 146 desc.valueNames.push_back("Intensive (higher quality)"); |
147 list.push_back(desc); | 147 list.push_back(desc); |
148 | 148 |
149 desc.identifier = "soloinstrument"; | 149 desc.identifier = "soloinstrument"; |
150 desc.name = "Instrument in recording"; | 150 desc.name = "Solo instrument"; |
151 desc.unit = ""; | 151 desc.unit = ""; |
152 desc.description = "The instrument known to be present in the recording, if there is only one"; | 152 desc.description = "The instrument known to be present in the recording, if there is only one"; |
153 desc.minValue = 0; | 153 desc.minValue = 0; |
154 desc.maxValue = m_instruments.size()-1; | 154 desc.maxValue = m_instruments.size()-1; |
155 desc.defaultValue = 0; | 155 desc.defaultValue = 0; |
297 params.threshold = 0.0005; | 297 params.threshold = 0.0005; |
298 params.window = CQParameters::Hann; //!!! todo: test whether it makes any difference | 298 params.window = CQParameters::Hann; //!!! todo: test whether it makes any difference |
299 | 299 |
300 m_cq = new CQSpectrogram(params, CQSpectrogram::InterpolateLinear); | 300 m_cq = new CQSpectrogram(params, CQSpectrogram::InterpolateLinear); |
301 | 301 |
302 m_colsPerSec = m_hqMode ? 50 : 25; | |
303 | |
302 for (int i = 0; i < (int)m_postFilter.size(); ++i) { | 304 for (int i = 0; i < (int)m_postFilter.size(); ++i) { |
303 delete m_postFilter[i]; | 305 delete m_postFilter[i]; |
304 } | 306 } |
305 m_postFilter.clear(); | 307 m_postFilter.clear(); |
306 for (int i = 0; i < processingNotes; ++i) { | 308 for (int i = 0; i < processingNotes; ++i) { |
307 m_postFilter.push_back(new MedianFilter<double>(3)); | 309 m_postFilter.push_back(new MedianFilter<double>(3)); |
308 } | 310 } |
309 m_pianoRoll.clear(); | 311 m_pianoRoll.clear(); |
310 m_columnCount = 0; | 312 m_columnCount = 0; |
311 m_reducedColumnCount = 0; | |
312 m_startTime = RealTime::zeroTime; | 313 m_startTime = RealTime::zeroTime; |
313 } | 314 } |
314 | 315 |
315 Silvet::FeatureSet | 316 Silvet::FeatureSet |
316 Silvet::process(const float *const *inputBuffers, Vamp::RealTime timestamp) | 317 Silvet::process(const float *const *inputBuffers, Vamp::RealTime timestamp) |
395 Silvet::Grid | 396 Silvet::Grid |
396 Silvet::preProcess(const Grid &in) | 397 Silvet::preProcess(const Grid &in) |
397 { | 398 { |
398 int width = in.size(); | 399 int width = in.size(); |
399 | 400 |
400 // reduce to 100 columns per second, or one column every 441 samples | 401 int spacing = processingSampleRate / m_colsPerSec; |
401 | 402 |
402 int spacing = processingSampleRate / 100; | 403 // need to be careful that col spacing is an integer number of samples! |
404 assert(spacing * m_colsPerSec == processingSampleRate); | |
403 | 405 |
404 Grid out; | 406 Grid out; |
405 | 407 |
406 // We count the CQ latency in terms of processing hops, but | 408 // We count the CQ latency in terms of processing hops, but |
407 // actually it probably isn't an exact number of hops so this | 409 // actually it probably isn't an exact number of hops so this |
408 // isn't quite accurate. But the small constant offset is | 410 // isn't quite accurate. But the small constant offset is |
409 // practically irrelevant compared to the jitter from the 40ms | 411 // practically irrelevant compared to the jitter from the frame |
410 // frame size we reduce to in a moment | 412 // size we reduce to in a moment |
411 int latentColumns = m_cq->getLatency() / m_cq->getColumnHop(); | 413 int latentColumns = m_cq->getLatency() / m_cq->getColumnHop(); |
412 | 414 |
413 for (int i = 0; i < width; ++i) { | 415 for (int i = 0; i < width; ++i) { |
414 | 416 |
415 if (m_columnCount < latentColumns) { | 417 if (m_columnCount < latentColumns) { |
447 MedianFilter<double>::filter(40, noiseLevel1); | 449 MedianFilter<double>::filter(40, noiseLevel1); |
448 for (int j = 0; j < processingHeight; ++j) { | 450 for (int j = 0; j < processingHeight; ++j) { |
449 outCol[j] = std::max(outCol[j] - noiseLevel2[j], 0.0); | 451 outCol[j] = std::max(outCol[j] - noiseLevel2[j], 0.0); |
450 } | 452 } |
451 | 453 |
452 // then we only use every fourth filtered column, for 25 | 454 out.push_back(outCol); |
453 // columns per second in the eventual grid | |
454 | |
455 if (m_reducedColumnCount % 4 == 0) { | |
456 out.push_back(outCol); | |
457 } | |
458 | |
459 ++m_reducedColumnCount; | |
460 } | 455 } |
461 | 456 |
462 ++m_columnCount; | 457 ++m_columnCount; |
463 } | 458 } |
464 | 459 |
509 // already, and if they haven't ended, we don't know their | 504 // already, and if they haven't ended, we don't know their |
510 // duration. | 505 // duration. |
511 | 506 |
512 int width = m_pianoRoll.size(); | 507 int width = m_pianoRoll.size(); |
513 | 508 |
514 //!!! adjust to only keep notes >= 100ms? or so | 509 double columnDuration = 1.0 / m_colsPerSec; |
515 int durationThreshold = 3; // columns | 510 |
511 // only keep notes >= 100ms or thereabouts | |
512 int durationThreshold = floor(0.1 / columnDuration); // columns | |
513 if (durationThreshold < 1) durationThreshold = 1; | |
516 | 514 |
517 FeatureList noteFeatures; | 515 FeatureList noteFeatures; |
518 | 516 |
519 if (width < durationThreshold + 1) { | 517 if (width < durationThreshold + 1) { |
520 m_pianoRoll.push_back(active); | 518 m_pianoRoll.push_back(active); |
521 return noteFeatures; | 519 return noteFeatures; |
522 } | 520 } |
523 | |
524 // we have 25 columns per second | |
525 double columnDuration = 1.0 / 25.0; | |
526 | 521 |
527 //!!! try: 20ms intervals in intensive mode | 522 //!!! try: 20ms intervals in intensive mode |
528 //!!! try: repeated note detection? (look for change in first derivative of the pitch matrix) | 523 //!!! try: repeated note detection? (look for change in first derivative of the pitch matrix) |
529 | 524 |
530 for (map<int, double>::const_iterator ni = m_pianoRoll[width-1].begin(); | 525 for (map<int, double>::const_iterator ni = m_pianoRoll[width-1].begin(); |