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