comparison layer/SpectrumLayer.cpp @ 254:a2ae3d93c645

* bit of work on harmonic cursor in spectrum
author Chris Cannam
date Mon, 11 Jun 2007 12:14:52 +0000
parents 28c8e8e3c537
children 6d113226bb4c
comparison
equal deleted inserted replaced
253:1b1e6947c124 254:a2ae3d93c645
19 #include "data/model/FFTModel.h" 19 #include "data/model/FFTModel.h"
20 #include "view/View.h" 20 #include "view/View.h"
21 #include "base/AudioLevel.h" 21 #include "base/AudioLevel.h"
22 #include "base/Preferences.h" 22 #include "base/Preferences.h"
23 #include "base/RangeMapper.h" 23 #include "base/RangeMapper.h"
24 #include "ColourMapper.h"
25
26 #include <QPainter>
24 27
25 SpectrumLayer::SpectrumLayer() : 28 SpectrumLayer::SpectrumLayer() :
26 m_originModel(0), 29 m_originModel(0),
27 m_channel(-1), 30 m_channel(-1),
28 m_channelSet(false), 31 m_channelSet(false),
71 m_windowSize, 74 m_windowSize,
72 true); 75 true);
73 76
74 setSliceableModel(newFFT); 77 setSliceableModel(newFFT);
75 78
79 m_biasCurve.clear();
80 for (size_t i = 0; i < m_windowSize; ++i) {
81 m_biasCurve.push_back(1.f / (float(m_windowSize)/2.f));
82 }
83
76 newFFT->resume(); 84 newFFT->resume();
77 } 85 }
78 86
79 void 87 void
80 SpectrumLayer::setChannel(int channel) 88 SpectrumLayer::setChannel(int channel)
141 if (!deflt) deflt = &garbage2; 149 if (!deflt) deflt = &garbage2;
142 150
143 if (name == "Window Size") { 151 if (name == "Window Size") {
144 152
145 *min = 0; 153 *min = 0;
146 *max = 10; 154 *max = 15;
147 *deflt = 5; 155 *deflt = 5;
148 156
149 val = 0; 157 val = 0;
150 int ws = m_windowSize; 158 int ws = m_windowSize;
151 while (ws > 32) { ws >>= 1; val ++; } 159 while (ws > 32) { ws >>= 1; val ++; }
245 SpectrumLayer::getValueExtents(float &, float &, bool &, QString &) const 253 SpectrumLayer::getValueExtents(float &, float &, bool &, QString &) const
246 { 254 {
247 return false; 255 return false;
248 } 256 }
249 257
258 bool
259 SpectrumLayer::getCrosshairExtents(View *v, QPainter &,
260 QPoint cursorPos,
261 std::vector<QRect> &extents) const
262 {
263 QRect vertical(cursorPos.x(), cursorPos.y(), 1, v->height() - cursorPos.y());
264 extents.push_back(vertical);
265
266 QRect horizontal(0, cursorPos.y(), v->width(), 12);
267 extents.push_back(horizontal);
268
269 return true;
270 }
271
272 float
273 SpectrumLayer::getFrequencyForX(float x, float w) const
274 {
275 float freq = 0;
276
277 int sampleRate = m_sliceableModel->getSampleRate();
278
279 float maxfreq = float(sampleRate) / 2;
280
281 switch (m_binScale) {
282
283 case LinearBins:
284 freq = ((x * maxfreq) / w);
285 break;
286
287 case LogBins:
288 freq = powf(10.f, (x * log10f(maxfreq)) / w);
289 break;
290
291 case InvertedLogBins:
292 freq = maxfreq - powf(10.f, ((w - x) * log10f(maxfreq)) / w);
293 break;
294 }
295
296 return freq;
297 }
298
299 float
300 SpectrumLayer::getXForFrequency(float freq, float w) const
301 {
302 float x = 0;
303
304 int sampleRate = m_sliceableModel->getSampleRate();
305
306 float maxfreq = float(sampleRate) / 2;
307
308 switch (m_binScale) {
309
310 case LinearBins:
311 x = (freq * w) / maxfreq;
312 break;
313
314 case LogBins:
315 x = (log10f(freq) * w) / log10f(maxfreq);
316 break;
317
318 case InvertedLogBins:
319 x = (w - log10f(maxfreq - freq) * w) / log10f(maxfreq);
320 break;
321 }
322
323 return x;
324 }
325
326 void
327 SpectrumLayer::paintCrosshairs(View *v, QPainter &paint,
328 QPoint cursorPos) const
329 {
330 paint.save();
331
332 ColourMapper mapper(m_colourMap, 0, 1);
333 paint.setPen(mapper.getContrastingColour());
334
335 int xorigin = m_xorigins[v];
336 int w = v->width() - xorigin - 1;
337
338 paint.drawLine(xorigin, cursorPos.y(), v->width(), cursorPos.y());
339 paint.drawLine(cursorPos.x(), cursorPos.y(), cursorPos.x(), v->height());
340
341 float fundamental = getFrequencyForX(cursorPos.x() - xorigin, w);
342
343 int harmonic = 2;
344
345 while (harmonic < 100) {
346
347 float hx = lrintf(getXForFrequency(fundamental * harmonic, w));
348 hx += xorigin;
349
350 if (hx < xorigin || hx > v->width()) break;
351
352 int len = 7;
353
354 if (harmonic % 2 == 0) {
355 if (harmonic % 4 == 0) {
356 len = 12;
357 } else {
358 len = 10;
359 }
360 }
361
362 paint.drawLine(int(hx),
363 cursorPos.y(),
364 int(hx),
365 cursorPos.y() + len);
366
367 ++harmonic;
368 }
369
370 paint.restore();
371 }
372
250 QString 373 QString
251 SpectrumLayer::getFeatureDescription(View *v, QPoint &p) const 374 SpectrumLayer::getFeatureDescription(View *v, QPoint &p) const
252 { 375 {
253 if (!m_sliceableModel) return ""; 376 if (!m_sliceableModel) return "";
254 377
334 } 457 }
335 458
336 return description; 459 return description;
337 } 460 }
338 461
462 void
463 SpectrumLayer::getBiasCurve(BiasCurve &curve) const
464 {
465 curve = m_biasCurve;
466 }
339 467
340 QString 468 QString
341 SpectrumLayer::toXmlString(QString indent, QString extraAttributes) const 469 SpectrumLayer::toXmlString(QString indent, QString extraAttributes) const
342 { 470 {
343 QString s; 471 QString s;