changeset 1143:c53ed1a6fcbd spectrogram-minor-refactor

Fixes to phase display and colour scale for it; tidy up some debug output
author Chris Cannam
date Fri, 05 Aug 2016 14:31:16 +0100
parents 8f4634b82e36
children 6eef0330ef12
files layer/Colour3DPlotRenderer.cpp layer/ColourScale.cpp layer/ScrollableImageCache.cpp layer/ScrollableMagRangeCache.cpp layer/ScrollableMagRangeCache.h layer/SpectrogramLayer.cpp layer/SpectrogramLayer.h
diffstat 7 files changed, 96 insertions(+), 45 deletions(-) [+]
line wrap: on
line diff
--- a/layer/Colour3DPlotRenderer.cpp	Fri Aug 05 14:00:58 2016 +0100
+++ b/layer/Colour3DPlotRenderer.cpp	Fri Aug 05 14:31:16 2016 +0100
@@ -483,7 +483,9 @@
                                                    bool timeConstrained)
 {
     Profiler profiler("Colour3DPlotRenderer::renderToCachePixelResolution");
+#ifdef DEBUG_COLOUR_PLOT_REPAINT
     cerr << "renderToCachePixelResolution" << endl;
+#endif
     
     // Draw to the draw buffer, and then copy from there. The draw
     // buffer is at the same resolution as the target in the cache, so
@@ -523,12 +525,14 @@
         }
     }
 
+#ifdef DEBUG_COLOUR_PLOT_REPAINT
     cerr << "[PIX] zoomLevel = " << zoomLevel
          << ", binResolution " << binResolution 
          << ", binsPerPeak " << binsPerPeak
          << ", peak cache " << m_sources.peaks
          << ", usePeaksCache = " << usePeaksCache
          << endl;
+#endif
     
     for (int y = 0; y < h; ++y) {
         binfory[y] = m_sources.verticalBinLayer->getBinForY(v, h - y - 1);
@@ -578,7 +582,9 @@
                                                  int x0, int repaintWidth)
 {
     Profiler profiler("Colour3DPlotRenderer::renderToCacheBinResolution");
+#ifdef DEBUG_COLOUR_PLOT_REPAINT
     cerr << "renderToCacheBinResolution" << endl;
+#endif
     
     // Draw to the draw buffer, and then scale-copy from there. Draw
     // buffer is at bin resolution, i.e. buffer x == source column
@@ -643,8 +649,10 @@
         binforx[x] = int(leftBoundaryFrame / binResolution) + x;
     }
 
+#ifdef DEBUG_COLOUR_PLOT_REPAINT
     cerr << "[BIN] binResolution " << binResolution 
          << endl;
