changeset 410:9c7ebf2cd956

* Halve space requirements for range (waveform peak) caches
author Chris Cannam
date Fri, 16 May 2008 13:27:07 +0000
parents 6075c90744d4
children 52303ec15cd2
files data/model/RangeSummarisableTimeValueModel.h data/model/WaveFileModel.cpp
diffstat 2 files changed, 80 insertions(+), 28 deletions(-) [+]
line wrap: on
line diff
--- a/data/model/RangeSummarisableTimeValueModel.h	Fri May 09 12:39:02 2008 +0000
+++ b/data/model/RangeSummarisableTimeValueModel.h	Fri May 16 13:27:07 2008 +0000
@@ -35,18 +35,65 @@
 public:
     RangeSummarisableTimeValueModel() { }
 
-    struct Range
+#define RANGE_USE_SHORT 1
+#ifdef RANGE_USE_SHORT
+    class Range
     {
-        float min;
-        float max;
-        float absmean;
+    public:
         Range() : 
-            min(0.f), max(0.f), absmean(0.f) { }
+            m_min(0), m_max(0), m_absmean(0) { }
         Range(const Range &r) : 
-            min(r.min), max(r.max), absmean(r.absmean) { }
-        Range(float min_, float max_, float absmean_) :
-            min(min_), max(max_), absmean(absmean_) { }
+            m_min(r.m_min), m_max(r.m_max), m_absmean(r.m_absmean) { }
+        Range(float min, float max, float absmean)
+        { setMin(min); setMax(max); setAbsmean(absmean); }
+        
+        float min() const { return i2f(m_min); }
+        float max() const { return i2f(m_max); }
+        float absmean() const { return i2f(m_absmean); }
+
+        void setMin(float min) { m_min = f2i(min); }
+        void setMax(float max) { m_max = f2i(max); }
+        void setAbsmean(float absmean) { m_absmean = f2i(absmean); }
+
+    private:
+        static inline int16_t f2i(float f) {
+            if (f > 1.f) f = 1.f;
+            if (f < -1.f) f = -1.f;
+            return int16_t(f * 32767.f);
+        }
+        static inline float i2f(int16_t i) {
+            return float(i) / 32767.f;
+        }
+
+        int16_t m_min;
+        int16_t m_max;
+        int16_t m_absmean;
     };
+#else
+    class Range
+    {
+    public:
+        Range() : 
+            m_min(0.f), m_max(0.f), m_absmean(0.f) { }
+        Range(const Range &r) : 
+            m_min(r.m_min), m_max(r.m_max), m_absmean(r.m_absmean) { }
+        Range(float min, float max, float absmean) :
+            m_min(min), m_max(max), m_absmean(absmean) { }
+
+        float min() const { return m_min; }
+        float max() const { return m_max; }
+        float absmean() const { return m_absmean; }
+
+        void setMin(float min) { m_min = min; }
+        void setMax(float max) { m_max = max; }
+        void setAbsmean(float absmean) { m_absmean = absmean; }
+
+    private:
+        float m_min;
+        float m_max;
+        float m_absmean;
+    };
+#endif
 
     typedef std::vector<Range> RangeBlock;
 
--- a/data/model/WaveFileModel.cpp	Fri May 09 12:39:02 2008 +0000
+++ b/data/model/WaveFileModel.cpp	Fri May 16 13:27:07 2008 +0000
@@ -502,9 +502,9 @@
 	    if (index >= cache.size()) break;
             
             const Range &range = cache[index];
-            if (range.max > max || got == 0) max = range.max;
-            if (range.min < min || got == 0) min = range.min;
-            total += range.absmean;
+            if (range.max() > max || got == 0) max = range.max();
+            if (range.min() < min || got == 0) min = range.min();
+            total += range.absmean();
             
 	    ++i;
             ++got;
