changeset 1121:d930ff725f64 spectrogram-minor-refactor

Wiring through the magnitude range updates
author Chris Cannam
date Fri, 22 Jul 2016 12:17:55 +0100
parents 65cdaf8d6b50
children 94370157b265
files layer/Colour3DPlotLayer.cpp layer/Colour3DPlotLayer.h layer/Colour3DPlotRenderer.cpp layer/Colour3DPlotRenderer.h layer/SpectrogramLayer.cpp layer/SpectrogramLayer.h
diffstat 6 files changed, 135 insertions(+), 83 deletions(-) [+]
line wrap: on
line diff
--- a/layer/Colour3DPlotLayer.cpp	Wed Jul 20 13:40:23 2016 +0100
+++ b/layer/Colour3DPlotLayer.cpp	Fri Jul 22 12:17:55 2016 +0100
@@ -609,16 +609,19 @@
 }
 
 bool
-Colour3DPlotLayer::isLayerScrollable(const LayerGeometryProvider *v) const
+Colour3DPlotLayer::isLayerScrollable(const LayerGeometryProvider */* v */) const
 {
     if (m_normalizeVisibleArea) {
         return false;
     }
-    if (getRenderer(v)->willRenderOpaque(v)) {
-        return true;
-    }
-    QPoint discard;
-    return !v->shouldIlluminateLocalFeatures(this, discard);
+    //!!! ah hang on, if we're potentially rendering incrementally
+    //!!! they we can't be scrollable
+    return false;
+//    if (getRenderer(v)->willRenderOpaque(v)) {
+//        return true;
+//    }
+//    QPoint discard;
+//    return !v->shouldIlluminateLocalFeatures(this, discard);
 }
 
 bool
@@ -1080,31 +1083,39 @@
 Colour3DPlotLayer::paintWithRenderer(LayerGeometryProvider *v,
                                      QPainter &paint, QRect rect) const
 {
-    static int depth = 0;
-    
     Colour3DPlotRenderer *renderer = getRenderer(v);
 
+    Colour3DPlotRenderer::RenderResult result;
+    
     if (m_synchronous) {
-        (void)renderer->render(v, paint, rect);
-        return;
+
+        result = renderer->render(v, paint, rect);
+
+    } else {
+
+        result = renderer->renderTimeConstrained(v, paint, rect);
+
+        //!!! + mag range
+
+        QRect uncached = renderer->getLargestUncachedRect(v);
+        if (uncached.width() > 0) {
+            cerr << "updating rect at " << uncached.x() << " width "
+                 << uncached.width() << endl;
+            v->updatePaintRect(uncached);
+        }
     }
+    
+    //!!! at the mo this measures the range of the whole thing, not
+    //!!! just the view - need to reset it when view extents change
 
-    ++depth;
-    cerr << "paint depth " << depth << endl;
+    m_viewMags[v->getId()].sample(result.range);
     
-    (void)renderer->renderTimeConstrained(v, paint, rect);
-
-    //!!! + mag range
-
-    QRect uncached = renderer->getLargestUncachedRect();
-    if (uncached.width() > 0) {
-        cerr << "updating rect at " << uncached.x() << " width "
-             << uncached.width() << endl;
-        v->updatePaintRect(uncached);
-    }
-
-    cerr << "exiting paint depth " << depth << endl;
-    --depth;
+    cerr << "mag range in this view: "
+         << m_viewMags[v->getId()].getMin()
+         << " -> "
+         << m_viewMags[v->getId()].getMax()
+         << endl;
+        
 }
 
 void
--- a/layer/Colour3DPlotLayer.h	Wed Jul 20 13:40:23 2016 +0100
+++ b/layer/Colour3DPlotLayer.h	Fri Jul 22 12:17:55 2016 +0100
@@ -185,8 +185,12 @@
     const int m_peakCacheDivisor;
     Dense3DModelPeakCache *getPeakCache() const;
 
+    typedef std::map<int, MagnitudeRange> ViewMagMap; // key is view id
+    mutable ViewMagMap m_viewMags;
+
     typedef std::map<int, Colour3DPlotRenderer *> ViewRendererMap; // key is view id
     mutable ViewRendererMap m_renderers;
+    
     Colour3DPlotRenderer *getRenderer(const LayerGeometryProvider *) const;
     void invalidateRenderers();
         
--- a/layer/Colour3DPlotRenderer.cpp	Wed Jul 20 13:40:23 2016 +0100
+++ b/layer/Colour3DPlotRenderer.cpp	Fri Jul 22 12:17:55 2016 +0100
@@ -48,8 +48,14 @@
 }
 
 QRect
