changeset 1529:c1c45c5146bb zoom

Merge from default branch
author Chris Cannam
date Tue, 18 Sep 2018 15:06:58 +0100
parents 710e6250a401 (diff) a7485c1bdba5 (current diff)
children bf32b26d1dad
files base/BaseTypes.h base/ZoomConstraint.h data/model/PowerOfSqrtTwoZoomConstraint.cpp data/model/PowerOfSqrtTwoZoomConstraint.h data/model/PowerOfTwoZoomConstraint.cpp data/model/PowerOfTwoZoomConstraint.h
diffstat 7 files changed, 139 insertions(+), 20 deletions(-) [+]
line wrap: on
line diff
--- a/base/BaseTypes.h	Tue Sep 18 15:04:46 2018 +0100
+++ b/base/BaseTypes.h	Tue Sep 18 15:06:58 2018 +0100
@@ -55,5 +55,56 @@
 typedef std::vector<std::complex<float>,
                     breakfastquay::StlAllocator<std::complex<float>>> complexvec_t;
 
+/** Display zoom level. Can be an integer number of samples per pixel,
+ *  or an integer number of pixels per sample.
+ */
+struct ZoomLevel {
+
+    enum Zone {
+        FramesPerPixel, // zoomed out (as in classic SV)
+        PixelsPerFrame  // zoomed in beyond 1-1 (interpolating the waveform)
+    };
+    Zone zone;
+    int level;
+
+    bool operator<(const ZoomLevel &other) const {
+        if (zone == FramesPerPixel) {
+            if (other.zone == zone) {
+                return level < other.level;
+            } else {
+                return false;
+            }
+        } else {
+            if (other.zone == zone) {
+                return level > other.level;
+            } else {
+                return false;
+            }
+        }
+    }
+
+    ZoomLevel incremented() const {
+        if (zone == FramesPerPixel) {
+            return { zone, level + 1 };
+        } else if (level == 1) {
+            return { FramesPerPixel, 2 };
+        } else if (level == 2) {
+            return { FramesPerPixel, 1 };
+        } else {
+            return { zone, level - 1 };
+        }
+    }
+
+    ZoomLevel decremented() const {
+        if (zone == PixelsPerFrame) {
+            return { zone, level + 1 };
+        } else if (level == 1) {
+            return { PixelsPerFrame, 2 };
+        } else {
+            return { zone, level - 1 };
+        }
+    }
+};
+
 #endif
 
--- a/base/ZoomConstraint.h	Tue Sep 18 15:04:46 2018 +0100
+++ b/base/ZoomConstraint.h	Tue Sep 18 15:06:58 2018 +0100
@@ -18,6 +18,8 @@
 
 #include <stdlib.h>
 
+#include "BaseTypes.h"
+
 /**
  * ZoomConstraint is a simple interface that describes a limitation on
  * the available zoom sizes for a view, for example based on cache
@@ -39,30 +41,42 @@
     };
 
     /**
-     * Given the "ideal" block size (frames per pixel) for a given
-     * zoom level, return the nearest viable block size for this
-     * constraint.
+     * Given an "ideal" zoom level (frames per pixel or pixels per
+     * frame) for a given zoom level, return the nearest viable block
+     * size for this constraint.
      *
      * For example, if a block size of 1523 frames per pixel is
      * requested but the underlying model only supports value
      * summaries at powers-of-two block sizes, return 1024 or 2048
      * depending on the rounding direction supplied.
      */
-    virtual int getNearestBlockSize(int requestedBlockSize,
-                                    RoundingDirection = RoundNearest)
+    virtual ZoomLevel getNearestZoomLevel(ZoomLevel requestedZoomLevel,
+                                          RoundingDirection = RoundNearest)
         const
     {
-        if (requestedBlockSize > getMaxZoomLevel()) return getMaxZoomLevel();
-        else return requestedBlockSize;
+        if (getMaxZoomLevel() < requestedZoomLevel) return getMaxZoomLevel();
+	else return requestedZoomLevel;
     }
 
     /**
+     * Return the minimum zoom level within range for this constraint.
+     * Individual views will probably want to limit this, for example
+     * in order to ensure that at least one or two samples fit in the
+     * current window size, or in order to save on interpolation cost.
+     */
+    virtual ZoomLevel getMinZoomLevel() const {
+        return { ZoomLevel::PixelsPerFrame, 16384 };
+    }
+    
+    /**
      * Return the maximum zoom level within range for this constraint.
      * This is quite large -- individual views will probably want to
      * limit how far a user might reasonably zoom out based on other
      * factors such as the duration of the file.
      */
-    virtual int getMaxZoomLevel() const { return 4194304; } // 2^22, arbitrarily
+    virtual ZoomLevel getMaxZoomLevel() const {
+        return { ZoomLevel::FramesPerPixel, 4194304 }; // 2^22, arbitrarily
+    }
 };
 
 #endif
--- a/data/model/PowerOfSqrtTwoZoomConstraint.cpp	Tue Sep 18 15:04:46 2018 +0100
+++ b/data/model/PowerOfSqrtTwoZoomConstraint.cpp	Tue Sep 18 15:06:58 2018 +0100
@@ -21,13 +21,30 @@
 #include "base/Debug.h"
 
 
