From 7c17d99ea573d0ee6a039b8abde5ddbfed79f54d Mon Sep 17 00:00:00 2001
From: Paul Licameli <paul.licameli@gmail.com>
Date: Mon, 25 May 2015 11:05:31 -0400
Subject: [PATCH] Bug971: spectrogram display

---
 src/TrackArtist.cpp | 74 ++++++++++++++++++---------------------------
 1 file changed, 30 insertions(+), 44 deletions(-)

diff --git a/src/TrackArtist.cpp b/src/TrackArtist.cpp
index 218c2b73a..9ffc5b409 100644
--- a/src/TrackArtist.cpp
+++ b/src/TrackArtist.cpp
@@ -1754,9 +1754,15 @@ void TrackArtist::DrawSpectrum(WaveTrack *track,
    }
 }
 
-static float sumFreqValues(float *freq, int x0, float bin0, float bin1)
+inline
+static float sumFreqValues(
+   const float *freq, int x, int half, float bin0, float bin1,
+   bool autocorrelation, int range, int gain)
 {
+   const int x0 = x * half;
    float value;
+#if 0
+   // Averaging method
    if (int(bin1) == int(bin0)) {
       value = freq[x0+int(bin0)];
    } else {
@@ -1768,9 +1774,28 @@ static float sumFreqValues(float *freq, int x0, float bin0, float bin1)
          value += freq[x0 + int(bin0)];
          bin0 += 1.0;
       }
+      // Do not reference past end of freq array.
+      if (int(bin1) >= half) {
+         bin1 -= 1.0;
+      }
+
       value += freq[x0 + int(bin1)] * (bin1 - int(bin1));
       value /= binwidth;
    }
+#else
+   // Maximum method, and no apportionment of any single bins over multiple pixel rows
+   // See Bug971
+   int bin = floor(0.5 + bin0);
+   const int limitBin = floor(0.5 + bin1);
+   value = freq[x0 + bin];
+   while (++bin < limitBin)
+      value = std::max(value, freq[x0 + bin]);
+#endif
+   if (!autocorrelation) {
+      // Last step converts dB to a 0.0-1.0 range
+      value = (value + range + gain) / (double)range;
+   }
+   value = std::min(1.0f, std::max(0.0f, value));
    return value;
 }
 
@@ -2090,37 +2115,8 @@ void TrackArtist::DrawClipSpectrum(WaveTrack *track,
             float value;
 
             if(!usePxCache) {
-               if (int (bin1) == int (bin0))
-                  value = freq[half * x + int (bin0)];
-               else {
-                  float binwidth= bin1 - bin0;
-                  value = freq[half * x + int (bin0)] * (1.f - bin0 + (int)bin0);
-
-                  bin0 = 1 + int (bin0);
-                  while (bin0 < int (bin1)) {
-                     value += freq[half * x + int (bin0)];
-                     bin0 += 1.0;
-                  }
-
-                  // Do not reference past end of freq array.
-                  if (int(bin1) >= half) {
-                     bin1 -= 1.0;
-                  }
-
-                  value += freq[half * x + int (bin1)] * (bin1 - int (bin1));
-
-                  value /= binwidth;
-               }
-
-               if (!autocorrelation) {
-                  // Last step converts dB to a 0.0-1.0 range
-                  value = (value + range + gain) / (double)range;
-               }
-
-               if (value > 1.0)
-                  value = float(1.0);
-               if (value < 0.0)
-                  value = float(0.0);
+               value = sumFreqValues(freq, x, half, bin0, bin1,
+                  autocorrelation, range, gain);
                clip->mSpecPxCache->values[x * mid.height + yy] = value;
             }
             else
@@ -2138,7 +2134,6 @@ void TrackArtist::DrawClipSpectrum(WaveTrack *track,
       {
          unsigned char rv, gv, bv;
          float value;
-         int x0=x*half;
 
 #ifdef EXPERIMENTAL_FIND_NOTES
          int maximas=0;
@@ -2256,17 +2251,8 @@ void TrackArtist::DrawClipSpectrum(WaveTrack *track,
                      value = minColor;
                } else
 #endif //EXPERIMENTAL_FIND_NOTES
-               {
-                  value=sumFreqValues(freq, x0, bin0, bin1);
-                  if (!autocorrelation) {
-                     // Last step converts dB to a 0.0-1.0 range
-                     value = (value + gain + range) / (double)range;
-                  }
-               }
-               if (value > 1.0)
-                  value = float(1.0);
-               if (value < 0.0)
-                  value = float(0.0);
+                  value=sumFreqValues(freq, x, half, bin0, bin1,
+                     autocorrelation, range, gain);
                clip->mSpecPxCache->values[x * mid.height + yy] = value;
             }
             else