-Colour3DPlotRenderer::getLargestUncachedRect()
+Colour3DPlotRenderer::getLargestUncachedRect(const LayerGeometryProvider *v)
 {
+    RenderType renderType = decideRenderType(v);
+
+    if (renderType == DirectTranslucent) {
+        return QRect(); // never cached
+    }
+
     int h = m_cache.getSize().height();
 
     QRect areaLeft(0, 0, m_cache.getValidLeft(), h);
@@ -91,20 +97,8 @@
     m_magCache.setZoomLevel(v->getZoomLevel());
     
     if (renderType == DirectTranslucent) {
-        renderDirectTranslucent(v, paint, rect);
-        //!!! mag range!
-
-        //!!! a dev debug check
-        if (!m_magCache.areColumnsSet(x0, x1 - x0)) {
-            cerr << "Columns (" << x0 << " -> " << x1-x0
-                 << ") not set in mag cache" << endl;
-            throw std::logic_error("Columns not set in mag cache");
-        }
-
-        //!!! this is wrong
-        MagnitudeRange range = m_magCache.getRange(x0, x1-x0);
-
-        return { rect, range }; //!!! this return arg is not very useful
+        MagnitudeRange range = renderDirectTranslucent(v, paint, rect);
+        return { rect, range };
     }
     
     cerr << "cache start " << m_cache.getStartFrame()
@@ -130,9 +124,9 @@
 
             //!!! a dev debug check
             if (!m_magCache.areColumnsSet(x0, x1 - x0)) {
-                cerr << "Columns (" << x0 << " -> " << x1-x0
+                cerr << "NB Columns (" << x0 << " -> " << x1-x0
                      << ") not set in mag cache" << endl;
-                throw std::logic_error("Columns not set in mag cache");
+//                throw std::logic_error("Columns not set in mag cache");
             }
             
             MagnitudeRange range = m_magCache.getRange(x0, x1-x0);
@@ -231,9 +225,9 @@
 
     //!!! a dev debug check
     if (!m_magCache.areColumnsSet(x0, x1 - x0)) {
-        cerr << "Columns (" << x0 << " -> " << x1-x0
+        cerr << "NB Columns (" << x0 << " -> " << x1-x0
              << ") not set in mag cache" << endl;
-        throw std::logic_error("Columns not set in mag cache");
+//        throw std::logic_error("Columns not set in mag cache");
     }
     
     MagnitudeRange range = m_magCache.getRange(x0, x1-x0);
@@ -298,13 +292,15 @@
     }
 }
 
-void
+MagnitudeRange
 Colour3DPlotRenderer::renderDirectTranslucent(const LayerGeometryProvider *v,
                                               QPainter &paint,
                                               QRect rect)
 {
     Profiler profiler("Colour3DPlotRenderer::renderDirectTranslucent");
 
+    MagnitudeRange magRange;
+    
     QPoint illuminatePos;
     bool illuminate = v->shouldIlluminateLocalFeatures
         (m_sources.verticalBinLayer, illuminatePos);
@@ -367,6 +363,8 @@
                 vector<float>(fullColumn.data() + minbin,
                               fullColumn.data() + maxbin + 1);
 
+            magRange.sample(column);
+
 //!!! fft scale                if (m_colourScale != ColourScaleType::Phase) {
 //                    column = ColumnOp::fftScale(column, m_fftSize);
 //                }
@@ -461,7 +459,8 @@
 	    }
 	}
     }
-   
+
+    return magRange;
 }
 
 void
@@ -555,6 +554,10 @@
     m_cache.drawImage(paintedLeft, attainedWidth,
                       m_drawBuffer,
                       paintedLeft - x0, attainedWidth);
+
+    for (int i = 0; in_range_for(m_magRanges, i); ++i) {
+        m_magCache.sampleColumn(i, m_magRanges.at(i));
+    }
 }
 
 void
@@ -685,6 +688,13 @@
                           scaled,
                           sourceLeft, sourceWidth);
     }
+    
+    for (int i = 0; i < targetWidth; ++i) {
+        int sourceIx = int((double(i) / targetWidth) * sourceWidth);
+        if (in_range_for(m_magRanges, sourceIx)) {
+            m_magCache.sampleColumn(i, m_magRanges.at(sourceIx));
+        }
+    }
 }
 
 int
@@ -732,8 +742,9 @@
     vector<float> preparedColumn;
 
     int modelWidth = sourceModel->getWidth();
