Mercurial > hg > svgui
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; |