diff layer/SpectrogramLayer.cpp @ 1064:77564d4fff43 spectrogram-minor-refactor

Extend column logic to peak frequency display as well, and correct some scopes according to whether values are per source column or per target pixel
author Chris Cannam
date Mon, 20 Jun 2016 12:00:32 +0100
parents a0f234acd6e7
children 85e49aa7fe77
line wrap: on
line diff
--- a/layer/SpectrogramLayer.cpp	Mon Jun 20 11:30:15 2016 +0100
+++ b/layer/SpectrogramLayer.cpp	Mon Jun 20 12:00:32 2016 +0100
@@ -2212,15 +2212,10 @@
     if (!fft) return 0;
 
     FFTModel::PeakSet peakfreqs;
-
+    vector<float> preparedColumn;
+            
     int psx = -1;
 
-#ifdef __GNUC__
-    float values[maxbin - minbin + 1];
-#else
-    float *values = (float *)alloca((maxbin - minbin + 1) * sizeof(float));
-#endif
-
     int minColumns = 4;
     bool haveTimeLimits = (softTimeLimit > 0.0);
     double hardTimeLimit = softTimeLimit * 2.0;
@@ -2252,75 +2247,72 @@
         if (sx0 < 0) continue;
         if (sx1 <= sx0) sx1 = sx0 + 1;
 
