comparison layer/SpectrogramLayer.cpp @ 92:23d1e37bbfb4

* Make a single base Thread class for RT and non-RT threads * Pull ResizeableBitmap out from the MatrixFile's ColumnBitmap * Reorder SpectrogramLayer::paint somewhat so as to improve cache hit ratio in the FFT file cache
author Chris Cannam
date Mon, 08 May 2006 16:44:47 +0000
parents ed01c1261b55
children 05c41701dc6c
comparison
equal deleted inserted replaced
91:ed01c1261b55 92:23d1e37bbfb4
25 #include <QPainter> 25 #include <QPainter>
26 #include <QImage> 26 #include <QImage>
27 #include <QPixmap> 27 #include <QPixmap>
28 #include <QRect> 28 #include <QRect>
29 #include <QTimer> 29 #include <QTimer>
30 #include <QApplication>
30 31
31 #include <iostream> 32 #include <iostream>
32 33
33 #include <cassert> 34 #include <cassert>
34 #include <cmath> 35 #include <cmath>
35 36
36 #define DEBUG_SPECTROGRAM_REPAINT 1 37 //#define DEBUG_SPECTROGRAM_REPAINT 1
37 38
38 static double mod(double x, double y) 39 static double mod(double x, double y)
39 { 40 {
40 double a = floor(x / y); 41 double a = floor(x / y);
41 double b = x - (y * a); 42 double b = x - (y * a);
1746 int y0 = 0; 1747 int y0 = 0;
1747 int y1 = v->height(); 1748 int y1 = v->height();
1748 1749
1749 bool recreateWholePixmapCache = true; 1750 bool recreateWholePixmapCache = true;
1750 1751
1752 // if (stillCacheing) {
1753 x0 = rect.left();
1754 x1 = rect.right() + 1;
1755 y0 = rect.top();
1756 y1 = rect.bottom() + 1;
1757 // }
1758
1751 if (!m_pixmapCacheInvalid) { 1759 if (!m_pixmapCacheInvalid) {
1752 1760
1753 //!!! This cache may have been obsoleted entirely by the 1761 //!!! This cache may have been obsoleted entirely by the
1754 //scrolling cache in View. Perhaps experiment with 1762 //scrolling cache in View. Perhaps experiment with
1755 //removing it and see if it makes things even quicker (or else 1763 //removing it and see if it makes things even quicker (or else
1830 #ifdef DEBUG_SPECTROGRAM_REPAINT 1838 #ifdef DEBUG_SPECTROGRAM_REPAINT
1831 std::cerr << "SpectrogramLayer: pixmap cache useless" << std::endl; 1839 std::cerr << "SpectrogramLayer: pixmap cache useless" << std::endl;
1832 #endif 1840 #endif
1833 } 1841 }
1834 } 1842 }
1835 1843 /*
1836 if (stillCacheing) { 1844 if (stillCacheing) {
1837 x0 = rect.left(); 1845 x0 = rect.left();
1838 x1 = rect.right() + 1; 1846 x1 = rect.right() + 1;
1839 y0 = rect.top(); 1847 y0 = rect.top();
1840 y1 = rect.bottom() + 1; 1848 y1 = rect.bottom() + 1;
1841 } 1849 }
1842 1850 */
1843 int w = x1 - x0; 1851 int w = x1 - x0;
1844 int h = y1 - y0; 1852 int h = y1 - y0;
1845 1853
1846 // std::cerr << "x0 " << x0 << ", x1 " << x1 << ", w " << w << ", h " << h << std::endl; 1854 // std::cerr << "x0 " << x0 << ", x1 " << x1 << ", w " << w << ", h " << h << std::endl;
1847 1855
1848 QImage scaled(w, h, QImage::Format_RGB32); 1856 QImage scaled(w, h, QImage::Format_RGB32);
1849 scaled.fill(m_colourMap.getColour(0).rgb()); 1857 scaled.fill(m_colourMap.getColour(0).rgb());
1850
1851 float ymag[h];
1852 float ydiv[h];
1853 1858
1854 int sr = m_model->getSampleRate(); 1859 int sr = m_model->getSampleRate();
1855 1860
1856 size_t bins = m_windowSize / 2; 1861 size_t bins = m_windowSize / 2;
1857 if (m_maxFrequency > 0) { 1862 if (m_maxFrequency > 0) {
1867 } 1872 }
1868 1873
1869 float minFreq = (float(minbin) * sr) / m_windowSize; 1874 float minFreq = (float(minbin) * sr) / m_windowSize;
1870 float maxFreq = (float(bins) * sr) / m_windowSize; 1875 float maxFreq = (float(bins) * sr) / m_windowSize;
1871 1876
1877 float ymag[h];
1878 float ydiv[h];
1879 float yval[bins + 1];
1880
1872 size_t increment = getWindowIncrement(); 1881 size_t increment = getWindowIncrement();
1873 1882
1874 bool logarithmic = (m_frequencyScale == LogFrequencyScale); 1883 bool logarithmic = (m_frequencyScale == LogFrequencyScale);
1875 1884
1876 m_mutex.unlock(); 1885 m_mutex.unlock();
1886
1887 for (size_t q = minbin; q <= bins; ++q) {
1888 float f0 = (float(q) * sr) / m_windowSize;
1889 yval[q] = v->getYForFrequency(f0, minFreq, maxFreq, logarithmic);
1890 }
1877 1891
1878 for (int x = 0; x < w; ++x) { 1892 for (int x = 0; x < w; ++x) {
1879 1893
1880 m_mutex.lock(); 1894 m_mutex.lock();
1881 if (m_cacheInvalid) { 1895 if (m_cacheInvalid) {
1905 continue; 1919 continue;
1906 } else { 1920 } else {
1907 s1i = s0i; 1921 s1i = s0i;
1908 } 1922 }
1909 } 1923 }
1910 1924
1911 bool haveColumn = false; 1925 for (int s = s0i; s <= s1i; ++s) {
1912 for (size_t s = s0i; s <= s1i; ++s) { 1926
1913 if (m_cache->haveColumnAt(s)) { 1927 if (!m_cache->haveColumnAt(s)) continue;
1914 haveColumn = true; 1928
1915 break; 1929 for (size_t q = minbin; q < bins; ++q) {
1916 } 1930
1917 } 1931 // float f0 = (float(q) * sr) / m_windowSize;
1918 if (!haveColumn) { 1932 // float f1 = (float(q + 1) * sr) / m_windowSize;
1919 m_mutex.unlock(); 1933
1920 continue; 1934 // float y0 = 0, y1 = 0;
1921 } 1935
1922 1936 float y0 = yval[q + 1];
1923 for (size_t q = minbin; q < bins; ++q) { 1937 float y1 = yval[q];
1924 1938
1925 float f0 = (float(q) * sr) / m_windowSize; 1939
1926 float f1 = (float(q + 1) * sr) / m_windowSize; 1940 /*
1927 1941 if (m_binDisplay != PeakFrequencies) {
1928 float y0 = 0, y1 = 0; 1942 y0 = v->getYForFrequency(f1, minFreq, maxFreq, logarithmic);
1929 1943 y1 = v->getYForFrequency(f0, minFreq, maxFreq, logarithmic);
1930 if (m_binDisplay != PeakFrequencies) { 1944 }
1931 y0 = v->getYForFrequency(f1, minFreq, maxFreq, logarithmic); 1945 */
1932 y1 = v->getYForFrequency(f0, minFreq, maxFreq, logarithmic);
1933 }
1934
1935 for (int s = s0i; s <= s1i; ++s) {
1936
1937 if (m_binDisplay == PeakBins || 1946 if (m_binDisplay == PeakBins ||
1938 m_binDisplay == PeakFrequencies) { 1947 m_binDisplay == PeakFrequencies) {
1939 if (!m_cache->isLocalPeak(s, q)) continue; 1948 if (!m_cache->isLocalPeak(s, q)) continue;
1940 } 1949 }
1941 1950
1947 1956
1948 if (m_binDisplay == PeakFrequencies && 1957 if (m_binDisplay == PeakFrequencies &&
1949 s < int(m_cache->getWidth()) - 1) { 1958 s < int(m_cache->getWidth()) - 1) {
1950 1959
1951 bool steady = false; 1960 bool steady = false;
1952 f0 = f1 = calculateFrequency(q, 1961 // f0 = f1 = calculateFrequency(q,
1962 float f = calculateFrequency(q,
1953 m_windowSize, 1963 m_windowSize,
1954 increment, 1964 increment,
1955 sr, 1965 sr,
1956 m_cache->getPhaseAt(s, q), 1966 m_cache->getPhaseAt(s, q),
1957 m_cache->getPhaseAt(s+1, q), 1967 m_cache->getPhaseAt(s+1, q),
1958 steady); 1968 steady);
1959 1969
1960 y0 = y1 = v->getYForFrequency 1970 y0 = y1 = v->getYForFrequency
1961 (f0, minFreq, maxFreq, logarithmic); 1971 // (f0, minFreq, maxFreq, logarithmic);
1972 (f, minFreq, maxFreq, logarithmic);
1962 } 1973 }
1963 1974
1964 int y0i = int(y0 + 0.001); 1975 int y0i = int(y0 + 0.001);
1965 int y1i = int(y1); 1976 int y1i = int(y1);
1966 1977
1978 float value;
1979
1980 if (m_colourScale == PhaseColourScale) {
1981 value = m_cache->getPhaseAt(s, q);
1982 } else if (m_normalizeColumns) {
1983 value = m_cache->getNormalizedMagnitudeAt(s, q) * m_gain;
1984 } else {
1985 value = m_cache->getMagnitudeAt(s, q) * m_gain;
1986 }
1987
1967 for (int y = y0i; y <= y1i; ++y) { 1988 for (int y = y0i; y <= y1i; ++y) {
1968 1989
1969 if (y < 0 || y >= h) continue; 1990 if (y < 0 || y >= h) continue;
1970 1991
1971 float yprop = sprop; 1992 float yprop = sprop;
1972 if (y == y0i) yprop *= (y + 1) - y0; 1993 if (y == y0i) yprop *= (y + 1) - y0;
1973 if (y == y1i) yprop *= y1 - y; 1994 if (y == y1i) yprop *= y1 - y;
1974
1975 float value;
1976
1977 if (m_colourScale == PhaseColourScale) {
1978 value = m_cache->getPhaseAt(s, q);
1979 } else if (m_normalizeColumns) {
1980 value = m_cache->getNormalizedMagnitudeAt(s, q) * m_gain;
1981 } else {
1982 value = m_cache->getMagnitudeAt(s, q) * m_gain;
1983 }
1984
1985 ymag[y] += yprop * value; 1995 ymag[y] += yprop * value;
1986 ydiv[y] += yprop; 1996 ydiv[y] += yprop;
1987 } 1997 }
1988 } 1998 }
1989 } 1999 }