-int
-PowerOfSqrtTwoZoomConstraint::getNearestBlockSize(int blockSize,
+ZoomLevel
+PowerOfSqrtTwoZoomConstraint::getNearestZoomLevel(ZoomLevel requested,
                                                   RoundingDirection dir) const
 {
     int type, power;
-    int rv = getNearestBlockSize(blockSize, type, power, dir);
-    return rv;
+    int blockSize;
+
+    if (requested.zone == ZoomLevel::FramesPerPixel) {
+        blockSize = getNearestBlockSize(requested.level, type, power, dir);
+        return { requested.zone, blockSize };
+    } else {
+        RoundingDirection opposite = dir;
+        if (dir == RoundUp) opposite = RoundDown;
+        else if (dir == RoundDown) opposite = RoundUp;
+        blockSize = getNearestBlockSize(requested.level, type, power, opposite);
+        if (blockSize > getMinZoomLevel().level) {
+            blockSize = getMinZoomLevel().level;
+        }
+        if (blockSize == 1) {
+            return { ZoomLevel::FramesPerPixel, 1 };
+        } else {
+            return { requested.zone, blockSize };
+        }
+    }
 }
 
 int
@@ -113,6 +130,9 @@
         prevBase = base;
     }
 
-    if (result > getMaxZoomLevel()) result = getMaxZoomLevel();
+    if (result > getMaxZoomLevel().level) {
+        result = getMaxZoomLevel().level;
+    }
+
     return result;
 }   
--- a/data/model/PowerOfSqrtTwoZoomConstraint.h	Tue Sep 18 15:04:46 2018 +0100
+++ b/data/model/PowerOfSqrtTwoZoomConstraint.h	Tue Sep 18 15:06:58 2018 +0100
@@ -21,17 +21,17 @@
 class PowerOfSqrtTwoZoomConstraint : virtual public ZoomConstraint
 {
 public:
-    virtual int getNearestBlockSize(int requestedBlockSize,
-                                    RoundingDirection dir = RoundNearest)
-        const;
-    
+    virtual ZoomLevel getNearestZoomLevel(ZoomLevel requested,
+                                          RoundingDirection dir = RoundNearest)
+	const override;
+	
+    virtual int getMinCachePower() const { return 6; }
+
     virtual int getNearestBlockSize(int requestedBlockSize,
                                     int &type,
                                     int &power,
                                     RoundingDirection dir = RoundNearest)
         const;
-        
-    virtual int getMinCachePower() const { return 6; }
 };
 
 #endif
--- a/data/model/PowerOfTwoZoomConstraint.cpp	Tue Sep 18 15:04:46 2018 +0100
+++ b/data/model/PowerOfTwoZoomConstraint.cpp	Tue Sep 18 15:06:58 2018 +0100
@@ -15,6 +15,34 @@
 
 #include "PowerOfTwoZoomConstraint.h"
 
+ZoomLevel
+PowerOfTwoZoomConstraint::getNearestZoomLevel(ZoomLevel requested,
+                                              RoundingDirection dir) const
+{
+    int blockSize;
+
+    if (requested.zone == ZoomLevel::FramesPerPixel) {
+        blockSize = getNearestBlockSize(requested.level, dir);
+        if (blockSize > getMaxZoomLevel().level) {
+            blockSize = getMaxZoomLevel().level;
+        }
+        return { requested.zone, blockSize };
+    } else {
+        RoundingDirection opposite = dir;
+        if (dir == RoundUp) opposite = RoundDown;
+        else if (dir == RoundDown) opposite = RoundUp;
+        blockSize = getNearestBlockSize(requested.level, opposite);
+        if (blockSize > getMinZoomLevel().level) {
+            blockSize = getMinZoomLevel().level;
+        }
+        if (blockSize == 1) {
+            return { ZoomLevel::FramesPerPixel, 1 };
+        } else {
+            return { requested.zone, blockSize };
+        }
+    }
+}
+
 int
 PowerOfTwoZoomConstraint::getNearestBlockSize(int req,
                                               RoundingDirection dir) const
--- a/data/model/PowerOfTwoZoomConstraint.h	Tue Sep 18 15:04:46 2018 +0100
+++ b/data/model/PowerOfTwoZoomConstraint.h	Tue Sep 18 15:06:58 2018 +0100
@@ -21,7 +21,12 @@
 class PowerOfTwoZoomConstraint : virtual public ZoomConstraint
 {
 public:
-    virtual int getNearestBlockSize(int requestedBlockSize,
+    virtual ZoomLevel getNearestZoomLevel(ZoomLevel requested,
+                                          RoundingDirection dir = RoundNearest)
+	const override;
+
+protected:
+    virtual int getNearestBlockSize(int requested,
                                     RoundingDirection dir = RoundNearest)
         const;
 };
--- a/data/model/ReadOnlyWaveFileModel.cpp	Tue Sep 18 15:04:46 2018 +0100
+++ b/data/model/ReadOnlyWaveFileModel.cpp	Tue Sep 18 15:06:58 2018 +0100
@@ -341,6 +341,7 @@
     int power = m_zoomConstraint.getMinCachePower();
     int roundedBlockSize = m_zoomConstraint.getNearestBlockSize
         (desired, cacheType, power, ZoomConstraint::RoundDown);
+
     if (cacheType != 0 && cacheType != 1) {
         // We will be reading directly from file, so can satisfy any
         // blocksize requirement