+        vector<float> pixelPeakColumn;
+        
         for (int sx = sx0; sx < sx1; ++sx) {
 
-            if (sx < 0 || sx >= int(fft->getWidth())) continue;
-
-            MagnitudeRange mag;
+            if (sx < 0 || sx >= int(fft->getWidth())) {
+                continue;
+            }
 
             if (sx != psx) {
+
+                ColumnOp::Column column;
+
+                column = getColumnFromFFTModel(fft,
+                                               sx,
+                                               minbin,
+                                               maxbin - minbin + 1);
+
+                if (m_colourScale != PhaseColourScale) {
+                    column = ColumnOp::fftScale(column, m_fftSize);
+                }
+
+                recordColumnExtents(column,
+                                    sx,
+                                    overallMag,
+                                    overallMagChanged);
+
+                if (m_colourScale != PhaseColourScale) {
+                    column = ColumnOp::normalize(column, m_normalization);
+                }
+
+                preparedColumn = ColumnOp::applyGain(column, m_gain);
+                
+                psx = sx;
+            }
+
+            if (sx == sx0) {
+                pixelPeakColumn = preparedColumn;
                 peakfreqs = fft->getPeakFrequencies(FFTModel::AllPeaks, sx,
                                                     minbin, maxbin - 1);
-                if (m_colourScale == PhaseColourScale) {
-                    fft->getPhasesAt(sx, values, minbin, maxbin - minbin + 1);
-                    /*!!!
-                } else if (m_normalization == ColumnOp::NormalizeColumns) {
-                    fft->getNormalizedMagnitudesAt(sx, values, minbin, maxbin - minbin + 1);
-                } else if (m_normalization == ColumnOp::NormalizeHybrid) {
-                    float max = fft->getNormalizedMagnitudesAt
-                        (sx, values, minbin, maxbin - minbin + 1);
-                    float scale = log10f(max + 1.f);
-                    for (int i = minbin; i <= maxbin; ++i) {
-                        values[i - minbin] *= scale;
-                        }*/
-                } else {
-                    fft->getMagnitudesAt(sx, values, minbin, maxbin - minbin + 1);
-                }
-                psx = sx;
-            }
-
-            for (FFTModel::PeakSet::const_iterator pi = peakfreqs.begin();
-                 pi != peakfreqs.end(); ++pi) {
-
-                int bin = pi->first;
-                double freq = pi->second;
-
-                if (bin < minbin) continue;
-                if (bin > maxbin) break;
-
-                double value = values[bin - minbin];
-
-                if (m_colourScale != PhaseColourScale) {
-                    if (m_normalization != ColumnOp::NormalizeColumns) {
-                        value /= (m_fftSize/2.0);
-                    }
-                    mag.sample(float(value));
-                    value *= m_gain;
-                }
-
-                double y = v->getYForFrequency
-                    (freq, displayMinFreq, displayMaxFreq, logarithmic);
-
-                int iy = int(y + 0.5);
-                if (iy < 0 || iy >= h) continue;
-
-                m_drawBuffer.setPixel(x, iy, getDisplayValue(v, value));
-            }
-
-            if (mag.isSet()) {
-                if (sx >= int(m_columnMags.size())) {
-#ifdef DEBUG_SPECTROGRAM
-                    cerr << "INTERNAL ERROR: " << sx << " >= "
-                              << m_columnMags.size()
-                              << " at SpectrogramLayer.cpp::paintDrawBuffer"
-                              << endl;
-#endif
-                } else {
-                    m_columnMags[sx].sample(mag);
-                    if (overallMag.sample(mag)) overallMagChanged = true;
+            } else {
+                for (int i = 0; in_range_for(pixelPeakColumn, i); ++i) {
+                    pixelPeakColumn[i] = std::max(pixelPeakColumn[i],
+                                                  preparedColumn[i]);
                 }
             }
         }
+        
+        for (FFTModel::PeakSet::const_iterator pi = peakfreqs.begin();
+             pi != peakfreqs.end(); ++pi) {
+
+            int bin = pi->first;
+            double freq = pi->second;
+
+            if (bin < minbin) continue;
+            if (bin > maxbin) break;
+            
+            double value = pixelPeakColumn[bin - minbin];
+            
+            double y = v->getYForFrequency
+                (freq, displayMinFreq, displayMaxFreq, logarithmic);
+            
+            int iy = int(y + 0.5);
+            if (iy < 0 || iy >= h) continue;
+
+            m_drawBuffer.setPixel(x, iy, getDisplayValue(v, value));
+        }
 
         if (haveTimeLimits) {
             if (columnCount >= minColumns) {
@@ -2491,8 +2483,6 @@
         
         if (binforx[x] < 0) continue;
 
-        float columnMax = 0.f;
-
         int sx0 = binforx[x] / divisor;
         int sx1 = sx0;
         if (x+1 < w) sx1 = binforx[x+1] / divisor;
@@ -2500,19 +2490,22 @@
         if (sx0 < 0) continue;
         if (sx1 <= sx0) sx1 = sx0 + 1;
 
+        vector<float> pixelPeakColumn;
+        
         for (int sx = sx0; sx < sx1; ++sx) {
 
 #ifdef DEBUG_SPECTROGRAM_REPAINT
 //            cerr << "sx = " << sx << endl;
 #endif
 
-            if (sx < 0 || sx >= sourceModel->getWidth()) continue;
-
-            MagnitudeRange mag;
+            if (sx < 0 || sx >= sourceModel->getWidth()) {
+                continue;
+            }
 
             if (sx != psx) {
 
-                // order: get column -> scale -> record extents ->
+                // order:
+                // get column -> scale -> record extents ->
                 // normalise -> peak pick -> apply display gain ->
                 // distribute/interpolate
 
@@ -2530,36 +2523,47 @@
                                                    maxbin - minbin + 1);
                 }
 
-                column = ColumnOp::fftScale(column, m_fftSize);
+                if (m_colourScale != PhaseColourScale) {
+                    column = ColumnOp::fftScale(column, m_fftSize);
+                }
 
                 recordColumnExtents(column,
                                     sx,
                                     overallMag,
                                     overallMagChanged);
 
-                column = ColumnOp::normalize(column, m_normalization);
+                if (m_colourScale != PhaseColourScale) {
+                    column = ColumnOp::normalize(column, m_normalization);
+                }
 
                 if (m_binDisplay == PeakBins) {
                     column = ColumnOp::peakPick(column);
                 }
 
                 preparedColumn =
-                    ColumnOp::distribute
-                    (ColumnOp::applyGain(column, m_gain),
-                     h,
-                     binfory,
-                     minbin,
-                     interpolate);
+                    ColumnOp::distribute(ColumnOp::applyGain(column, m_gain),
+                                         h,
+                                         binfory,
+                                         minbin,
+                                         interpolate);
                 
                 psx = sx;
             }
 
-            //!!! now peak of all preparedColumns for this pixel
+            if (sx == sx0) {
+                pixelPeakColumn = preparedColumn;
+            } else {
+                for (int i = 0; in_range_for(pixelPeakColumn, i); ++i) {
+                    pixelPeakColumn[i] = std::max(pixelPeakColumn[i],
+                                                  preparedColumn[i]);
+                }
+            }
         }
 
         for (int y = 0; y < h; ++y) {
-            unsigned char pixel = getDisplayValue(v, preparedColumn[y]);
-            m_drawBuffer.setPixel(x, h-y-1, pixel);
+            m_drawBuffer.setPixel(x,
+                                  h-y-1,
+                                  getDisplayValue(v, pixelPeakColumn[y]));
         }
 
         if (haveTimeLimits) {