@@ -555,25 +555,25 @@
         RangeBlock ranges;
         getSummaries(channel, blockStart, blockEnd - blockStart, ranges, blockSize);
         for (size_t i = 0; i < ranges.size(); ++i) {
-            if (first || ranges[i].min < range.min) range.min = ranges[i].min;
-            if (first || ranges[i].max > range.max) range.max = ranges[i].max;
-            if (first || ranges[i].absmean < range.absmean) range.absmean = ranges[i].absmean;
+            if (first || ranges[i].min() < range.min()) range.setMin(ranges[i].min());
+            if (first || ranges[i].max() > range.max()) range.setMax(ranges[i].max());
+            if (first || ranges[i].absmean() < range.absmean()) range.setAbsmean(ranges[i].absmean());
             first = false;
         }
     }
 
     if (blockStart > start) {
         Range startRange = getSummary(channel, start, blockStart - start);
-        range.min = std::min(range.min, startRange.min);
-        range.max = std::max(range.max, startRange.max);
-        range.absmean = std::min(range.absmean, startRange.absmean);
+        range.setMin(std::min(range.min(), startRange.min()));
+        range.setMax(std::max(range.max(), startRange.max()));
+        range.setAbsmean(std::min(range.absmean(), startRange.absmean()));
     }
 
     if (blockEnd < start + count) {
         Range endRange = getSummary(channel, blockEnd, start + count - blockEnd);
-        range.min = std::min(range.min, endRange.min);
-        range.max = std::max(range.max, endRange.max);
-        range.absmean = std::min(range.absmean, endRange.absmean);
+        range.setMin(std::min(range.min(), endRange.min()));
+        range.setMax(std::max(range.max(), endRange.max()));
+        range.setAbsmean(std::min(range.absmean(), endRange.absmean()));
     }
 
     return range;
@@ -663,6 +663,7 @@
     }
 
     Range *range = new Range[2 * channels];
+    float *means = new float[2 * channels];
     size_t count[2];
     count[0] = count[1] = 0;
 
@@ -698,13 +699,14 @@
                         
                         size_t rangeIndex = ch * 2 + ct;
                         
-                        if (sample > range[rangeIndex].max || count[ct] == 0) {
-                            range[rangeIndex].max = sample;
+                        if (sample > range[rangeIndex].max() || count[ct] == 0) {
+                            range[rangeIndex].setMax(sample);
                         }
-                        if (sample < range[rangeIndex].min || count[ct] == 0) {
-                            range[rangeIndex].min = sample;
+                        if (sample < range[rangeIndex].min() || count[ct] == 0) {
+                            range[rangeIndex].setMin(sample);
                         }
-                        range[rangeIndex].absmean += fabsf(sample);
+
+                        means[rangeIndex] += fabsf(sample);
                     }
                 }
                 
@@ -713,10 +715,11 @@
                 for (size_t ct = 0; ct < 2; ++ct) {
 
                     if (++count[ct] == cacheBlockSize[ct]) {
-
+                        
                         for (size_t ch = 0; ch < size_t(channels); ++ch) {
                             size_t rangeIndex = ch * 2 + ct;
-                            range[rangeIndex].absmean /= count[ct];
+                            means[rangeIndex] /= count[ct];
+                            range[rangeIndex].setAbsmean(means[rangeIndex]);
                             m_model.m_cache[ct].push_back(range[rangeIndex]);
                             range[rangeIndex] = Range();
                         }
@@ -753,7 +756,8 @@
 
                 for (size_t ch = 0; ch < size_t(channels); ++ch) {
                     size_t rangeIndex = ch * 2 + ct;
-                    range[rangeIndex].absmean /= count[ct];
+                    means[rangeIndex] /= count[ct];
+                    range[rangeIndex].setAbsmean(means[rangeIndex]);
                     m_model.m_cache[ct].push_back(range[rangeIndex]);
                     range[rangeIndex] = Range();
                 }
@@ -766,6 +770,7 @@
         }
     }
     
+    delete[] means;
     delete[] range;
 
     m_fillExtent = m_frameCount;