comparison layer/SpectrogramLayer.cpp @ 119:508276c923ba

* Various experiments in spectrogram colour scaling, etc. Nothing final here yet, but some promising developments.
author Chris Cannam
date Fri, 14 Jul 2006 17:12:16 +0000
parents 853a7fc542d0
children 8dfa20f1c70a
comparison
equal deleted inserted replaced
118:853a7fc542d0 119:508276c923ba
33 #include <iostream> 33 #include <iostream>
34 34
35 #include <cassert> 35 #include <cassert>
36 #include <cmath> 36 #include <cmath>
37 37
38 #define DEBUG_SPECTROGRAM_REPAINT 1 38 //#define DEBUG_SPECTROGRAM_REPAINT 1
39 39
40 SpectrogramLayer::SpectrogramLayer(Configuration config) : 40 SpectrogramLayer::SpectrogramLayer(Configuration config) :
41 Layer(), 41 Layer(),
42 m_model(0), 42 m_model(0),
43 m_channel(0), 43 m_channel(0),
47 m_zeroPadLevel(0), 47 m_zeroPadLevel(0),
48 m_fftSize(1024), 48 m_fftSize(1024),
49 m_gain(1.0), 49 m_gain(1.0),
50 m_threshold(0.0), 50 m_threshold(0.0),
51 m_colourRotation(0), 51 m_colourRotation(0),
52 m_minFrequency(0), 52 m_minFrequency(10),
53 m_maxFrequency(8000), 53 m_maxFrequency(8000),
54 m_colourScale(dBColourScale), 54 m_colourScale(dBColourScale),
55 m_colourScheme(DefaultColours), 55 m_colourScheme(DefaultColours),
56 m_frequencyScale(LinearFrequencyScale), 56 m_frequencyScale(LinearFrequencyScale),
57 m_binDisplay(AllBins), 57 m_binDisplay(AllBins),
346 switch (value) { 346 switch (value) {
347 default: 347 default:
348 case 0: return tr("Linear"); 348 case 0: return tr("Linear");
349 case 1: return tr("Meter"); 349 case 1: return tr("Meter");
350 case 2: return tr("dB"); 350 case 2: return tr("dB");
351 case 3: return tr("Phase"); 351 case 3: return tr("Other");
352 case 4: return tr("Phase");
352 } 353 }
353 } 354 }
354 if (name == "Window Type") { 355 if (name == "Window Type") {
355 switch ((WindowType)value) { 356 switch ((WindowType)value) {
356 default: 357 default:
490 switch (value) { 491 switch (value) {
491 default: 492 default:
492 case 0: setColourScale(LinearColourScale); break; 493 case 0: setColourScale(LinearColourScale); break;
493 case 1: setColourScale(MeterColourScale); break; 494 case 1: setColourScale(MeterColourScale); break;
494 case 2: setColourScale(dBColourScale); break; 495 case 2: setColourScale(dBColourScale); break;
495 case 3: setColourScale(PhaseColourScale); break; 496 case 3: setColourScale(OtherColourScale); break;
497 case 4: setColourScale(PhaseColourScale); break;
496 } 498 }
497 } else if (name == "Frequency Scale") { 499 } else if (name == "Frequency Scale") {
498 switch (value) { 500 switch (value) {
499 default: 501 default:
500 case 0: setFrequencyScale(LinearFrequencyScale); break; 502 case 0: setFrequencyScale(LinearFrequencyScale); break;
680 SpectrogramLayer::setMinFrequency(size_t mf) 682 SpectrogramLayer::setMinFrequency(size_t mf)
681 { 683 {
682 if (m_minFrequency == mf) return; 684 if (m_minFrequency == mf) return;
683 685
684 invalidatePixmapCaches(); 686 invalidatePixmapCaches();
687 invalidateMagnitudes();
685 688
686 m_minFrequency = mf; 689 m_minFrequency = mf;
687 690
688 emit layerParametersChanged(); 691 emit layerParametersChanged();
689 } 692 }
698 SpectrogramLayer::setMaxFrequency(size_t mf) 701 SpectrogramLayer::setMaxFrequency(size_t mf)
699 { 702 {
700 if (m_maxFrequency == mf) return; 703 if (m_maxFrequency == mf) return;
701 704
702 invalidatePixmapCaches(); 705 invalidatePixmapCaches();
706 invalidateMagnitudes();
703 707
704 m_maxFrequency = mf; 708 m_maxFrequency = mf;
705 709
706 emit layerParametersChanged(); 710 emit layerParametersChanged();
707 } 711 }
804 SpectrogramLayer::setNormalizeColumns(bool n) 808 SpectrogramLayer::setNormalizeColumns(bool n)
805 { 809 {
806 if (m_normalizeColumns == n) return; 810 if (m_normalizeColumns == n) return;
807 811
808 invalidatePixmapCaches(); 812 invalidatePixmapCaches();
813 invalidateMagnitudes();
809 m_normalizeColumns = n; 814 m_normalizeColumns = n;
810 815
811 emit layerParametersChanged(); 816 emit layerParametersChanged();
812 } 817 }
813 818
842 847
843 void 848 void
844 SpectrogramLayer::cacheInvalid() 849 SpectrogramLayer::cacheInvalid()
845 { 850 {
846 invalidatePixmapCaches(); 851 invalidatePixmapCaches();
852 invalidateMagnitudes();
847 } 853 }
848 854
849 void 855 void
850 SpectrogramLayer::cacheInvalid(size_t, size_t) 856 SpectrogramLayer::cacheInvalid(size_t, size_t)
851 { 857 {
1054 steadyState = false; 1060 steadyState = false;
1055 return frequency; 1061 return frequency;
1056 } 1062 }
1057 1063
1058 unsigned char 1064 unsigned char
1059 SpectrogramLayer::getDisplayValue(float input) const 1065 SpectrogramLayer::getDisplayValue(View *v, float input) const
1060 { 1066 {
1061 int value; 1067 int value;
1068
1069 //!!! for the moment we're always normalizing visible area
1070 float min = m_viewMags[v].getMin();
1071 float max = m_viewMags[v].getMax();
1072 float thresh = -80.f;
1073
1074 if (max == 0.f) max = 1.f;
1075 if (max == min) min = max - 0.0001f;
1062 1076
1063 switch (m_colourScale) { 1077 switch (m_colourScale) {
1064 1078
1065 default: 1079 default:
1066 case LinearColourScale: 1080 case LinearColourScale:
1067 value = int 1081 // value = int
1068 (input * (m_normalizeColumns ? 1.0 : 50.0) * 255.0) + 1; 1082 // (input * (m_normalizeColumns ? 1.0 : 50.0) * 255.0) + 1;
1083 value = int(((input - min) / (max - min)) * 255.f) + 1;
1069 break; 1084 break;
1070 1085
1071 case MeterColourScale: 1086 case MeterColourScale:
1072 value = AudioLevel::multiplier_to_preview 1087 // value = AudioLevel::multiplier_to_preview
1073 (input * (m_normalizeColumns ? 1.0 : 50.0), 255) + 1; 1088 // (input * (m_normalizeColumns ? 1.0 : 50.0), 255) + 1;
1089 value = AudioLevel::multiplier_to_preview((input - min) / (max - min), 255) + 1;
1074 break; 1090 break;
1075 1091
1076 case dBColourScale: 1092 case dBColourScale:
1077 input = 20.0 * log10(input); 1093 //!!! experiment with normalizing the visible area this way.
1078 input = (input + 80.0) / 80.0; 1094 //In any case, we need to have some indication of what the dB
1079 if (input < 0.0) input = 0.0; 1095 //scale is relative to.
1080 if (input > 1.0) input = 1.0; 1096 input = 10.f * log10f(input / max);
1081 value = int(input * 255.0) + 1; 1097 if (min > 0.f) {
1098 thresh = 10.f * log10f(min);
1099 if (thresh < -80.f) thresh = -80.f;
1100 }
1101 input = (input - thresh) / (-thresh);
1102 if (input < 0.f) input = 0.f;
1103 if (input > 1.f) input = 1.f;
1104 value = int(input * 255.f) + 1;
1105 break;
1106
1107 case OtherColourScale:
1108 //!!! the "Other" scale is just where our current experiments go
1109 //!!! power rather than v
1110 input = 10.f * log10f((input * input) / (max * max));
1111 if (min > 0.f) {
1112 thresh = 10.f * log10f(min * min);
1113 if (thresh < -80.f) thresh = -80.f;
1114 }
1115 input = (input - thresh) / (-thresh);
1116 if (input < 0.f) input = 0.f;
1117 if (input > 1.f) input = 1.f;
1118 value = int(input * 255.f) + 1;
1119 break;
1120
1121 /*!!!
1122 input = 10.f * log10f(input * input);
1123 input = 1.f / (1.f + expf(- (input + 20.f) / 10.f));
1124
1125 if (input < 0.f) input = 0.f;
1126 if (input > 1.f) input = 1.f;
1127 value = int(input * 255.f) + 1;
1128 */
1082 break; 1129 break;
1083 1130
1084 case PhaseColourScale: 1131 case PhaseColourScale:
1085 value = int((input * 127.0 / M_PI) + 128); 1132 value = int((input * 127.0 / M_PI) + 128);
1086 break; 1133 break;
1108 input = AudioLevel::preview_to_multiplier(value - 1, 255) 1155 input = AudioLevel::preview_to_multiplier(value - 1, 255)
1109 / (m_normalizeColumns ? 1.0 : 50.0); 1156 / (m_normalizeColumns ? 1.0 : 50.0);
1110 break; 1157 break;
1111 1158
1112 case dBColourScale: 1159 case dBColourScale:
1160 input = float(value - 1) / 255.0;
1161 input = (input * 80.0) - 80.0;
1162 input = powf(10.0, input) / 20.0;
1163 value = int(input);
1164 break;
1165
1166 case OtherColourScale:
1113 input = float(value - 1) / 255.0; 1167 input = float(value - 1) / 255.0;
1114 input = (input * 80.0) - 80.0; 1168 input = (input * 80.0) - 80.0;
1115 input = powf(10.0, input) / 20.0; 1169 input = powf(10.0, input) / 20.0;
1116 value = int(input); 1170 value = int(input);
1117 break; 1171 break;
1471 i != m_fftAdapters.end(); ++i) { 1525 i != m_fftAdapters.end(); ++i) {
1472 delete i->second.first; 1526 delete i->second.first;
1473 } 1527 }
1474 1528
1475 m_fftAdapters.clear(); 1529 m_fftAdapters.clear();
1530 }
1531
1532 void
1533 SpectrogramLayer::invalidateMagnitudes()
1534 {
1535 m_viewMags.clear();
1536 for (std::vector<MagnitudeRange>::iterator i = m_columnMags.begin();
1537 i != m_columnMags.end(); ++i) {
1538 *i = MagnitudeRange();
1539 }
1540 }
1541
1542 bool
1543 SpectrogramLayer::updateViewMagnitudes(View *v) const
1544 {
1545 MagnitudeRange mag;
1546
1547 int x0 = 0, x1 = v->width();
1548 float s00 = 0, s01 = 0, s10 = 0, s11 = 0;
1549
1550 getXBinRange(v, x0, s00, s01);
1551 getXBinRange(v, x1, s10, s11);
1552
1553 int s0 = int(std::min(s00, s10) + 0.0001);
1554 int s1 = int(std::max(s01, s11));
1555
1556 if (m_columnMags.size() <= s1) {
1557 m_columnMags.resize(s1 + 1);
1558 }
1559
1560 for (int s = s0; s <= s1; ++s) {
1561 if (m_columnMags[s].isSet()) {
1562 mag.sample(m_columnMags[s]);
1563 }
1564 }
1565
1566 std::cerr << "SpectrogramLayer::updateViewMagnitudes returning from cols "
1567 << s0 << " -> " << s1 << " inclusive" << std::endl;
1568
1569 if (!mag.isSet()) return false;
1570 if (mag == m_viewMags[v]) return false;
1571 m_viewMags[v] = mag;
1572 return true;
1476 } 1573 }
1477 1574
1478 void 1575 void
1479 SpectrogramLayer::paint(View *v, QPainter &paint, QRect rect) const 1576 SpectrogramLayer::paint(View *v, QPainter &paint, QRect rect) const
1480 { 1577 {
1657 */ 1754 */
1658 1755
1659 if (recreateWholePixmapCache) { 1756 if (recreateWholePixmapCache) {
1660 x0 = 0; 1757 x0 = 0;
1661 x1 = v->width(); 1758 x1 = v->width();
1759 }
1760
1761 if (updateViewMagnitudes(v)) {
1762 std::cerr << "SpectrogramLayer: magnitude range changed to [" << m_viewMags[v].getMin() << "->" << m_viewMags[v].getMax() << "]" << std::endl;
1763 } else {
1764 std::cerr << "No change in magnitude range [" << m_viewMags[v].getMin() << "->" << m_viewMags[v].getMax() << "]" << std::endl;
1662 } 1765 }
1663 1766
1664 int paintBlockWidth = (300000 / zoomLevel); 1767 int paintBlockWidth = (300000 / zoomLevel);
1665 if (paintBlockWidth < 20) paintBlockWidth = 20; 1768 if (paintBlockWidth < 20) paintBlockWidth = 20;
1666 1769
1748 for (size_t q = minbin; q <= bins; ++q) { 1851 for (size_t q = minbin; q <= bins; ++q) {
1749 float f0 = (float(q) * sr) / fftSize; 1852 float f0 = (float(q) * sr) / fftSize;
1750 yval[q] = v->getYForFrequency(f0, minFreq, maxFreq, logarithmic); 1853 yval[q] = v->getYForFrequency(f0, minFreq, maxFreq, logarithmic);
1751 } 1854 }
1752 1855
1856 MagnitudeRange overallMag = m_viewMags[v];
1857 bool overallMagChanged = false;
1858
1753 for (int x = 0; x < w; ++x) { 1859 for (int x = 0; x < w; ++x) {
1754 1860
1755 for (int y = 0; y < h; ++y) { 1861 for (int y = 0; y < h; ++y) {
1756 ymag[y] = 0.0; 1862 ymag[y] = 0.0;
1757 ydiv[y] = 0.0; 1863 ydiv[y] = 0.0;
1776 } 1882 }
1777 1883
1778 for (int s = s0i; s <= s1i; ++s) { 1884 for (int s = s0i; s <= s1i; ++s) {
1779 1885
1780 if (!fft->isColumnReady(s)) continue; 1886 if (!fft->isColumnReady(s)) continue;
1887 MagnitudeRange mag;
1781 1888
1782 for (size_t q = minbin; q < bins; ++q) { 1889 for (size_t q = minbin; q < bins; ++q) {
1783 1890
1784 float y0 = yval[q + 1]; 1891 float y0 = yval[q + 1];
1785 float y1 = yval[q]; 1892 float y1 = yval[q];
1820 float value; 1927 float value;
1821 1928
1822 if (m_colourScale == PhaseColourScale) { 1929 if (m_colourScale == PhaseColourScale) {
1823 value = fft->getPhaseAt(s, q); 1930 value = fft->getPhaseAt(s, q);
1824 } else if (m_normalizeColumns) { 1931 } else if (m_normalizeColumns) {
1825 value = fft->getNormalizedMagnitudeAt(s, q) * m_gain; 1932 value = fft->getNormalizedMagnitudeAt(s, q);
1933 mag.sample(value);
1934 value *= m_gain;
1826 } else { 1935 } else {
1827 value = fft->getMagnitudeAt(s, q) * m_gain; 1936 value = fft->getMagnitudeAt(s, q);
1937 mag.sample(value);
1938 value *= m_gain;
1828 } 1939 }
1829 1940
1830 for (int y = y0i; y <= y1i; ++y) { 1941 for (int y = y0i; y <= y1i; ++y) {
1831 1942
1832 if (y < 0 || y >= h) continue; 1943 if (y < 0 || y >= h) continue;
1836 if (y == y1i) yprop *= y1 - y; 1947 if (y == y1i) yprop *= y1 - y;
1837 ymag[y] += yprop * value; 1948 ymag[y] += yprop * value;
1838 ydiv[y] += yprop; 1949 ydiv[y] += yprop;
1839 } 1950 }
1840 } 1951 }
1952
1953 if (mag.isSet()) {
1954
1955 m_columnMags[s].sample(mag);
1956
1957 if (overallMag.sample(mag)) {
1958 //!!! scaling would change here
1959 overallMagChanged = true;
1960 std::cerr << "Overall mag changed (again?) at column " << s << ", to [" << overallMag.getMin() << "->" << overallMag.getMax() << "]" << std::endl;
1961 }
1962 }
1841 } 1963 }
1842 1964
1843 for (int y = 0; y < h; ++y) { 1965 for (int y = 0; y < h; ++y) {
1844 1966
1845 if (ydiv[y] > 0.0) { 1967 if (ydiv[y] > 0.0) {
1846 1968
1847 unsigned char pixel = 0; 1969 unsigned char pixel = 0;
1848 1970
1849 float avg = ymag[y] / ydiv[y]; 1971 float avg = ymag[y] / ydiv[y];
1850 pixel = getDisplayValue(avg); 1972 pixel = getDisplayValue(v, avg);
1851 1973
1852 assert(x <= m_drawBuffer.width()); 1974 assert(x <= m_drawBuffer.width());
1853 QColor c = m_colourMap.getColour(pixel); 1975 QColor c = m_colourMap.getColour(pixel);
1854 m_drawBuffer.setPixel(x, y, 1976 m_drawBuffer.setPixel(x, y,
1855 qRgb(c.red(), c.green(), c.blue())); 1977 qRgb(c.red(), c.green(), c.blue()));
1856 } 1978 }
1857 } 1979 }
1858 } 1980 }
1859 1981
1982 if (overallMagChanged) {
1983 m_viewMags[v] = overallMag;
1984 std::cerr << "Overall mag is now [" << m_viewMags[v].getMin() << "->" << m_viewMags[v].getMax() << "] - will be updating" << std::endl;
1985 } else {
1986 std::cerr << "Overall mag unchanged at [" << m_viewMags[v].getMin() << "->" << m_viewMags[v].getMax() << "]" << std::endl;
1987 }
1988
1860 paint.drawImage(x0, y0, m_drawBuffer, 0, 0, w, h); 1989 paint.drawImage(x0, y0, m_drawBuffer, 0, 0, w, h);
1861 1990
1862 if (recreateWholePixmapCache) { 1991 if (recreateWholePixmapCache) {
1863 cache.pixmap = QPixmap(v->width(), v->height()); 1992 cache.pixmap = QPixmap(v->width(), v->height());
1864 } 1993 }
1865 1994
1866 QPainter cachePainter(&cache.pixmap); 1995 QPainter cachePainter(&cache.pixmap);
1867 cachePainter.drawImage(x0, y0, m_drawBuffer, 0, 0, w, h); 1996 cachePainter.drawImage(x0, y0, m_drawBuffer, 0, 0, w, h);
1868 cachePainter.end(); 1997 cachePainter.end();
1869 1998
1870 cache.startFrame = startFrame; 1999 if (!overallMagChanged) {
1871 cache.zoomLevel = zoomLevel; 2000
1872 2001 cache.startFrame = startFrame;
1873 if (cache.validArea.x() > 0) { 2002 cache.zoomLevel = zoomLevel;
2003
2004 if (cache.validArea.x() > 0) {
1874 #ifdef DEBUG_SPECTROGRAM_REPAINT 2005 #ifdef DEBUG_SPECTROGRAM_REPAINT
1875 std::cerr << "SpectrogramLayer::paint() updating left" << std::endl; 2006 std::cerr << "SpectrogramLayer::paint() updating left" << std::endl;
1876 #endif 2007 #endif
1877 v->update(0, 0, cache.validArea.x(), v->height()); 2008 v->update(0, 0, cache.validArea.x(), v->height());
1878 } 2009 }
1879 2010
1880 if (cache.validArea.x() + cache.validArea.width() < 2011 if (cache.validArea.x() + cache.validArea.width() <
1881 cache.pixmap.width()) { 2012 cache.pixmap.width()) {
1882 #ifdef DEBUG_SPECTROGRAM_REPAINT 2013 #ifdef DEBUG_SPECTROGRAM_REPAINT
1883 std::cerr << "SpectrogramLayer::paint() updating right (" 2014 std::cerr << "SpectrogramLayer::paint() updating right ("
1884 << cache.validArea.x() + cache.validArea.width() 2015 << cache.validArea.x() + cache.validArea.width()
1885 << ", " 2016 << ", "
1886 << cache.pixmap.width() - (cache.validArea.x() + 2017 << cache.pixmap.width() - (cache.validArea.x() +
1887 cache.validArea.width()) 2018 cache.validArea.width())
1888 << ")" << std::endl; 2019 << ")" << std::endl;
1889 #endif 2020 #endif
1890 v->update(cache.validArea.x() + cache.validArea.width(), 2021 v->update(cache.validArea.x() + cache.validArea.width(),
1891 0, 2022 0,
1892 cache.pixmap.width() - (cache.validArea.x() + 2023 cache.pixmap.width() - (cache.validArea.x() +
1893 cache.validArea.width()), 2024 cache.validArea.width()),
1894 v->height()); 2025 v->height());
2026 }
2027 } else {
2028 // overallMagChanged
2029 cache.validArea = QRect();
2030 v->update();
1895 } 2031 }
1896 2032
1897 #ifdef DEBUG_SPECTROGRAM_REPAINT 2033 #ifdef DEBUG_SPECTROGRAM_REPAINT
1898 std::cerr << "SpectrogramLayer::paint() returning" << std::endl; 2034 std::cerr << "SpectrogramLayer::paint() returning" << std::endl;
1899 #endif 2035 #endif
2138 int 2274 int
2139 SpectrogramLayer::getColourScaleWidth(QPainter &paint) const 2275 SpectrogramLayer::getColourScaleWidth(QPainter &paint) const
2140 { 2276 {
2141 int cw; 2277 int cw;
2142 2278
2279 cw = paint.fontMetrics().width("-80dB");
2280
2281 /*!!!
2143 switch (m_colourScale) { 2282 switch (m_colourScale) {
2144 default: 2283 default:
2145 case LinearColourScale: 2284 case LinearColourScale:
2146 cw = paint.fontMetrics().width(QString("0.00")); 2285 cw = paint.fontMetrics().width(QString("0.00"));
2147 break; 2286 break;
2148 2287
2149 case MeterColourScale: 2288 case MeterColourScale:
2150 case dBColourScale: 2289 case dBColourScale:
2290 case OtherColourScale:
2151 cw = std::max(paint.fontMetrics().width(tr("-Inf")), 2291 cw = std::max(paint.fontMetrics().width(tr("-Inf")),
2152 paint.fontMetrics().width(tr("-90"))); 2292 paint.fontMetrics().width(tr("-90")));
2153 break; 2293 break;
2154 2294
2155 case PhaseColourScale: 2295 case PhaseColourScale:
2156 cw = paint.fontMetrics().width(QString("-") + QChar(0x3c0)); 2296 cw = paint.fontMetrics().width(QString("-") + QChar(0x3c0));
2157 break; 2297 break;
2158 } 2298 }
2299 */
2300
2159 2301
2160 return cw; 2302 return cw;
2161 } 2303 }
2162 2304
2163 int 2305 int
2199 bins = int((double(m_maxFrequency) * m_fftSize) / sr + 0.1); 2341 bins = int((double(m_maxFrequency) * m_fftSize) / sr + 0.1);
2200 if (bins > m_fftSize / 2) bins = m_fftSize / 2; 2342 if (bins > m_fftSize / 2) bins = m_fftSize / 2;
2201 } 2343 }
2202 2344
2203 int cw = getColourScaleWidth(paint); 2345 int cw = getColourScaleWidth(paint);
2346 int cbw = paint.fontMetrics().width("dB");
2204 2347
2205 int py = -1; 2348 int py = -1;
2206 int textHeight = paint.fontMetrics().height(); 2349 int textHeight = paint.fontMetrics().height();
2207 int toff = -textHeight + paint.fontMetrics().ascent() + 2; 2350 int toff = -textHeight + paint.fontMetrics().ascent() + 2;
2208 2351
2209 if (h > textHeight * 2 + 10) { 2352 if (h > textHeight * 3 + 10) {
2210 2353
2211 int ch = h - textHeight * 2 - 8; 2354 int topLines = 2;
2212 paint.drawRect(4, textHeight + 4, cw - 1, ch + 1); 2355 if (m_colourScale == PhaseColourScale) topLines = 1;
2356
2357 int ch = h - textHeight * (topLines + 1) - 8;
2358 // paint.drawRect(4, textHeight + 4, cw - 1, ch + 1);
2359 paint.drawRect(4 + cw - cbw, textHeight * topLines + 4, cbw - 1, ch + 1);
2213 2360
2214 QString top, bottom; 2361 QString top, bottom;
2215 2362 /*!!!
2216 switch (m_colourScale) { 2363 switch (m_colourScale) {
2217 default: 2364 default:
2218 case LinearColourScale: 2365 case LinearColourScale:
2219 top = (m_normalizeColumns ? "1.0" : "0.02"); 2366 top = (m_normalizeColumns ? "1.0" : "0.02");
2220 bottom = (m_normalizeColumns ? "0.0" : "0.00"); 2367 bottom = (m_normalizeColumns ? "0.0" : "0.00");
2227 arg(int(AudioLevel::multiplier_to_dB 2374 arg(int(AudioLevel::multiplier_to_dB
2228 (AudioLevel::preview_to_multiplier(0, 255)))); 2375 (AudioLevel::preview_to_multiplier(0, 255))));
2229 break; 2376 break;
2230 2377
2231 case dBColourScale: 2378 case dBColourScale:
2379 case OtherColourScale:
2232 top = "0"; 2380 top = "0";
2233 bottom = "-80"; 2381 bottom = "-80";
2234 break; 2382 break;
2235 2383
2236 case PhaseColourScale: 2384 case PhaseColourScale:
2237 top = QChar(0x3c0); 2385 top = QChar(0x3c0);
2238 bottom = "-" + top; 2386 bottom = "-" + top;
2239 break; 2387 break;
2240 } 2388 }
2241 2389 */
2242 paint.drawText((cw + 6 - paint.fontMetrics().width(top)) / 2, 2390 float min = m_viewMags[v].getMin();
2243 2 + textHeight + toff, top); 2391 float max = m_viewMags[v].getMax();
2244 2392
2245 paint.drawText((cw + 6 - paint.fontMetrics().width(bottom)) / 2, 2393 float dBmin = AudioLevel::multiplier_to_dB(min);
2246 h + toff - 3, bottom); 2394 float dBmax = AudioLevel::multiplier_to_dB(max);
2395
2396 if (dBmin < -80.f) dBmin = -80.f;
2397 bottom = QString("%1").arg(lrintf(dBmin));
2398
2399 if (dBmax < -80.f) dBmax = -80.f;
2400 else top = QString("%1").arg(lrintf(dBmax));
2401
2402 //!!! & phase etc
2403
2404 if (m_colourScale != PhaseColourScale) {
2405 paint.drawText((cw + 6 - paint.fontMetrics().width("dBFS")) / 2,
2406 2 + textHeight + toff, "dBFS");
2407 }
2408
2409 // paint.drawText((cw + 6 - paint.fontMetrics().width(top)) / 2,
2410 paint.drawText(3 + cw - cbw - paint.fontMetrics().width(top),
2411 2 + textHeight * topLines + toff + textHeight/2, top);
2412
2413 paint.drawText(3 + cw - cbw - paint.fontMetrics().width(bottom),
2414 h + toff - 3 - textHeight/2, bottom);
2247 2415
2248 paint.save(); 2416 paint.save();
2249 paint.setBrush(Qt::NoBrush); 2417 paint.setBrush(Qt::NoBrush);
2418
2419 int lasty = 0;
2420 int lastdb = 0;
2421
2250 for (int i = 0; i < ch; ++i) { 2422 for (int i = 0; i < ch; ++i) {
2251 int v = (i * 255) / ch + 1; 2423
2252 paint.setPen(m_colourMap.getColour(v)); 2424 float dBval = dBmin + (((dBmax - dBmin) * i) / (ch - 1));
2253 paint.drawLine(5, 4 + textHeight + ch - i, 2425 int idb = int(dBval);
2254 cw + 2, 4 + textHeight + ch - i); 2426
2427 float value = AudioLevel::dB_to_multiplier(dBval);
2428 int colour = getDisplayValue(v, value * m_gain);
2429 /*
2430 float value = min + (((max - min) * i) / (ch - 1));
2431 if (value < m_threshold) value = 0.f;
2432 int colour = getDisplayValue(v, value * m_gain);
2433 */
2434 /*
2435 int colour = (i * 255) / ch + 1;
2436 */
2437 paint.setPen(m_colourMap.getColour(colour));
2438
2439 int y = textHeight * topLines + 4 + ch - i;
2440
2441 paint.drawLine(5 + cw - cbw, y, cw + 2, y);
2442
2443 // paint.drawLine(5, 4 + textHeight + ch - i,
2444 // cw + 2, 4 + textHeight + ch - i);
2445
2446
2447 if (i == 0) {
2448 lasty = y;
2449 lastdb = idb;
2450 } else if (i < ch - paint.fontMetrics().ascent() &&
2451 ((abs(y - lasty) > textHeight &&
2452 idb % 10 == 0) ||
2453 (abs(y - lasty) > paint.fontMetrics().ascent() &&
2454 idb % 5 == 0))) {
2455 paint.setPen(Qt::black);
2456 QString text = QString("%1").arg(idb);
2457 paint.drawText(3 + cw - cbw - paint.fontMetrics().width(text),
2458 y + toff + textHeight/2, text);
2459 paint.setPen(Qt::white);
2460 paint.drawLine(5 + cw - cbw, y, 8 + cw - cbw, y);
2461 lasty = y;
2462 lastdb = idb;
2463 }
2255 } 2464 }
2256 paint.restore(); 2465 paint.restore();
2257 } 2466 }
2258 2467
2259 paint.drawLine(cw + 7, 0, cw + 7, h); 2468 paint.drawLine(cw + 7, 0, cw + 7, h);