comparison data/model/FFTModel.cpp @ 500:83eae5239db6

* Permit viewing (though not editing) colour 3d plot layer data in the spreadsheet data viewer dialog * Add somewhat simplistic RDF export for layers * Fix display of peak frequencies in spectrum layer * Fix (I hope) sizing of plugin parameter dialog
author Chris Cannam
date Tue, 02 Dec 2008 17:17:25 +0000
parents 115f60df1e4d
children 6066bde1c126
comparison
equal deleted inserted replaced
499:b71116d3c180 500:83eae5239db6
168 168
169 result.clear(); 169 result.clear();
170 size_t h = getHeight(); 170 size_t h = getHeight();
171 171
172 float magnitudes[h]; 172 float magnitudes[h];
173
173 if (m_server->getMagnitudesAt(x << m_xshift, magnitudes)) { 174 if (m_server->getMagnitudesAt(x << m_xshift, magnitudes)) {
175
174 for (size_t y = 0; y < h; ++y) { 176 for (size_t y = 0; y < h; ++y) {
175 result.push_back(magnitudes[h]); 177 result.push_back(magnitudes[y]);
176 } 178 }
179
177 } else { 180 } else {
178 for (size_t i = 0; i < h; ++i) result.push_back(0.f); 181 for (size_t i = 0; i < h; ++i) result.push_back(0.f);
179 } 182 }
180 } 183 }
181 184
257 return peaks; 260 return peaks;
258 } 261 }
259 262
260 getColumn(x, values); 263 getColumn(x, values);
261 264
265 float mean = 0.f;
266 for (int i =0; i < values.size(); ++i) mean += values[i];
267 if (values.size() >0) mean /= values.size();
268
262 // For peak picking we use a moving median window, picking the 269 // For peak picking we use a moving median window, picking the
263 // highest value within each continuous region of values that 270 // highest value within each continuous region of values that
264 // exceed the median. For pitch adaptivity, we adjust the window 271 // exceed the median. For pitch adaptivity, we adjust the window
265 // size to a roughly constant pitch range (about four tones). 272 // size to a roughly constant pitch range (about four tones).
266 273
267 size_t sampleRate = getSampleRate(); 274 size_t sampleRate = getSampleRate();
268 275
269 std::deque<float> window; 276 std::deque<float> window;
270 std::vector<size_t> inrange; 277 std::vector<size_t> inrange;
271 float dist = 0.5; 278 float dist = 0.5;
279
272 size_t medianWinSize = getPeakPickWindowSize(type, sampleRate, ymin, dist); 280 size_t medianWinSize = getPeakPickWindowSize(type, sampleRate, ymin, dist);
273 size_t halfWin = medianWinSize/2; 281 size_t halfWin = medianWinSize/2;
274 282
275 size_t binmin; 283 size_t binmin;
276 if (ymin > halfWin) binmin = ymin - halfWin; 284 if (ymin > halfWin) binmin = ymin - halfWin;
278 286
279 size_t binmax; 287 size_t binmax;
280 if (ymax + halfWin < values.size()) binmax = ymax + halfWin; 288 if (ymax + halfWin < values.size()) binmax = ymax + halfWin;
281 else binmax = values.size()-1; 289 else binmax = values.size()-1;
282 290
291 size_t prevcentre = 0;
292
283 for (size_t bin = binmin; bin <= binmax; ++bin) { 293 for (size_t bin = binmin; bin <= binmax; ++bin) {
284 294
285 float value = values[bin]; 295 float value = values[bin];
286 296
287 window.push_back(value); 297 window.push_back(value);
288 298
289 // so-called median will actually be the dist*100'th percentile 299 // so-called median will actually be the dist*100'th percentile
290 medianWinSize = getPeakPickWindowSize(type, sampleRate, bin, dist); 300 medianWinSize = getPeakPickWindowSize(type, sampleRate, bin, dist);
291 halfWin = medianWinSize/2; 301 halfWin = medianWinSize/2;
292 302
293 while (window.size() > medianWinSize) window.pop_front(); 303 while (window.size() > medianWinSize) {
304 window.pop_front();
305 }
306
307 size_t actualSize = window.size();
294 308
295 if (type == MajorPitchAdaptivePeaks) { 309 if (type == MajorPitchAdaptivePeaks) {
296 if (ymax + halfWin < values.size()) binmax = ymax + halfWin; 310 if (ymax + halfWin < values.size()) binmax = ymax + halfWin;
297 else binmax = values.size()-1; 311 else binmax = values.size()-1;
298 } 312 }
299 313
300 std::deque<float> sorted(window); 314 std::deque<float> sorted(window);
301 std::sort(sorted.begin(), sorted.end()); 315 std::sort(sorted.begin(), sorted.end());
302 float median = sorted[int(sorted.size() * dist)]; 316 float median = sorted[int(sorted.size() * dist)];
303 317
304 if (value > median) { 318 size_t centrebin = 0;
305 inrange.push_back(bin); 319 if (bin > actualSize/2) centrebin = bin - actualSize/2;
306 } 320
307 321 while (centrebin > prevcentre || bin == binmin) {
308 if (value <= median || bin+1 == values.size()) { 322
309 size_t peakbin = 0; 323 if (centrebin > prevcentre) ++prevcentre;
310 float peakval = 0.f; 324
311 if (!inrange.empty()) { 325 float centre = values[prevcentre];
312 for (size_t i = 0; i < inrange.size(); ++i) { 326
313 if (i == 0 || values[inrange[i]] > peakval) { 327 if (centre > median) {
314 peakval = values[inrange[i]]; 328 inrange.push_back(centrebin);
315 peakbin = inrange[i]; 329 }
330
331 if (centre <= median || centrebin+1 == values.size()) {
332 if (!inrange.empty()) {
333 size_t peakbin = 0;
334 float peakval = 0.f;
335 for (size_t i = 0; i < inrange.size(); ++i) {
336 if (i == 0 || values[inrange[i]] > peakval) {
337 peakval = values[inrange[i]];
338 peakbin = inrange[i];
339 }
340 }
341 inrange.clear();
342 if (peakbin >= ymin && peakbin <= ymax) {
343 peaks.insert(peakbin);
316 } 344 }
317 } 345 }
318 inrange.clear();
319 if (peakbin >= ymin && peakbin <= ymax) {
320 peaks.insert(peakbin);
321 }
322 } 346 }
347
348 if (bin == binmin) break;
323 } 349 }
324 } 350 }
325 351
326 return peaks; 352 return peaks;
327 } 353 }