Mercurial > hg > svgui
diff layer/SpectrogramLayer.cpp @ 44:ad214997dddb
* Refactor Layer classes so as no longer to store a single View pointer;
instead they need to be able to draw themselves on any View on demand.
Layers with caches (e.g. spectrogram) will need to be further refactored
so as to maintain a per-View cache
* Begin refactoring MainWindow by pulling out the document stuff (set of
layers, models etc) into a Document class. Not yet in use.
This revision is fairly unstable.
author | Chris Cannam |
---|---|
date | Thu, 02 Mar 2006 16:58:49 +0000 |
parents | 78515b1e29eb |
children | 25a2915d351d |
line wrap: on
line diff
--- a/layer/SpectrogramLayer.cpp Wed Mar 01 18:13:01 2006 +0000 +++ b/layer/SpectrogramLayer.cpp Thu Mar 02 16:58:49 2006 +0000 @@ -31,8 +31,8 @@ //#define DEBUG_SPECTROGRAM_REPAINT 1 -SpectrogramLayer::SpectrogramLayer(View *w, Configuration config) : - Layer(w), +SpectrogramLayer::SpectrogramLayer(Configuration config) : + Layer(), m_model(0), m_channel(0), m_windowSize(1024), @@ -54,6 +54,7 @@ m_pixmapCacheInvalid(true), m_fillThread(0), m_updateTimer(0), + m_candidateFillStartFrame(0), m_lastFillExtent(0), m_exiting(false) { @@ -74,9 +75,6 @@ setBinDisplay(PeakFrequencies); setNormalizeColumns(true); } - - if (m_view) m_view->setLightBackground(false); - m_view->addLayer(this); } SpectrogramLayer::~SpectrogramLayer() @@ -414,7 +412,7 @@ } else if (name == tr("Colour Rotation")) { setColourRotation(value); } else if (name == tr("Colour")) { - if (m_view) m_view->setLightBackground(value == 2); +//!!! if (v) v->setLightBackground(value == 2); switch (value) { default: case 0: setColourScheme(DefaultColours); break; @@ -800,7 +798,7 @@ } void -SpectrogramLayer::setLayerDormant(bool dormant) +SpectrogramLayer::setLayerDormant(const bool dormant) { if (dormant == m_dormant) return; @@ -893,16 +891,16 @@ m_lastFillExtent = fillExtent; } } else { - if (m_view) { +// if (v) { size_t sf = 0; - if (m_view->getStartFrame() > 0) sf = m_view->getStartFrame(); +//!!! if (v->getStartFrame() > 0) sf = v->getStartFrame(); #ifdef DEBUG_SPECTROGRAM_REPAINT std::cerr << "SpectrogramLayer: going backwards, emitting modelChanged(" - << sf << "," << m_view->getEndFrame() << ")" << std::endl; + << sf << "," << m_model->getEndFrame() << ")" << std::endl; #endif - emit modelChanged(sf, m_view->getEndFrame()); + emit modelChanged(sf, m_model->getEndFrame()); m_pixmapCacheInvalid = true; - } +// } m_lastFillExtent = fillExtent; } } @@ -1197,7 +1195,7 @@ SpectrogramLayer::Cache::~Cache() { - for (size_t i = 0; i < m_height; ++i) { + for (size_t i = 0; i < m_width; ++i) { if (m_magnitude && m_magnitude[i]) free(m_magnitude[i]); if (m_phase && m_phase[i]) free(m_phase[i]); } @@ -1228,24 +1226,24 @@ void SpectrogramLayer::Cache::resize(uint16_t **&array, size_t width, size_t height) { - for (size_t i = height; i < m_height; ++i) { + for (size_t i = width; i < m_width; ++i) { free(array[i]); } - if (height != m_height) { - array = (uint16_t **)realloc(array, height * sizeof(uint16_t *)); + if (width != m_width) { + array = (uint16_t **)realloc(array, width * sizeof(uint16_t *)); if (!array) throw std::bad_alloc(); - MUNLOCK(array, height * sizeof(uint16_t *)); + MUNLOCK(array, width * sizeof(uint16_t *)); } - for (size_t i = m_height; i < height; ++i) { + for (size_t i = m_width; i < width; ++i) { array[i] = 0; } - for (size_t i = 0; i < height; ++i) { - array[i] = (uint16_t *)realloc(array[i], width * sizeof(uint16_t)); + for (size_t i = 0; i < width; ++i) { + array[i] = (uint16_t *)realloc(array[i], height * sizeof(uint16_t)); if (!array[i]) throw std::bad_alloc(); - MUNLOCK(array[i], width * sizeof(uint16_t)); + MUNLOCK(array[i], height * sizeof(uint16_t)); } } @@ -1254,8 +1252,8 @@ { for (size_t x = 0; x < m_width; ++x) { for (size_t y = 0; y < m_height; ++y) { - m_magnitude[y][x] = 0; - m_phase[y][x] = 0; + m_magnitude[x][y] = 0; + m_phase[x][y] = 0; } m_factor[x] = 1.0; } @@ -1304,19 +1302,8 @@ size_t windowSize = m_layer.m_windowSize; size_t windowIncrement = m_layer.getWindowIncrement(); - size_t visibleStart = start; - size_t visibleEnd = end; - - if (m_layer.m_view) { - if (m_layer.m_view->getStartFrame() < 0) { - visibleStart = 0; - } else { - visibleStart = m_layer.m_view->getStartFrame(); - visibleStart = (visibleStart / windowIncrement) * - windowIncrement; - } - visibleEnd = m_layer.m_view->getEndFrame(); - } + size_t visibleStart = m_layer.m_candidateFillStartFrame; + visibleStart = (visibleStart / windowIncrement) * windowIncrement; size_t width = (end - start) / windowIncrement + 1; size_t height = windowSize / 2; @@ -1363,39 +1350,11 @@ int updateAt = (end / windowIncrement) / 20; if (updateAt < 100) updateAt = 100; - bool doVisibleFirst = (visibleStart != start && visibleEnd != end); + bool doVisibleFirst = (visibleStart != start); if (doVisibleFirst) { - for (size_t f = visibleStart; f < visibleEnd; f += windowIncrement) { - - m_layer.fillCacheColumn(int((f - start) / windowIncrement), - input, output, plan, - windowSize, windowIncrement, - windower); - - if (m_layer.m_cacheInvalid || m_layer.m_exiting) { - interrupted = true; - m_fillExtent = 0; - break; - } - - if (++counter == updateAt || - (f >= visibleEnd - 1 && f < visibleEnd + windowIncrement)) { - if (f < end) m_fillExtent = f; - m_fillCompletion = size_t(100 * fabsf(float(f - visibleStart) / - float(end - start))); - counter = 0; - } - } - - std::cerr << "SpectrogramLayer::CacheFillThread::run: visible bit done" << std::endl; - m_layer.m_view->update(); - } - - if (!interrupted && doVisibleFirst) { - - for (size_t f = visibleEnd; f < end; f += windowIncrement) { + for (size_t f = visibleStart; f < end; f += windowIncrement) { m_layer.fillCacheColumn(int((f - start) / windowIncrement), input, output, plan, @@ -1440,8 +1399,7 @@ break; } - if (++counter == updateAt || - (f >= visibleEnd - 1 && f < visibleEnd + windowIncrement)) { + if (++counter == updateAt) { m_fillExtent = f; m_fillCompletion = baseCompletion + size_t(100 * fabsf(float(f - start) / @@ -1498,9 +1456,9 @@ } bool -SpectrogramLayer::getYBinRange(int y, float &q0, float &q1) const +SpectrogramLayer::getYBinRange(View *v, int y, float &q0, float &q1) const { - int h = m_view->height(); + int h = v->height(); if (y < 0 || y >= h) return false; int sr = m_model->getSampleRate(); @@ -1509,8 +1467,8 @@ bool logarithmic = (m_frequencyScale == LogFrequencyScale); - q0 = m_view->getFrequencyForY(y, minf, maxf, logarithmic); - q1 = m_view->getFrequencyForY(y - 1, minf, maxf, logarithmic); + q0 = v->getFrequencyForY(y, minf, maxf, logarithmic); + q1 = v->getFrequencyForY(y - 1, minf, maxf, logarithmic); // Now map these on to actual bins @@ -1528,14 +1486,14 @@ } bool -SpectrogramLayer::getXBinRange(int x, float &s0, float &s1) const +SpectrogramLayer::getXBinRange(View *v, int x, float &s0, float &s1) const { size_t modelStart = m_model->getStartFrame(); size_t modelEnd = m_model->getEndFrame(); // Each pixel column covers an exact range of sample frames: - int f0 = getFrameForX(x) - modelStart; - int f1 = getFrameForX(x + 1) - modelStart - 1; + int f0 = v->getFrameForX(x) - modelStart; + int f1 = v->getFrameForX(x + 1) - modelStart - 1; if (f1 < int(modelStart) || f0 > int(modelEnd)) { return false; @@ -1552,10 +1510,10 @@ } bool -SpectrogramLayer::getXBinSourceRange(int x, RealTime &min, RealTime &max) const +SpectrogramLayer::getXBinSourceRange(View *v, int x, RealTime &min, RealTime &max) const { float s0 = 0, s1 = 0; - if (!getXBinRange(x, s0, s1)) return false; + if (!getXBinRange(v, x, s0, s1)) return false; int s0i = int(s0 + 0.001); int s1i = int(s1); @@ -1571,11 +1529,11 @@ } bool -SpectrogramLayer::getYBinSourceRange(int y, float &freqMin, float &freqMax) +SpectrogramLayer::getYBinSourceRange(View *v, int y, float &freqMin, float &freqMax) const { float q0 = 0, q1 = 0; - if (!getYBinRange(y, q0, q1)) return false; + if (!getYBinRange(v, y, q0, q1)) return false; int q0i = int(q0 + 0.001); int q1i = int(q1); @@ -1591,16 +1549,16 @@ } bool -SpectrogramLayer::getAdjustedYBinSourceRange(int x, int y, +SpectrogramLayer::getAdjustedYBinSourceRange(View *v, int x, int y, float &freqMin, float &freqMax, float &adjFreqMin, float &adjFreqMax) const { float s0 = 0, s1 = 0; - if (!getXBinRange(x, s0, s1)) return false; + if (!getXBinRange(v, x, s0, s1)) return false; float q0 = 0, q1 = 0; - if (!getYBinRange(y, q0, q1)) return false; + if (!getYBinRange(v, y, q0, q1)) return false; int s0i = int(s0 + 0.001); int s1i = int(s1); @@ -1661,15 +1619,15 @@ } bool -SpectrogramLayer::getXYBinSourceRange(int x, int y, +SpectrogramLayer::getXYBinSourceRange(View *v, int x, int y, float &min, float &max, float &phaseMin, float &phaseMax) const { float q0 = 0, q1 = 0; - if (!getYBinRange(y, q0, q1)) return false; + if (!getYBinRange(v, y, q0, q1)) return false; float s0 = 0, s1 = 0; - if (!getXBinRange(x, s0, s1)) return false; + if (!getXBinRange(v, x, s0, s1)) return false; int q0i = int(q0 + 0.001); int q1i = int(q1); @@ -1722,13 +1680,15 @@ } void -SpectrogramLayer::paint(QPainter &paint, QRect rect) const +SpectrogramLayer::paint(View *v, QPainter &paint, QRect rect) const { // Profiler profiler("SpectrogramLayer::paint", true); #ifdef DEBUG_SPECTROGRAM_REPAINT - std::cerr << "SpectrogramLayer::paint(): m_model is " << m_model << ", zoom level is " << m_view->getZoomLevel() << ", m_updateTimer " << m_updateTimer << ", pixmap cache invalid " << m_pixmapCacheInvalid << std::endl; + std::cerr << "SpectrogramLayer::paint(): m_model is " << m_model << ", zoom level is " << v->getZoomLevel() << ", m_updateTimer " << m_updateTimer << ", pixmap cache invalid " << m_pixmapCacheInvalid << std::endl; #endif + m_candidateFillStartFrame = v->getStartFrame(); + if (!m_model || !m_model->isOK() || !m_model->isReady()) { return; } @@ -1762,13 +1722,13 @@ std::cerr << "SpectrogramLayer::paint(): Still cacheing = " << stillCacheing << std::endl; #endif - long startFrame = m_view->getStartFrame(); - int zoomLevel = m_view->getZoomLevel(); + long startFrame = v->getStartFrame(); + int zoomLevel = v->getZoomLevel(); int x0 = 0; - int x1 = m_view->width(); + int x1 = v->width(); int y0 = 0; - int y1 = m_view->height(); + int y1 = v->height(); bool recreateWholePixmapCache = true; @@ -1780,11 +1740,11 @@ //make it optional) if (int(m_pixmapCacheZoomLevel) == zoomLevel && - m_pixmapCache->width() == m_view->width() && - m_pixmapCache->height() == m_view->height()) { - - if (getXForFrame(m_pixmapCacheStartFrame) == - getXForFrame(startFrame)) { + m_pixmapCache->width() == v->width() && + m_pixmapCache->height() == v->height()) { + + if (v->getXForFrame(m_pixmapCacheStartFrame) == + v->getXForFrame(startFrame)) { #ifdef DEBUG_SPECTROGRAM_REPAINT std::cerr << "SpectrogramLayer: pixmap cache good" << std::endl; @@ -1802,8 +1762,8 @@ recreateWholePixmapCache = false; - int dx = getXForFrame(m_pixmapCacheStartFrame) - - getXForFrame(startFrame); + int dx = v->getXForFrame(m_pixmapCacheStartFrame) - + v->getXForFrame(startFrame); #ifdef DEBUG_SPECTROGRAM_REPAINT std::cerr << "SpectrogramLayer: dx = " << dx << " (pixmap cache " << m_pixmapCache->width() << "x" << m_pixmapCache->height() << ")" << std::endl; @@ -1914,7 +1874,7 @@ float s0 = 0, s1 = 0; - if (!getXBinRange(x0 + x, s0, s1)) { + if (!getXBinRange(v, x0 + x, s0, s1)) { assert(x <= scaled.width()); m_mutex.unlock(); continue; @@ -1932,8 +1892,8 @@ if (m_binDisplay != PeakFrequencies || s1i >= int(m_cache->getWidth())) { - y0 = m_view->getYForFrequency(f1, minFreq, maxFreq, logarithmic); - y1 = m_view->getYForFrequency(f0, minFreq, maxFreq, logarithmic); + y0 = v->getYForFrequency(f1, minFreq, maxFreq, logarithmic); + y1 = v->getYForFrequency(f0, minFreq, maxFreq, logarithmic); } for (int s = s0i; s <= s1i; ++s) { @@ -1961,7 +1921,7 @@ m_cache->getPhaseAt(s+1, q), steady); - y0 = y1 = m_view->getYForFrequency + y0 = y1 = v->getYForFrequency (f0, minFreq, maxFreq, logarithmic); } @@ -2032,21 +1992,21 @@ } float -SpectrogramLayer::getYForFrequency(float frequency) const +SpectrogramLayer::getYForFrequency(View *v, float frequency) const { - return m_view->getYForFrequency(frequency, - getEffectiveMinFrequency(), - getEffectiveMaxFrequency(), - m_frequencyScale == LogFrequencyScale); + return v->getYForFrequency(frequency, + getEffectiveMinFrequency(), + getEffectiveMaxFrequency(), + m_frequencyScale == LogFrequencyScale); } float -SpectrogramLayer::getFrequencyForY(int y) const +SpectrogramLayer::getFrequencyForY(View *v, int y) const { - return m_view->getFrequencyForY(y, - getEffectiveMinFrequency(), - getEffectiveMaxFrequency(), - m_frequencyScale == LogFrequencyScale); + return v->getFrequencyForY(y, + getEffectiveMinFrequency(), + getEffectiveMaxFrequency(), + m_frequencyScale == LogFrequencyScale); } int @@ -2059,7 +2019,7 @@ } bool -SpectrogramLayer::snapToFeatureFrame(int &frame, +SpectrogramLayer::snapToFeatureFrame(View *v, int &frame, size_t &resolution, SnapType snap) const { @@ -2081,7 +2041,7 @@ } QString -SpectrogramLayer::getFeatureDescription(QPoint &pos) const +SpectrogramLayer::getFeatureDescription(View *v, QPoint &pos) const { int x = pos.x(); int y = pos.y(); @@ -2097,10 +2057,10 @@ bool haveValues = false; - if (!getXBinSourceRange(x, rtMin, rtMax)) { + if (!getXBinSourceRange(v, x, rtMin, rtMax)) { return ""; } - if (getXYBinSourceRange(x, y, magMin, magMax, phaseMin, phaseMax)) { + if (getXYBinSourceRange(v, x, y, magMin, magMax, phaseMin, phaseMax)) { haveValues = true; } @@ -2108,7 +2068,7 @@ if (m_binDisplay == PeakFrequencies) { - if (!getAdjustedYBinSourceRange(x, y, freqMin, freqMax, + if (!getAdjustedYBinSourceRange(v, x, y, freqMin, freqMax, adjFreqMin, adjFreqMax)) { return ""; } @@ -2132,7 +2092,7 @@ } else { - if (!getYBinSourceRange(y, freqMin, freqMax)) return ""; + if (!getYBinSourceRange(v, y, freqMin, freqMax)) return ""; } QString text; @@ -2218,7 +2178,7 @@ } int -SpectrogramLayer::getVerticalScaleWidth(QPainter &paint) const +SpectrogramLayer::getVerticalScaleWidth(View *v, QPainter &paint) const { if (!m_model || !m_model->isOK()) return 0; @@ -2238,7 +2198,7 @@ } void -SpectrogramLayer::paintVerticalScale(QPainter &paint, QRect rect) const +SpectrogramLayer::paintVerticalScale(View *v, QPainter &paint, QRect rect) const { if (!m_model || !m_model->isOK()) { return; @@ -2317,10 +2277,10 @@ int bin = -1; - for (int y = 0; y < m_view->height(); ++y) { + for (int y = 0; y < v->height(); ++y) { float q0, q1; - if (!getYBinRange(m_view->height() - y, q0, q1)) continue; + if (!getYBinRange(v, v->height() - y, q0, q1)) continue; int vy; @@ -2366,7 +2326,7 @@ for (int i = 0; i < 128; ++i) { float f = Pitch::getFrequencyForPitch(i); - int y = lrintf(m_view->getYForFrequency(f, minf, maxf, true)); + int y = lrintf(v->getYForFrequency(f, minf, maxf, true)); int n = (i % 12); if (n == 1 || n == 3 || n == 6 || n == 8 || n == 10) { // black notes