Mercurial > hg > svgui
comparison layer/SpectrogramLayer.cpp @ 122:71992cee2ece
* Finish preferences dialog (as far as it's going at the moment) and connect it up
* Fix Parzen window shape (was triangular!)
* Various fixes to spectrogram draw coordinates in smoothing mode etc
* Draw C keys in grey on the piano
author | Chris Cannam |
---|---|
date | Fri, 21 Jul 2006 16:03:42 +0000 |
parents | 7363cacf7de0 |
children | bd6e85b3d88b |
comparison
equal
deleted
inserted
replaced
121:7363cacf7de0 | 122:71992cee2ece |
---|---|
77 setColourScale(MeterColourScale); | 77 setColourScale(MeterColourScale); |
78 setBinDisplay(PeakFrequencies); | 78 setBinDisplay(PeakFrequencies); |
79 setNormalizeColumns(true); | 79 setNormalizeColumns(true); |
80 } | 80 } |
81 | 81 |
82 Preferences *prefs = Preferences::getInstance(); | |
83 connect(prefs, SIGNAL(propertyChanged(PropertyContainer::PropertyName)), | |
84 this, SLOT(preferenceChanged(PropertyContainer::PropertyName))); | |
85 setWindowType(prefs->getWindowType()); | |
86 | |
82 setColourmap(); | 87 setColourmap(); |
83 } | 88 } |
84 | 89 |
85 SpectrogramLayer::~SpectrogramLayer() | 90 SpectrogramLayer::~SpectrogramLayer() |
86 { | 91 { |
543 const View *v = i->first; | 548 const View *v = i->first; |
544 | 549 |
545 if (startFrame < v->getEndFrame() && int(endFrame) >= v->getStartFrame()) { | 550 if (startFrame < v->getEndFrame() && int(endFrame) >= v->getStartFrame()) { |
546 i->second.validArea = QRect(); | 551 i->second.validArea = QRect(); |
547 } | 552 } |
553 } | |
554 } | |
555 | |
556 void | |
557 SpectrogramLayer::preferenceChanged(PropertyContainer::PropertyName name) | |
558 { | |
559 std::cerr << "SpectrogramLayer::preferenceChanged(" << name.toStdString() << ")" << std::endl; | |
560 | |
561 if (name == "Window Type") { | |
562 setWindowType(Preferences::getInstance()->getWindowType()); | |
563 return; | |
564 } | |
565 if (name == "Smooth Spectrogram") { | |
566 invalidatePixmapCaches(); | |
567 invalidateMagnitudes(); | |
568 emit layerParametersChanged(); | |
569 } | |
570 if (name == "Tuning Frequency") { | |
571 emit layerParametersChanged(); | |
548 } | 572 } |
549 } | 573 } |
550 | 574 |
551 void | 575 void |
552 SpectrogramLayer::setChannel(int ch) | 576 SpectrogramLayer::setChannel(int ch) |
1334 int q0i = int(q0 + 0.001); | 1358 int q0i = int(q0 + 0.001); |
1335 int q1i = int(q1); | 1359 int q1i = int(q1); |
1336 | 1360 |
1337 int sr = m_model->getSampleRate(); | 1361 int sr = m_model->getSampleRate(); |
1338 | 1362 |
1339 //!!! wrong for smoothing -- wrong fft size for fft adapter | |
1340 | |
1341 for (int q = q0i; q <= q1i; ++q) { | 1363 for (int q = q0i; q <= q1i; ++q) { |
1342 if (q == q0i) freqMin = (sr * q) / m_fftSize; | 1364 if (q == q0i) freqMin = (sr * q) / m_fftSize; |
1343 if (q == q1i) freqMax = (sr * (q+1)) / m_fftSize; | 1365 if (q == q1i) freqMax = (sr * (q+1)) / m_fftSize; |
1344 } | 1366 } |
1345 return true; | 1367 return true; |
1434 | 1456 |
1435 int s0i = int(s0 + 0.001); | 1457 int s0i = int(s0 + 0.001); |
1436 int s1i = int(s1); | 1458 int s1i = int(s1); |
1437 | 1459 |
1438 bool rv = false; | 1460 bool rv = false; |
1461 | |
1462 size_t zp = getZeroPadLevel(v); | |
1463 q0i *= zp + 1; | |
1464 q1i *= zp + 1; | |
1439 | 1465 |
1440 FFTFuzzyAdapter *fft = getFFTAdapter(v); | 1466 FFTFuzzyAdapter *fft = getFFTAdapter(v); |
1441 | 1467 |
1442 if (fft) { | 1468 if (fft) { |
1443 | 1469 |
1862 } | 1888 } |
1863 | 1889 |
1864 m_drawBuffer.fill(m_colourMap.getColour(0).rgb()); | 1890 m_drawBuffer.fill(m_colourMap.getColour(0).rgb()); |
1865 | 1891 |
1866 int sr = m_model->getSampleRate(); | 1892 int sr = m_model->getSampleRate(); |
1893 | |
1894 // Set minFreq and maxFreq to the frequency extents of the possibly | |
1895 // zero-padded visible bin range, and displayMinFreq and displayMaxFreq | |
1896 // to the actual scale frequency extents (presumably not zero padded). | |
1867 | 1897 |
1868 size_t bins = fftSize / 2; | 1898 size_t bins = fftSize / 2; |
1869 if (m_maxFrequency > 0) { | 1899 if (m_maxFrequency > 0) { |
1870 bins = int((double(m_maxFrequency) * fftSize) / sr + 0.1); | 1900 bins = int((double(m_maxFrequency) * fftSize) / sr + 0.1); |
1871 if (bins > fftSize / 2) bins = fftSize / 2; | 1901 if (bins > fftSize / 2) bins = fftSize / 2; |
1879 } | 1909 } |
1880 | 1910 |
1881 float minFreq = (float(minbin) * sr) / fftSize; | 1911 float minFreq = (float(minbin) * sr) / fftSize; |
1882 float maxFreq = (float(bins) * sr) / fftSize; | 1912 float maxFreq = (float(bins) * sr) / fftSize; |
1883 | 1913 |
1914 float displayMinFreq = minFreq; | |
1915 float displayMaxFreq = maxFreq; | |
1916 | |
1917 if (fftSize != m_fftSize) { | |
1918 displayMinFreq = getEffectiveMinFrequency(); | |
1919 displayMaxFreq = getEffectiveMaxFrequency(); | |
1920 } | |
1921 | |
1884 float ymag[h]; | 1922 float ymag[h]; |
1885 float ydiv[h]; | 1923 float ydiv[h]; |
1886 float yval[bins + 1]; //!!! cache this | 1924 float yval[bins + 1]; //!!! cache this? |
1887 | 1925 |
1888 size_t increment = getWindowIncrement(); | 1926 size_t increment = getWindowIncrement(); |
1889 | 1927 |
1890 bool logarithmic = (m_frequencyScale == LogFrequencyScale); | 1928 bool logarithmic = (m_frequencyScale == LogFrequencyScale); |
1891 | 1929 |
1892 for (size_t q = minbin; q <= bins; ++q) { | 1930 for (size_t q = minbin; q <= bins; ++q) { |
1893 float f0 = (float(q) * sr) / fftSize; | 1931 float f0 = (float(q) * sr) / fftSize; |
1894 yval[q] = v->getYForFrequency(f0, minFreq, maxFreq, logarithmic); | 1932 yval[q] = v->getYForFrequency(f0, displayMinFreq, displayMaxFreq, |
1933 logarithmic); | |
1934 // std::cerr << "min: " << minFreq << ", max: " << maxFreq << ", yval[" << q << "]: " << yval[q] << std::endl; | |
1895 } | 1935 } |
1896 | 1936 |
1897 MagnitudeRange overallMag = m_viewMags[v]; | 1937 MagnitudeRange overallMag = m_viewMags[v]; |
1898 bool overallMagChanged = false; | 1938 bool overallMagChanged = false; |
1899 | 1939 |
1957 fft->getPhaseAt(s, q), | 1997 fft->getPhaseAt(s, q), |
1958 fft->getPhaseAt(s+1, q), | 1998 fft->getPhaseAt(s+1, q), |
1959 steady); | 1999 steady); |
1960 | 2000 |
1961 y0 = y1 = v->getYForFrequency | 2001 y0 = y1 = v->getYForFrequency |
1962 (f, minFreq, maxFreq, logarithmic); | 2002 (f, displayMinFreq, displayMaxFreq, logarithmic); |
1963 } | 2003 } |
1964 | 2004 |
1965 int y0i = int(y0 + 0.001); | 2005 int y0i = int(y0 + 0.001); |
1966 int y1i = int(y1); | 2006 int y1i = int(y1); |
1967 | 2007 |
2427 { | 2467 { |
2428 if (!m_model || !m_model->isOK()) { | 2468 if (!m_model || !m_model->isOK()) { |
2429 return; | 2469 return; |
2430 } | 2470 } |
2431 | 2471 |
2472 Profiler profiler("SpectrogramLayer::paintVerticalScale", true); | |
2473 | |
2432 //!!! cache this? | 2474 //!!! cache this? |
2433 | 2475 |
2434 int h = rect.height(), w = rect.width(); | 2476 int h = rect.height(), w = rect.width(); |
2435 | 2477 |
2436 int tickw = (m_frequencyScale == LogFrequencyScale ? 10 : 4); | 2478 int tickw = (m_frequencyScale == LogFrequencyScale ? 10 : 4); |
2613 | 2655 |
2614 int sr = m_model->getSampleRate(); | 2656 int sr = m_model->getSampleRate(); |
2615 float minf = getEffectiveMinFrequency(); | 2657 float minf = getEffectiveMinFrequency(); |
2616 float maxf = getEffectiveMaxFrequency(); | 2658 float maxf = getEffectiveMaxFrequency(); |
2617 | 2659 |
2618 int py = h; | 2660 int py = h, ppy = h; |
2619 paint.setBrush(paint.pen().color()); | 2661 paint.setBrush(paint.pen().color()); |
2620 | 2662 |
2621 for (int i = 0; i < 128; ++i) { | 2663 for (int i = 0; i < 128; ++i) { |
2622 | 2664 |
2623 float f = Pitch::getFrequencyForPitch(i); | 2665 float f = Pitch::getFrequencyForPitch(i); |
2624 int y = lrintf(v->getYForFrequency(f, minf, maxf, true)); | 2666 int y = lrintf(v->getYForFrequency(f, minf, maxf, true)); |
2667 | |
2668 if (y < -2) break; | |
2669 if (y > h + 2) { | |
2670 continue; | |
2671 } | |
2672 | |
2625 int n = (i % 12); | 2673 int n = (i % 12); |
2674 | |
2675 if (n == 1) { | |
2676 // C# -- fill the C from here | |
2677 if (ppy - y > 2) { | |
2678 paint.fillRect(w - pkw, | |
2679 // y - (py - y) / 2 - (py - y) / 4, | |
2680 y, | |
2681 pkw, | |
2682 (py + ppy) / 2 - y, | |
2683 // py - y + 1, | |
2684 Qt::gray); | |
2685 } | |
2686 } | |
2687 | |
2626 if (n == 1 || n == 3 || n == 6 || n == 8 || n == 10) { | 2688 if (n == 1 || n == 3 || n == 6 || n == 8 || n == 10) { |
2627 // black notes | 2689 // black notes |
2628 paint.drawLine(w - pkw, y, w, y); | 2690 paint.drawLine(w - pkw, y, w, y); |
2629 int rh = ((py - y) / 4) * 2; | 2691 int rh = ((py - y) / 4) * 2; |
2630 if (rh < 2) rh = 2; | 2692 if (rh < 2) rh = 2; |
2631 paint.drawRect(w - pkw, y - (py-y)/4, pkw/2, rh); | 2693 paint.drawRect(w - pkw, y - (py-y)/4, pkw/2, rh); |
2632 } else if (n == 0 || n == 5) { | 2694 } else if (n == 0 || n == 5) { |
2633 // C, A | 2695 // C, F |
2634 if (py < h) { | 2696 if (py < h) { |
2635 paint.drawLine(w - pkw, (y + py) / 2, w, (y + py) / 2); | 2697 paint.drawLine(w - pkw, (y + py) / 2, w, (y + py) / 2); |
2636 } | 2698 } |
2637 } | 2699 } |
2638 | 2700 |
2701 ppy = py; | |
2639 py = y; | 2702 py = y; |
2640 } | 2703 } |
2641 } | 2704 } |
2642 } | 2705 } |
2643 | 2706 |