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;