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; |