Mercurial > hg > svcore
comparison data/model/FFTModel.cpp @ 1573:f04038819c26 spectrogramparam
Introduce & make use of faster MovingMedian class (now with resize capability)
author | Chris Cannam |
---|---|
date | Thu, 08 Nov 2018 15:02:30 +0000 |
parents | 5fe24e4af12c |
children | 054bbf17ac17 |
comparison
equal
deleted
inserted
replaced
1572:c36ffc195988 | 1573:f04038819c26 |
---|---|
18 | 18 |
19 #include "base/Profiler.h" | 19 #include "base/Profiler.h" |
20 #include "base/Pitch.h" | 20 #include "base/Pitch.h" |
21 #include "base/HitCount.h" | 21 #include "base/HitCount.h" |
22 #include "base/Debug.h" | 22 #include "base/Debug.h" |
23 #include "base/MovingMedian.h" | |
23 | 24 |
24 #include <algorithm> | 25 #include <algorithm> |
25 | 26 |
26 #include <cassert> | 27 #include <cassert> |
27 #include <deque> | 28 #include <deque> |
427 // exceed the median. For pitch adaptivity, we adjust the window | 428 // exceed the median. For pitch adaptivity, we adjust the window |
428 // size to a roughly constant pitch range (about four tones). | 429 // size to a roughly constant pitch range (about four tones). |
429 | 430 |
430 sv_samplerate_t sampleRate = getSampleRate(); | 431 sv_samplerate_t sampleRate = getSampleRate(); |
431 | 432 |
432 deque<float> window; | |
433 vector<int> inrange; | 433 vector<int> inrange; |
434 float dist = 0.5; | 434 float dist = 0.5; |
435 | 435 |
436 int medianWinSize = getPeakPickWindowSize(type, sampleRate, ymin, dist); | 436 int medianWinSize = getPeakPickWindowSize(type, sampleRate, ymin, dist); |
437 int halfWin = medianWinSize/2; | 437 int halfWin = medianWinSize/2; |
438 | |
439 MovingMedian<float> window(medianWinSize); | |
438 | 440 |
439 int binmin; | 441 int binmin; |
440 if (ymin > halfWin) binmin = ymin - halfWin; | 442 if (ymin > halfWin) binmin = ymin - halfWin; |
441 else binmin = 0; | 443 else binmin = 0; |
442 | 444 |
448 | 450 |
449 for (int bin = binmin; bin <= binmax; ++bin) { | 451 for (int bin = binmin; bin <= binmax; ++bin) { |
450 | 452 |
451 float value = values[bin]; | 453 float value = values[bin]; |
452 | 454 |
453 window.push_back(value); | |
454 | |
455 // so-called median will actually be the dist*100'th percentile | 455 // so-called median will actually be the dist*100'th percentile |
456 medianWinSize = getPeakPickWindowSize(type, sampleRate, bin, dist); | 456 medianWinSize = getPeakPickWindowSize(type, sampleRate, bin, dist); |
457 | |
458 halfWin = medianWinSize/2; | 457 halfWin = medianWinSize/2; |
459 | 458 |
460 while ((int)window.size() > medianWinSize) { | 459 int actualSize = std::min(medianWinSize, bin - binmin + 1); |
461 window.pop_front(); | 460 window.resize(actualSize); |
462 } | 461 window.setPercentile(dist * 100.0); |
463 | 462 window.push(value); |
464 int actualSize = int(window.size()); | |
465 | 463 |
466 if (type == MajorPitchAdaptivePeaks) { | 464 if (type == MajorPitchAdaptivePeaks) { |
467 if (ymax + halfWin < nv) binmax = ymax + halfWin; | 465 if (ymax + halfWin < nv) binmax = ymax + halfWin; |
468 else binmax = nv - 1; | 466 else binmax = nv - 1; |
469 } | 467 } |
470 | 468 |
471 vector<float> sorted(window.begin(), window.end()); | 469 float median = window.get(); |
472 sort(sorted.begin(), sorted.end()); | |
473 float median = sorted[int(float(sorted.size()) * dist)]; | |
474 | 470 |
475 int centrebin = 0; | 471 int centrebin = 0; |
476 if (bin > actualSize/2) centrebin = bin - actualSize/2; | 472 if (bin > actualSize/2) centrebin = bin - actualSize/2; |
477 | 473 |
478 while (centrebin > prevcentre || bin == binmin) { | 474 while (centrebin > prevcentre || bin == binmin) { |