-    cerr << "modelWidth " << modelWidth << endl;
-            
+
+    cerr << "modelWidth " << modelWidth << ", divisor " << divisor << endl;
+
     for (int x = start; x != finish; x += step) {
 
         // x is the on-canvas pixel coord; sx (later) will be the
@@ -742,7 +753,7 @@
         ++columnCount;
 
 #ifdef DEBUG_SPECTROGRAM_REPAINT
-        cerr << "x = " << x << endl;
+        cerr << "x = " << x << ", binforx[x] = " << binforx[x] << endl;
 #endif
         
         if (binforx[x] < 0) continue;
@@ -755,6 +766,7 @@
         if (sx1 <= sx0) sx1 = sx0 + 1;
 
         vector<float> pixelPeakColumn;
+        MagnitudeRange magRange;
         
         for (int sx = sx0; sx < sx1; ++sx) {
 
@@ -786,12 +798,7 @@
 //                    column = ColumnOp::fftScale(column, m_fftSize);
 //                }
 
-                MagnitudeRange r;
-                r.sample(column);
-                int magColIndex = sx - int(m_magCache.getStartFrame() /
-                                           sourceModel->getResolution());
-                cerr << "magColIndex = " << magColIndex << endl;
-                m_magCache.sampleColumn(magColIndex, r);
+                magRange.sample(column);
                 
 //!!! extents                recordColumnExtents(column,
 //                                    sx,
@@ -827,6 +834,7 @@
         }
 
         if (!pixelPeakColumn.empty()) {
+
             for (int y = 0; y < h; ++y) {
                 int py;
                 if (m_params.invertVertical) {
@@ -839,10 +847,13 @@
                      py,
                      m_params.colourScale.getPixel(pixelPeakColumn[y]));
             }
+            
+            m_magRanges.push_back(magRange);
         }
 
         double fractionComplete = double(columnCount) / double(w);
         if (timer.outOfTime(fractionComplete)) {
+            cerr << "out of time" << endl;
             return columnCount;
         }
     }
@@ -916,6 +927,7 @@
         if (sx1 <= sx0) sx1 = sx0 + 1;
 
         vector<float> pixelPeakColumn;
+        MagnitudeRange magRange;
         
         for (int sx = sx0; sx < sx1; ++sx) {
 
@@ -931,6 +943,8 @@
                     vector<float>(fullColumn.data() + minbin,
                                   fullColumn.data() + maxbin + 1);
 
+                magRange.sample(column);
+                
 //!!! fft scale                if (m_colourScale != ColourScaleType::Phase) {
 //                    column = ColumnOp::fftScale(column, getFFTSize());
 //                }
@@ -963,6 +977,7 @@
         }
 
         if (!pixelPeakColumn.empty()) {
+            
             for (FFTModel::PeakSet::const_iterator pi = peakfreqs.begin();
                  pi != peakfreqs.end(); ++pi) {
 
@@ -985,6 +1000,8 @@
                      iy,
                      m_params.colourScale.getPixel(value));
             }
+
+            m_magRanges.push_back(magRange);
         }
 
         double fractionComplete = double(columnCount) / double(w);
@@ -1009,6 +1026,7 @@
     }
 
     m_drawBuffer.fill(0);
+    m_magRanges.clear();
 }
 
 void
@@ -1018,6 +1036,7 @@
         recreateDrawBuffer(w, h);
     } else {
         m_drawBuffer.fill(0);
+        m_magRanges.clear();
     }
 }
 
--- a/layer/Colour3DPlotRenderer.h	Wed Jul 20 13:40:23 2016 +0100
+++ b/layer/Colour3DPlotRenderer.h	Fri Jul 22 12:17:55 2016 +0100
@@ -163,7 +163,7 @@
      *
      * Returns an empty QRect if the cache is entirely valid.
      */