+#endif
     
     for (int y = 0; y < h; ++y) {
         binfory[y] = m_sources.verticalBinLayer->getBinForY(v, h - y - 1);
@@ -663,9 +671,11 @@
     int scaledLeft = v->getXForFrame(leftBoundaryFrame);
     int scaledRight = v->getXForFrame(rightBoundaryFrame);
 
+#ifdef DEBUG_COLOUR_PLOT_REPAINT
     cerr << "scaling draw buffer from width " << m_drawBuffer.width()
          << " to " << (scaledRight - scaledLeft) << " (nb drawBufferWidth = "
          << drawBufferWidth << ")" << endl;
+#endif
     
     QImage scaled = m_drawBuffer.scaled
         (scaledRight - scaledLeft, h,
@@ -691,8 +701,10 @@
         sourceLeft = 0;
     }
     
+#ifdef DEBUG_COLOUR_PLOT_REPAINT
     cerr << "repaintWidth = " << repaintWidth
          << ", targetWidth = " << targetWidth << endl;
+#endif
     
     if (targetWidth > 0) {
         // we are copying from an image that has already been scaled,
@@ -706,9 +718,6 @@
         // but the mag range vector has not been scaled
         int sourceIx = int((double(i + sourceLeft) / scaled.width())
                            * int(m_magRanges.size()));
-//        int sourceIx = int((double(i) / targetWidth) * sourceWidth);
-        cerr << "mag range target ix = " << i << ", source ix = "
-             << sourceIx << ", of " << m_magRanges.size() << endl;
         if (in_range_for(m_magRanges, sourceIx)) {
             m_magCache.sampleColumn(i, m_magRanges.at(sourceIx));
         }
@@ -765,8 +774,10 @@
 
     int modelWidth = sourceModel->getWidth();
 
+#ifdef DEBUG_COLOUR_PLOT_REPAINT
     cerr << "modelWidth " << modelWidth << ", divisor " << divisor << endl;
-
+#endif
+    
     for (int x = start; x != finish; x += step) {
 
         // x is the on-canvas pixel coord; sx (later) will be the
@@ -912,8 +923,10 @@
     vector<float> preparedColumn;
 
     int modelWidth = fft->getWidth();
+#ifdef DEBUG_COLOUR_PLOT_REPAINT
     cerr << "modelWidth " << modelWidth << endl;
-
+#endif
+    
     double minFreq =
         (double(minbin) * fft->getSampleRate()) / fft->getFFTSize();
     double maxFreq =
--- a/layer/ColourScale.cpp	Fri Aug 05 14:00:58 2016 +0100
+++ b/layer/ColourScale.cpp	Fri Aug 05 14:31:16 2016 +0100
@@ -89,12 +89,11 @@
     if (m_params.scaleType == ColourScaleType::Phase) {
 	double half = (maxPixF - 1.f) / 2.f;
         int pixel = 1 + int((value * half) / M_PI + half);
+//        cerr << "phase = " << value << " pixel = " << pixel << endl;
         return pixel;
     }
     
     value *= m_params.gain;
-
-//    value = pow(value, m_params.multiple);
     
     if (value < m_params.threshold) return 0;
 
--- a/layer/ScrollableImageCache.cpp	Fri Aug 05 14:00:58 2016 +0100
+++ b/layer/ScrollableImageCache.cpp	Fri Aug 05 14:31:16 2016 +0100
@@ -17,7 +17,7 @@
 #include <iostream>
 using namespace std;
 
-#define DEBUG_SCROLLABLE_IMAGE_CACHE 1
+//#define DEBUG_SCROLLABLE_IMAGE_CACHE 1
 
 void
 ScrollableImageCache::scrollTo(const LayerGeometryProvider *v,
--- a/layer/ScrollableMagRangeCache.cpp	Fri Aug 05 14:00:58 2016 +0100
+++ b/layer/ScrollableMagRangeCache.cpp	Fri Aug 05 14:31:16 2016 +0100
@@ -17,7 +17,7 @@
 #include <iostream>
 using namespace std;
 
-#define DEBUG_SCROLLABLE_MAG_RANGE_CACHE 1
+//#define DEBUG_SCROLLABLE_MAG_RANGE_CACHE 1
 
 void
 ScrollableMagRangeCache::scrollTo(const LayerGeometryProvider *v,
@@ -76,11 +76,13 @@
 	m_ranges = newRanges;
     }
 
+#ifdef DEBUG_SCROLLABLE_MAG_RANGE_CACHE
     cerr << "maxes (" << m_ranges.size() << ") now: ";
     for (int i = 0; in_range_for(m_ranges, i); ++i) {
 	cerr << m_ranges[i].getMax() << " ";
     }
     cerr << endl;
+#endif
 }
 
 MagnitudeRange
@@ -109,23 +111,3 @@
     }
 }
 
-//!!! unneeded?
-void
-ScrollableMagRangeCache::sampleColumn(const LayerGeometryProvider *v,
-				      sv_frame_t frame,
-				      const MagnitudeRange &r)
-{
-    int x = (v->getXForFrame(frame) -
-	     v->getXForFrame(m_startFrame));
-
-    if (!in_range_for(m_ranges, x)) {
-	cerr << "WARNING: ScrollableMagRangeCache::sampleColumn: column " << x
-	     << " arising from frame " << frame << " is out of range for cache "
-	     << "of width " << m_ranges.size()
-	     << " (with start frame " << m_startFrame << ")" << endl;
-	throw logic_error("column out of range");
-    } else {
-	sampleColumn(x, r);
-    }
-}
-
--- a/layer/ScrollableMagRangeCache.h	Fri Aug 05 14:00:58 2016 +0100
+++ b/layer/ScrollableMagRangeCache.h	Fri Aug 05 14:31:16 2016 +0100
@@ -130,12 +130,6 @@
      */
     void sampleColumn(int column, const MagnitudeRange &r);
     
-    /**
-     * Update a column in the cache, by frame.
-     */
-    void sampleColumn(const LayerGeometryProvider *v, sv_frame_t frame,
-		      const MagnitudeRange &r);
-    
 private:
     std::vector<MagnitudeRange> m_ranges;
     sv_frame_t m_startFrame;
--- a/layer/SpectrogramLayer.cpp	Fri Aug 05 14:00:58 2016 +0100
+++ b/layer/SpectrogramLayer.cpp	Fri Aug 05 14:31:16 2016 +0100
@@ -51,8 +51,8 @@
 #include <alloca.h>
 #endif
 
-#define DEBUG_SPECTROGRAM 1
-#define DEBUG_SPECTROGRAM_REPAINT 1
+//#define DEBUG_SPECTROGRAM 1
+//#define DEBUG_SPECTROGRAM_REPAINT 1
 
 using namespace std;
 
@@ -1507,9 +1507,11 @@
 
         result = renderer->renderTimeConstrained(v, paint, rect);
 
+#ifdef DEBUG_SPECTROGRAM_REPAINT
         cerr << "rect width from this paint: " << result.rendered.width()
              << ", mag range in this paint: " << result.range.getMin() << " -> "
              << result.range.getMax() << endl;
+#endif
         
         QRect uncached = renderer->getLargestUncachedRect(v);
         if (uncached.width() > 0) {
@@ -1522,15 +1524,19 @@
     if (magRange.isSet()) {
         if (m_viewMags[viewId] != magRange) {
             m_viewMags[viewId] = magRange;
+#ifdef DEBUG_SPECTROGRAM_REPAINT
             cerr << "mag range in this view has changed: "
                  << magRange.getMin() << " -> " << magRange.getMax() << endl;
+#endif
         }
     }
 
     if (!continuingPaint && m_normalizeVisibleArea &&
         m_viewMags[viewId] != m_lastRenderedMags[viewId]) {
+#ifdef DEBUG_SPECTROGRAM_REPAINT
         cerr << "mag range has changed from last rendered range: re-rendering"
              << endl;
+#endif
         delete m_renderers[viewId];
         m_renderers.erase(viewId);
         v->updatePaintRect(v->getPaintRect());
@@ -1571,8 +1577,10 @@
         return;
     }
 
+#ifdef DEBUG_SPECTROGRAM_REPAINT
     cerr << "SpectrogramLayer: illuminateLocalFeatures("
               << localPos.x() << "," << localPos.y() << ")" << endl;
+#endif
 
     double s0, s1;
     double f0, f1;
@@ -1589,8 +1597,10 @@
         int y1 = int(getYForFrequency(v, f1));
         int y0 = int(getYForFrequency(v, f0));
         
+#ifdef DEBUG_SPECTROGRAM_REPAINT
         cerr << "SpectrogramLayer: illuminate "
                   << x0 << "," << y1 << " -> " << x1 << "," << y0 << endl;
+#endif
         
         paint.setPen(v->getForeground());
 
@@ -2093,6 +2103,11 @@
                                      QPainter &paint, QRect rect) const
 {
     // The colour scale
+
+    if (m_colourScale == ColourScaleType::Phase) {
+        paintDetailedScalePhase(v, paint, rect);
+        return;
+    }
     
     int h = rect.height();
     int textHeight = paint.fontMetrics().height();
@@ -2102,7 +2117,6 @@
     int cbw = paint.fontMetrics().width("dB");
 
     int topLines = 2;
-    if (m_colourScale == ColourScaleType::Phase) topLines = 1;
 
     int ch = h - textHeight * (topLines + 1) - 8;
 //	paint.drawRect(4, textHeight + 4, cw - 1, ch + 1);
@@ -2135,12 +2149,8 @@
          << endl;
 #endif
         
-    //!!! & phase etc
-
-    if (m_colourScale != ColourScaleType::Phase) {
-        paint.drawText((cw + 6 - paint.fontMetrics().width("dBFS")) / 2,
-                       2 + textHeight + toff, "dBFS");
-    }
+    paint.drawText((cw + 6 - paint.fontMetrics().width("dBFS")) / 2,
+                   2 + textHeight + toff, "dBFS");
 
 //	paint.drawText((cw + 6 - paint.fontMetrics().width(top)) / 2,
     paint.drawText(3 + cw - cbw - paint.fontMetrics().width(top),
@@ -2189,6 +2199,56 @@
     paint.restore();
 }
 
+void
+SpectrogramLayer::paintDetailedScalePhase(LayerGeometryProvider *v,
+                                          QPainter &paint, QRect rect) const
+{
+    // The colour scale in phase mode
+    
+    int h = rect.height();
+    int textHeight = paint.fontMetrics().height();
+    int toff = -textHeight + paint.fontMetrics().ascent() + 2;
+
+    int cw = getColourScaleWidth(paint);
+
+    // Phase is not measured in dB of course, but this places the
+    // scale at the same position as in the magnitude spectrogram
+    int cbw = paint.fontMetrics().width("dB");
+
+    int topLines = 1;
+
+    int ch = h - textHeight * (topLines + 1) - 8;
+    paint.drawRect(4 + cw - cbw, textHeight * topLines + 4, cbw - 1, ch + 1);
+
+    QString top, bottom, middle;
+    top = QString("%1").arg(QChar(0x3c0)); // pi
+    bottom = "-" + top;
+    middle = "0";
+    
+    double min = -M_PI;
+    double max =  M_PI;
+
+    paint.drawText(3 + cw - cbw - paint.fontMetrics().width(top),
+                   2 + textHeight * topLines + toff + textHeight/2, top);
+
+    paint.drawText(3 + cw - cbw - paint.fontMetrics().width(middle),
+                   2 + textHeight * topLines + ch/2 + toff + textHeight/2, middle);
+
+    paint.drawText(3 + cw - cbw - paint.fontMetrics().width(bottom),
+                   h + toff - 3 - textHeight/2, bottom);
+
+    paint.save();
+    paint.setBrush(Qt::NoBrush);
+
+    for (int i = 0; i < ch; ++i) {
+        double val = min + (((max - min) * i) / (ch - 1));
+        paint.setPen(getRenderer(v)->getColour(val));
+        int y = textHeight * topLines + 4 + ch - i;
+        paint.drawLine(5 + cw - cbw, y, cw + 2, y);
+    }
+    paint.restore();
+}
+
 class SpectrogramRangeMapper : public RangeMapper
 {
 public:
--- a/layer/SpectrogramLayer.h	Fri Aug 05 14:00:58 2016 +0100
+++ b/layer/SpectrogramLayer.h	Fri Aug 05 14:31:16 2016 +0100
@@ -322,7 +322,10 @@
 
     void paintWithRenderer(LayerGeometryProvider *v, QPainter &paint, QRect rect) const;
 
-    void paintDetailedScale(LayerGeometryProvider *v, QPainter &paint, QRect rect) const;
+    void paintDetailedScale(LayerGeometryProvider *v,
+                            QPainter &paint, QRect rect) const;
+    void paintDetailedScalePhase(LayerGeometryProvider *v,
+                                 QPainter &paint, QRect rect) const;
     
     virtual void updateMeasureRectYCoords(LayerGeometryProvider *v,
                                           const MeasureRect &r) const;