Mercurial > hg > svcore
comparison data/model/FFTModel.cpp @ 1206:659372323b45 tony-2.0-integration
Merge latest SV 3.0 branch code
| author | Chris Cannam |
|---|---|
| date | Fri, 19 Aug 2016 15:58:57 +0100 |
| parents | 6f7a440b6218 |
| children | 6b847a59d908 |
comparison
equal
deleted
inserted
replaced
| 1136:e94719f941ba | 1206:659372323b45 |
|---|---|
| 96 FFTModel::Column | 96 FFTModel::Column |
| 97 FFTModel::getColumn(int x) const | 97 FFTModel::getColumn(int x) const |
| 98 { | 98 { |
| 99 auto cplx = getFFTColumn(x); | 99 auto cplx = getFFTColumn(x); |
| 100 Column col; | 100 Column col; |
| 101 col.reserve(int(cplx.size())); | 101 col.reserve(cplx.size()); |
| 102 for (auto c: cplx) col.push_back(abs(c)); | 102 for (auto c: cplx) col.push_back(abs(c)); |
| 103 return col; | 103 return move(col); |
| 104 } | |
| 105 | |
| 106 FFTModel::Column | |
| 107 FFTModel::getPhases(int x) const | |
| 108 { | |
| 109 auto cplx = getFFTColumn(x); | |
| 110 Column col; | |
| 111 col.reserve(cplx.size()); | |
| 112 for (auto c: cplx) { | |
| 113 col.push_back(arg(c)); | |
| 114 } | |
| 115 return move(col); | |
| 104 } | 116 } |
| 105 | 117 |
| 106 float | 118 float |
| 107 FFTModel::getMagnitudeAt(int x, int y) const | 119 FFTModel::getMagnitudeAt(int x, int y) const |
| 108 { | 120 { |
| 114 float | 126 float |
| 115 FFTModel::getMaximumMagnitudeAt(int x) const | 127 FFTModel::getMaximumMagnitudeAt(int x) const |
| 116 { | 128 { |
| 117 Column col(getColumn(x)); | 129 Column col(getColumn(x)); |
| 118 float max = 0.f; | 130 float max = 0.f; |
| 119 for (int i = 0; i < col.size(); ++i) { | 131 int n = int(col.size()); |
| 132 for (int i = 0; i < n; ++i) { | |
| 120 if (col[i] > max) max = col[i]; | 133 if (col[i] > max) max = col[i]; |
| 121 } | 134 } |
| 122 return max; | 135 return max; |
| 123 } | 136 } |
| 124 | 137 |
| 133 FFTModel::getValuesAt(int x, int y, float &re, float &im) const | 146 FFTModel::getValuesAt(int x, int y, float &re, float &im) const |
| 134 { | 147 { |
| 135 auto col = getFFTColumn(x); | 148 auto col = getFFTColumn(x); |
| 136 re = col[y].real(); | 149 re = col[y].real(); |
| 137 im = col[y].imag(); | 150 im = col[y].imag(); |
| 138 } | |
| 139 | |
| 140 bool | |
| 141 FFTModel::isColumnAvailable(int) const | |
| 142 { | |
| 143 //!!! | |
| 144 return true; | |
| 145 } | 151 } |
| 146 | 152 |
| 147 bool | 153 bool |
| 148 FFTModel::getMagnitudesAt(int x, float *values, int minbin, int count) const | 154 FFTModel::getMagnitudesAt(int x, float *values, int minbin, int count) const |
| 149 { | 155 { |
| 151 auto col = getFFTColumn(x); | 157 auto col = getFFTColumn(x); |
| 152 for (int i = 0; i < count; ++i) { | 158 for (int i = 0; i < count; ++i) { |
| 153 values[i] = abs(col[minbin + i]); | 159 values[i] = abs(col[minbin + i]); |
| 154 } | 160 } |
| 155 return true; | 161 return true; |
| 156 } | |
| 157 | |
| 158 float | |
| 159 FFTModel::getNormalizedMagnitudesAt(int x, float *values, int minbin, int count) const | |
| 160 { | |
| 161 if (!getMagnitudesAt(x, values, minbin, count)) return false; | |
| 162 if (count == 0) count = getHeight(); | |
| 163 float max = 0.f; | |
| 164 for (int i = 0; i < count; ++i) { | |
| 165 if (values[i] > max) max = values[i]; | |
| 166 } | |
| 167 if (max > 0.f) { | |
| 168 for (int i = 0; i < count; ++i) { | |
| 169 values[i] /= max; | |
| 170 } | |
| 171 } | |
| 172 return max; | |
| 173 } | 162 } |
| 174 | 163 |
| 175 bool | 164 bool |
| 176 FFTModel::getPhasesAt(int x, float *values, int minbin, int count) const | 165 FFTModel::getPhasesAt(int x, float *values, int minbin, int count) const |
| 177 { | 166 { |
| 311 if (m_cached.size() >= m_cacheSize) { | 300 if (m_cached.size() >= m_cacheSize) { |
| 312 m_cached.pop_front(); | 301 m_cached.pop_front(); |
| 313 } | 302 } |
| 314 m_cached.push_back(sc); | 303 m_cached.push_back(sc); |
| 315 | 304 |
| 316 return col; | 305 return move(col); |
| 317 } | 306 } |
| 318 | 307 |
| 319 bool | 308 bool |
| 320 FFTModel::estimateStableFrequency(int x, int y, double &frequency) | 309 FFTModel::estimateStableFrequency(int x, int y, double &frequency) |
| 321 { | 310 { |
| 352 | 341 |
| 353 return true; | 342 return true; |
| 354 } | 343 } |
| 355 | 344 |
| 356 FFTModel::PeakLocationSet | 345 FFTModel::PeakLocationSet |
| 357 FFTModel::getPeaks(PeakPickType type, int x, int ymin, int ymax) | 346 FFTModel::getPeaks(PeakPickType type, int x, int ymin, int ymax) const |
| 358 { | 347 { |
| 359 Profiler profiler("FFTModel::getPeaks"); | 348 Profiler profiler("FFTModel::getPeaks"); |
| 360 | 349 |
| 361 FFTModel::PeakLocationSet peaks; | 350 FFTModel::PeakLocationSet peaks; |
| 362 if (!isOK()) return peaks; | 351 if (!isOK()) return peaks; |
| 386 } | 375 } |
| 387 return peaks; | 376 return peaks; |
| 388 } | 377 } |
| 389 | 378 |
| 390 Column values = getColumn(x); | 379 Column values = getColumn(x); |
| 380 int nv = int(values.size()); | |
| 391 | 381 |
| 392 float mean = 0.f; | 382 float mean = 0.f; |
| 393 for (int i = 0; i < values.size(); ++i) mean += values[i]; | 383 for (int i = 0; i < nv; ++i) mean += values[i]; |
| 394 if (values.size() > 0) mean = mean / float(values.size()); | 384 if (nv > 0) mean = mean / float(values.size()); |
| 395 | 385 |
| 396 // For peak picking we use a moving median window, picking the | 386 // For peak picking we use a moving median window, picking the |
| 397 // highest value within each continuous region of values that | 387 // highest value within each continuous region of values that |
| 398 // exceed the median. For pitch adaptivity, we adjust the window | 388 // exceed the median. For pitch adaptivity, we adjust the window |
| 399 // size to a roughly constant pitch range (about four tones). | 389 // size to a roughly constant pitch range (about four tones). |
| 410 int binmin; | 400 int binmin; |
| 411 if (ymin > halfWin) binmin = ymin - halfWin; | 401 if (ymin > halfWin) binmin = ymin - halfWin; |
| 412 else binmin = 0; | 402 else binmin = 0; |
| 413 | 403 |
| 414 int binmax; | 404 int binmax; |
| 415 if (ymax + halfWin < values.size()) binmax = ymax + halfWin; | 405 if (ymax + halfWin < nv) binmax = ymax + halfWin; |
| 416 else binmax = values.size()-1; | 406 else binmax = nv - 1; |
| 417 | 407 |
| 418 int prevcentre = 0; | 408 int prevcentre = 0; |
| 419 | 409 |
| 420 for (int bin = binmin; bin <= binmax; ++bin) { | 410 for (int bin = binmin; bin <= binmax; ++bin) { |
| 421 | 411 |
| 432 } | 422 } |
| 433 | 423 |
| 434 int actualSize = int(window.size()); | 424 int actualSize = int(window.size()); |
| 435 | 425 |
| 436 if (type == MajorPitchAdaptivePeaks) { | 426 if (type == MajorPitchAdaptivePeaks) { |
| 437 if (ymax + halfWin < values.size()) binmax = ymax + halfWin; | 427 if (ymax + halfWin < nv) binmax = ymax + halfWin; |
| 438 else binmax = values.size()-1; | 428 else binmax = nv - 1; |
| 439 } | 429 } |
| 440 | 430 |
| 441 deque<float> sorted(window); | 431 deque<float> sorted(window); |
| 442 sort(sorted.begin(), sorted.end()); | 432 sort(sorted.begin(), sorted.end()); |
| 443 float median = sorted[int(float(sorted.size()) * dist)]; | 433 float median = sorted[int(float(sorted.size()) * dist)]; |
| 453 | 443 |
| 454 if (centre > median) { | 444 if (centre > median) { |
| 455 inrange.push_back(centrebin); | 445 inrange.push_back(centrebin); |
| 456 } | 446 } |
| 457 | 447 |
| 458 if (centre <= median || centrebin+1 == values.size()) { | 448 if (centre <= median || centrebin+1 == nv) { |
| 459 if (!inrange.empty()) { | 449 if (!inrange.empty()) { |
| 460 int peakbin = 0; | 450 int peakbin = 0; |
| 461 float peakval = 0.f; | 451 float peakval = 0.f; |
| 462 for (int i = 0; i < (int)inrange.size(); ++i) { | 452 for (int i = 0; i < (int)inrange.size(); ++i) { |
| 463 if (i == 0 || values[inrange[i]] > peakval) { | 453 if (i == 0 || values[inrange[i]] > peakval) { |
| 499 return medianWinSize; | 489 return medianWinSize; |
| 500 } | 490 } |
| 501 | 491 |
| 502 FFTModel::PeakSet | 492 FFTModel::PeakSet |
| 503 FFTModel::getPeakFrequencies(PeakPickType type, int x, | 493 FFTModel::getPeakFrequencies(PeakPickType type, int x, |
| 504 int ymin, int ymax) | 494 int ymin, int ymax) const |
| 505 { | 495 { |
| 506 Profiler profiler("FFTModel::getPeakFrequencies"); | 496 Profiler profiler("FFTModel::getPeakFrequencies"); |
| 507 | 497 |
| 508 PeakSet peaks; | 498 PeakSet peaks; |
| 509 if (!isOK()) return peaks; | 499 if (!isOK()) return peaks; |