-    QRect getLargestUncachedRect();
+    QRect getLargestUncachedRect(const LayerGeometryProvider *v);
 
     /**
      * Return true if the rendering will be opaque. This may be used
@@ -184,6 +184,12 @@
     // member is to avoid reallocation.
     QImage m_drawBuffer;
 
+    // A temporary store of magnitude ranges per-column, used when
+    // rendering to the draw buffer. This always has the same length
+    // as the width of the draw buffer, and the x coordinates of the
+    // two containers are equivalent.
+    std::vector<MagnitudeRange> m_magRanges;
+    
     // The image cache is our persistent record of the visible
     // area. It is always the same size as the view (i.e. the paint
     // size reported by the LayerGeometryProvider) and is scrolled and
@@ -205,8 +211,8 @@
     RenderResult render(const LayerGeometryProvider *v,
                         QPainter &paint, QRect rect, bool timeConstrained);
 
-    void renderDirectTranslucent(const LayerGeometryProvider *v,
-                                 QPainter &paint, QRect rect);
+    MagnitudeRange renderDirectTranslucent(const LayerGeometryProvider *v,
+                                           QPainter &paint, QRect rect);
     
     void renderToCachePixelResolution(const LayerGeometryProvider *v, int x0,
                                       int repaintWidth, bool rightToLeft,
--- a/layer/SpectrogramLayer.cpp	Wed Jul 20 13:40:23 2016 +0100
+++ b/layer/SpectrogramLayer.cpp	Fri Jul 22 12:17:55 2016 +0100
@@ -1385,12 +1385,13 @@
     cerr << "SpectrogramLayer::invalidateMagnitudes called" << endl;
 #endif
     m_viewMags.clear();
-    for (vector<MagnitudeRange>::iterator i = m_columnMags.begin();
+/*!!!    for (vector<MagnitudeRange>::iterator i = m_columnMags.begin();
          i != m_columnMags.end(); ++i) {
         *i = MagnitudeRange();
     }
+*/
 }
-
+/*!!!
 bool
 SpectrogramLayer::updateViewMagnitudes(LayerGeometryProvider *v) const
 {
@@ -1434,7 +1435,7 @@
     m_viewMags[v->getId()] = mag;
     return true;
 }
-
+*/
 void
 SpectrogramLayer::setSynchronousPainting(bool synchronous)
 {
@@ -1487,31 +1488,42 @@
 void
 SpectrogramLayer::paintWithRenderer(LayerGeometryProvider *v, QPainter &paint, QRect rect) const
 {
-    static int depth = 0;
+    Colour3DPlotRenderer *renderer = getRenderer(v);
+
+    Colour3DPlotRenderer::RenderResult result;
     
-    Colour3DPlotRenderer *renderer = getRenderer(v);
-
     if (m_synchronous) {
-        (void)renderer->render(v, paint, rect);
-        return;
+
+        result = renderer->render(v, paint, rect);
+
+    } else {
+
+        result = renderer->renderTimeConstrained(v, paint, rect);
+
+        cerr << "mag range in this paint: " << result.range.getMin() << " -> "
+             << result.range.getMax() << endl;
+        
+        //!!!
+
+        QRect uncached = renderer->getLargestUncachedRect(v);
+        if (uncached.width() > 0) {
+            cerr << "updating rect at " << uncached.x() << " width "
+                 << uncached.width() << endl;
+            v->updatePaintRect(uncached);
+        }
     }
 
-    ++depth;
-    cerr << "paint depth " << depth << endl;
+    //!!! at the mo this measures the range of the whole thing, not
+    //!!! just the view - need to reset it when view extents change
+
+    m_viewMags[v->getId()].sample(result.range);
     
-    (void)renderer->renderTimeConstrained(v, paint, rect);
-
-    //!!! + mag range
-
-    QRect uncached = renderer->getLargestUncachedRect();
-    if (uncached.width() > 0) {
-        cerr << "updating rect at " << uncached.x() << " width "
-             << uncached.width() << endl;
-        v->updatePaintRect(uncached);
-    }
-
-    cerr << "exiting paint depth " << depth << endl;
-    --depth;
+    cerr << "mag range in this view: "
+         << m_viewMags[v->getId()].getMin()
+         << " -> "
+         << m_viewMags[v->getId()].getMax()
+         << endl;
+        
 }
 
 void
--- a/layer/SpectrogramLayer.h	Wed Jul 20 13:40:23 2016 +0100
+++ b/layer/SpectrogramLayer.h	Fri Jul 22 12:17:55 2016 +0100
@@ -300,9 +300,9 @@
 
     typedef std::map<int, MagnitudeRange> ViewMagMap; // key is view id
     mutable ViewMagMap m_viewMags;
-    mutable std::vector<MagnitudeRange> m_columnMags;
+//!!!    mutable std::vector<MagnitudeRange> m_columnMags;
     void invalidateMagnitudes();
-    bool updateViewMagnitudes(LayerGeometryProvider *v) const;
+//!!!    bool updateViewMagnitudes(LayerGeometryProvider *v) const;
 
     typedef std::map<int, Colour3DPlotRenderer *> ViewRendererMap; // key is view id
     mutable ViewRendererMap m_renderers;