changeset 719:67e6d518ac27

Bodge in Matthias's suggested normalise-to-log as an option in spectrogram and colour 3d plot layers (not wired into gui)
author Chris Cannam
date Tue, 28 Jan 2014 17:37:42 +0000
parents b81f21f2c4c3
children 5f9c0147d1d6 5d3a6ecdf2db
files layer/Colour3DPlotLayer.cpp layer/Colour3DPlotLayer.h layer/SpectrogramLayer.cpp layer/SpectrogramLayer.h
diffstat 4 files changed, 96 insertions(+), 50 deletions(-) [+]
line wrap: on
line diff
--- a/layer/Colour3DPlotLayer.cpp	Wed Dec 04 14:00:27 2013 +0000
+++ b/layer/Colour3DPlotLayer.cpp	Tue Jan 28 17:37:42 2014 +0000
@@ -51,6 +51,7 @@
     m_binScale(LinearBinScale),
     m_normalizeColumns(false),
     m_normalizeVisibleArea(false),
+    m_normalizeHybrid(false),
     m_invertVertical(false),
     m_opaque(false),
     m_smooth(false),
@@ -430,6 +431,21 @@
 }
 
 void
+Colour3DPlotLayer::setNormalizeHybrid(bool n)
+{
+    if (m_normalizeHybrid == n) return;
+    m_normalizeHybrid = n;
+    cacheInvalid();
+    emit layerParametersChanged();
+}
+
+bool
+Colour3DPlotLayer::getNormalizeHybrid() const
+{
+    return m_normalizeHybrid;
+}
+
+void
 Colour3DPlotLayer::setNormalizeVisibleArea(bool n)
 {
     if (m_normalizeVisibleArea == n) return;
@@ -882,7 +898,7 @@
 {
     DenseThreeDimensionalModel::Column values = m_model->getColumn(col);
     while (values.size() < m_model->getHeight()) values.push_back(0.f);
-    if (!m_normalizeColumns) return values;
+    if (!m_normalizeColumns && !m_normalizeHybrid) return values;
 
     float colMax = 0.f, colMin = 0.f;
     float min = 0.f, max = 0.f;
@@ -905,6 +921,13 @@
         if (value != newvalue) values[y] = newvalue;
     }
 
+    if (m_normalizeHybrid && (colMax > 0.0)) {
+        float logmax = log10(colMax);
+        for (size_t y = 0; y < values.size(); ++y) {
+            values[y] *= logmax;
+        }
+    }
+
     return values;
 }
     
--- a/layer/Colour3DPlotLayer.h	Wed Dec 04 14:00:27 2013 +0000
+++ b/layer/Colour3DPlotLayer.h	Tue Jan 28 17:37:42 2014 +0000
@@ -116,12 +116,26 @@
     void setBinScale(BinScale);
     BinScale getBinScale() const;
 
+    /**
+     * Normalize each column to its maximum value, independent of its
+     * neighbours.
+     */
     void setNormalizeColumns(bool n);
     bool getNormalizeColumns() const;
 
+    /**
+     * Normalize each value against the maximum in the visible region.
+     */
     void setNormalizeVisibleArea(bool n);
     bool getNormalizeVisibleArea() const;
 
+    /**
+     * Normalize each column to its maximum value, and then scale by
+     * the log of the (absolute) maximum value.
+     */
+    void setNormalizeHybrid(bool n);
+    bool getNormalizeHybrid() const;
+
     void setInvertVertical(bool i);
     bool getInvertVertical() const;
 
@@ -168,6 +182,7 @@
     BinScale    m_binScale;
     bool        m_normalizeColumns;
     bool        m_normalizeVisibleArea;
+    bool        m_normalizeHybrid;
     bool        m_invertVertical;
     bool        m_opaque;
     bool        m_smooth;
--- a/layer/SpectrogramLayer.cpp	Wed Dec 04 14:00:27 2013 +0000
+++ b/layer/SpectrogramLayer.cpp	Tue Jan 28 17:37:42 2014 +0000
@@ -75,6 +75,7 @@
     m_binDisplay(AllBins),
     m_normalizeColumns(false),
     m_normalizeVisibleArea(false),
+    m_normalizeHybrid(false),
     m_lastEmittedZoomStep(-1),
     m_synchronous(false),
     m_haveDetailedScale(false),
@@ -951,6 +952,24 @@
 }
 
 void
+SpectrogramLayer::setNormalizeHybrid(bool n)
+{
+    if (m_normalizeHybrid == n) return;
+
+    invalidateImageCaches();
+    invalidateMagnitudes();
+    m_normalizeHybrid = n;
+
+    emit layerParametersChanged();
+}
+
+bool
+SpectrogramLayer::getNormalizeHybrid() const
+{
+    return m_normalizeHybrid;
+}
+
+void
 SpectrogramLayer::setNormalizeVisibleArea(bool n)
 {
     SVDEBUG << "SpectrogramLayer::setNormalizeVisibleArea(" << n
@@ -1245,50 +1264,6 @@
 }
 
 float
-SpectrogramLayer::getInputForDisplayValue(unsigned char uc) const
-{
-    //!!! unused
-
-    int value = uc;
-    float input;
-
-    //!!! incorrect for normalizing visible area (and also out of date)
-    
-    switch (m_colourScale) {
-	
-    default:
-    case LinearColourScale:
-	input = float(value - 1) / 255.0 / (m_normalizeColumns ? 1 : 50);
-	break;
-    
-    case MeterColourScale:
-	input = AudioLevel::preview_to_multiplier(value - 1, 255)
-	    / (m_normalizeColumns ? 1.0 : 50.0);
-	break;
-
-    case dBSquaredColourScale:
-	input = float(value - 1) / 255.0;
-	input = (input * 80.0) - 80.0;
-	input = powf(10.0, input) / 20.0;
-	value = int(input);
-	break;
-
-    case dBColourScale:
-	input = float(value - 1) / 255.0;
-	input = (input * 80.0) - 80.0;
-	input = powf(10.0, input) / 20.0;
-	value = int(input);
-	break;
-
-    case PhaseColourScale:
-	input = float(value - 128) * M_PI / 127.0;
-	break;
-    }
-
-    return input;
-}
-
-float
 SpectrogramLayer::getEffectiveMinFrequency() const
 {
     int sr = m_model->getSampleRate();
@@ -2556,6 +2531,14 @@
                     fft->getPhasesAt(sx, values, minbin, maxbin - minbin + 1);
                 } else if (m_normalizeColumns) {
                     fft->getNormalizedMagnitudesAt(sx, values, minbin, maxbin - minbin + 1);
+                } else if (m_normalizeHybrid) {
+                    fft->getNormalizedMagnitudesAt(sx, values, minbin, maxbin - minbin + 1);
+                    float max = fft->getMaximumMagnitudeAt(sx);
+                    if (max > 0.f) {
+                        for (int i = minbin; i <= maxbin; ++i) {
+                            values[i - minbin] *= log10(max);
+                        }
+                    }
                 } else {
                     fft->getMagnitudesAt(sx, values, minbin, maxbin - minbin + 1);
                 }
@@ -2574,7 +2557,7 @@
                 float value = values[bin - minbin];
 
                 if (m_colourScale != PhaseColourScale) {
-                    if (!m_normalizeColumns) {
+                    if (!m_normalizeColumns && !m_normalizeHybrid) {
                         value /= (m_fftSize/2.f);
                     }
                     mag.sample(value);
@@ -2715,6 +2698,14 @@
                         fft->getPhasesAt(sx, autoarray, minbin, maxbin - minbin + 1);
                     } else if (m_normalizeColumns) {
                         fft->getNormalizedMagnitudesAt(sx, autoarray, minbin, maxbin - minbin + 1);
+                    } else if (m_normalizeHybrid) {
+                        fft->getNormalizedMagnitudesAt(sx, autoarray, minbin, maxbin - minbin + 1);
+                        float max = fft->getMaximumMagnitudeAt(sx);
+                        for (int i = minbin; i <= maxbin; ++i) {
+                            if (max > 0.f) {
+                                autoarray[i - minbin] *= log10(max);
+                            }
+                        }
                     } else {
                         fft->getMagnitudesAt(sx, autoarray, minbin, maxbin - minbin + 1);
                     }
@@ -2723,7 +2714,7 @@
                     SVDEBUG << "Retrieving column " << sx << " from peaks cache" << endl;
 #endif
                     c = sourceModel->getColumn(sx);
-                    if (m_normalizeColumns) {
+                    if (m_normalizeColumns || m_normalizeHybrid) {
                         for (int y = 0; y < h; ++y) {
                             if (c[y] > columnMax) columnMax = c[y];
                         }
@@ -2823,9 +2814,12 @@
             float peak = peaks[y];
             
             if (m_colourScale != PhaseColourScale &&
-                m_normalizeColumns && 
+                (m_normalizeColumns || m_normalizeHybrid) && 
                 columnMax > 0.f) {
                 peak /= columnMax;
+                if (m_normalizeHybrid) {
+                    peak *= log10(columnMax);
+                }
             }
             
             unsigned char peakpix = getDisplayValue(v, peak);
--- a/layer/SpectrogramLayer.h	Wed Dec 04 14:00:27 2013 +0000
+++ b/layer/SpectrogramLayer.h	Tue Jan 28 17:37:42 2014 +0000
@@ -170,13 +170,27 @@
      */
     void setBinDisplay(BinDisplay);
     BinDisplay getBinDisplay() const;
-
+ 
+    /**
+     * Normalize each column to its maximum value, independent of its
+     * neighbours.
+     */
     void setNormalizeColumns(bool n);
     bool getNormalizeColumns() const;
 
+    /**
+     * Normalize each value against the maximum in the visible region.
+     */
     void setNormalizeVisibleArea(bool n);
     bool getNormalizeVisibleArea() const;
 
+    /**
+     * Normalize each column to its maximum value, and then scale by
+     * the log of the (absolute) maximum value.
+     */
+    void setNormalizeHybrid(bool n);
+    bool getNormalizeHybrid() const;
+    
     void setColourMap(int map);
     int getColourMap() const;
 
@@ -260,6 +274,7 @@
     BinDisplay          m_binDisplay;
     bool                m_normalizeColumns;
     bool                m_normalizeVisibleArea;
+    bool                m_normalizeHybrid;
     int                 m_lastEmittedZoomStep;
     bool                m_synchronous;
 
@@ -320,7 +335,6 @@
     void rotatePalette(int distance);
 
     unsigned char getDisplayValue(View *v, float input) const;
-    float getInputForDisplayValue(unsigned char uc) const;
 
     int getColourScaleWidth(QPainter &) const;