changeset 1336:43296804c473 zoom

Toward oversampling rendering
author Chris Cannam
date Mon, 24 Sep 2018 14:40:48 +0100
parents bc44b520405f
children 4f9a3c84be60
files layer/WaveformLayer.cpp layer/WaveformLayer.h
diffstat 2 files changed, 126 insertions(+), 35 deletions(-) [+]
line wrap: on
line diff
--- a/layer/WaveformLayer.cpp	Fri Sep 21 14:46:53 2018 +0100
+++ b/layer/WaveformLayer.cpp	Mon Sep 24 14:40:48 2018 +0100
@@ -31,6 +31,8 @@
 #include <iostream>
 #include <cmath>
 
+#include <bqresample/Resampler.h>
+
 //#define DEBUG_WAVEFORM_PAINT 1
 
 using std::vector;
@@ -48,15 +50,18 @@
     m_scale(LinearScale),
     m_middleLineHeight(0.5),
     m_aggressive(false),
+    m_oversampleRate(8),
+    m_oversampleTail(200),
+    m_oversampler(0),
     m_cache(0),
     m_cacheValid(false)
 {
-    
 }
 
 WaveformLayer::~WaveformLayer()
 {
     delete m_cache;
+    delete m_oversampler;
 }
 
 void
@@ -80,6 +85,12 @@
     m_cacheValid = false;
     if (!m_model || !m_model->isOK()) return;
 
+    delete m_oversampler;
+    breakfastquay::Resampler::Parameters params;
+    params.initialSampleRate = m_model->getSampleRate();
+    m_oversampler = new breakfastquay::Resampler
+        (params, m_model->getChannelCount());
+    
     connectSignals(m_model);
 
     emit modelReplaced();
@@ -410,7 +421,8 @@
                             -5, -3, -2, -1, -0.5, 0 };
 
 bool
-WaveformLayer::getSourceFramesForX(LayerGeometryProvider *v, int x, int modelZoomLevel,
+WaveformLayer::getSourceFramesForX(LayerGeometryProvider *v,
+                                   int x, int modelZoomLevel,
                                    sv_frame_t &f0, sv_frame_t &f1) const
 {
     sv_frame_t viewFrame = v->getFrameForX(x);
@@ -597,32 +609,44 @@
     while ((int)m_effectiveGains.size() <= maxChannel) {
         m_effectiveGains.push_back(m_gain);
     }
+    for (int ch = minChannel; ch <= maxChannel; ++ch) {
+        m_effectiveGains[ch] = getNormalizeGain(v, ch);
+    }
 
-    vector<RangeSummarisableTimeValueModel::RangeBlock> ranges;
+    if (v->getZoomLevel().zone == ZoomLevel::FramesPerPixel) {
+    
+        vector<RangeSummarisableTimeValueModel::RangeBlock> ranges;
 
-    for (int ch = minChannel; ch <= maxChannel; ++ch) {
-        ranges.push_back({});
-        m_model->getSummaries(ch, frame0, frame1 - frame0,
-                              ranges[ch - minChannel], blockSize);
+        for (int ch = minChannel; ch <= maxChannel; ++ch) {
+            ranges.push_back({});
+            m_model->getSummaries(ch, frame0, frame1 - frame0,
+                                  ranges[ch - minChannel], blockSize);
 #ifdef DEBUG_WAVEFORM_PAINT
-        cerr << "channel " << ch << ": " << ranges[ch - minChannel].size() << " ranges from " << frame0 << " to " << frame1 << " at zoom level " << blockSize << endl;
+            cerr << "channel " << ch << ": " << ranges[ch - minChannel].size() << " ranges from " << frame0 << " to " << frame1 << " at zoom level " << blockSize << endl;
 #endif
-    }
+        }
     
-    if (mergingChannels || mixingChannels) {
-        if (minChannel != 0 || maxChannel != 0) {
-            SVCERR << "Internal error: min & max channels should be 0 when merging or mixing all channels" << endl;
-        } else if (m_model->getChannelCount() > 1) {
-            ranges.push_back({});
-            m_model->getSummaries
-                (1, frame0, frame1 - frame0, ranges[1], blockSize);
+        if (mergingChannels || mixingChannels) {
+            if (minChannel != 0 || maxChannel != 0) {
+                SVCERR << "Internal error: min & max channels should be 0 when merging or mixing all channels" << endl;
+            } else if (m_model->getChannelCount() > 1) {
+                ranges.push_back({});
+                m_model->getSummaries
+                    (1, frame0, frame1 - frame0, ranges[1], blockSize);
+            }
+        }
+    
+        for (int ch = minChannel; ch <= maxChannel; ++ch) {
+            paintChannelSummarised(v, paint, rect, ch,
+                                   ranges, blockSize, frame0, frame1);
+        }
+    } else {
+
+        for (int ch = minChannel; ch <= maxChannel; ++ch) {
+            paintChannelOversampled(v, paint, rect, ch, frame0, frame1);
         }
     }
     
-    for (int ch = minChannel; ch <= maxChannel; ++ch) {
-        paintChannel(v, paint, rect, ch, ranges, blockSize, frame0, frame1);
-    }
-
     if (m_middleLineHeight != 0.5) {
         paint->restore();
     }
@@ -639,10 +663,12 @@
 }
 
 void
-WaveformLayer::paintChannel(LayerGeometryProvider *v, QPainter *paint,
-                            QRect rect, int ch,
-                            const vector<RangeSummarisableTimeValueModel::RangeBlock> &ranges,
-                            int blockSize, sv_frame_t frame0, sv_frame_t frame1)
+WaveformLayer::paintChannelSummarised(LayerGeometryProvider *v,
+                                      QPainter *paint,
+                                      QRect rect, int ch,
+                                      const vector<RangeSummarisableTimeValueModel::RangeBlock> &ranges,
+                                      int blockSize,
+                                      sv_frame_t frame0, sv_frame_t frame1)
     const
 {
     int x0 = rect.left();
@@ -675,12 +701,6 @@
     int prevRangeBottom = -1, prevRangeTop = -1;
     QColor prevRangeBottomColour = baseColour, prevRangeTopColour = baseColour;
 
-    m_effectiveGains[ch] = m_gain;
-
-    if (m_autoNormalize) {
-        m_effectiveGains[ch] = getNormalizeGain(v, ch);
-    }
-
     double gain = m_effectiveGains[ch];
 
     int m = (h / channels) / 2;
@@ -935,6 +955,68 @@
 }
 
 void
+WaveformLayer::paintChannelOversampled(LayerGeometryProvider *v,
+                                       QPainter *paint,
+                                       QRect rect,
+                                       int ch,
+                                       sv_frame_t frame0, sv_frame_t frame1)
+    const
+{
+    int x0 = rect.left();
+    int y0 = rect.top();
+
+    int x1 = rect.right();
+    int y1 = rect.bottom();
+
+    int h = v->getPaintHeight();
+
+    int channels = 0, minChannel = 0, maxChannel = 0;
+    bool mergingChannels = false, mixingChannels = false;
+
+    channels = getChannelArrangement(minChannel, maxChannel,
+                                     mergingChannels, mixingChannels);
+    if (channels == 0) return;
+
+    QColor baseColour = getBaseQColor();
+    vector<QColor> greys = getPartialShades(v);
+        
+    QColor midColour = baseColour;
+    if (midColour == Qt::black) {
+        midColour = Qt::gray;
+    } else if (v->hasLightBackground()) {
+        midColour = midColour.light(150);
+    } else {
+        midColour = midColour.light(50);
+    }
+
+    double gain = m_effectiveGains[ch];
+
+    int m = (h / channels) / 2;
+    int my = m + (((ch - minChannel) * h) / channels);
+
+#ifdef DEBUG_WAVEFORM_PAINT        
+    cerr << "ch = " << ch << ", channels = " << channels << ", m = " << m << ", my = " << my << ", h = " << h << endl;
+#endif
+
+    if (my - m > y1 || my + m < y0) return;
+
+    if ((m_scale == dBScale || m_scale == MeterScale) &&
+        m_channelMode != MergeChannels) {
+        m = (h / channels);
+        my = m + (((ch - minChannel) * h) / channels);
+    }
+
+    paint->setPen(greys[1]);
+    paint->drawLine(x0, my, x1, my);
+
+    paintChannelScaleGuides(v, paint, rect, ch);
+  
+    for (sv_frame_t f = frame0; f <= frame1; ++f) {
+
+    }
+}
+
+void
 WaveformLayer::paintChannelScaleGuides(LayerGeometryProvider *v,
                                        QPainter *paint,
                                        QRect rect,
--- a/layer/WaveformLayer.h	Fri Sep 21 14:46:53 2018 +0100
+++ b/layer/WaveformLayer.h	Mon Sep 24 14:40:48 2018 +0100
@@ -26,6 +26,8 @@
 class QPainter;
 class QPixmap;
 
+namespace breakfastquay { class Resampler; }
+
 class WaveformLayer : public SingleColourLayer
 {
     Q_OBJECT
@@ -213,12 +215,15 @@
     int getChannelArrangement(int &min, int &max,
                               bool &merging, bool &mixing) const;
 
-    void paintChannel(LayerGeometryProvider *, QPainter *paint, QRect rect,
-                      int channel,
-                      const std::vector<RangeSummarisableTimeValueModel::RangeBlock> &ranges,
-                      int blockSize, sv_frame_t frame0, sv_frame_t frame1)
-        const;
+    void paintChannelSummarised
+    (LayerGeometryProvider *, QPainter *paint, QRect rect, int channel,
+     const std::vector<RangeSummarisableTimeValueModel::RangeBlock> &ranges,
+     int blockSize, sv_frame_t frame0, sv_frame_t frame1) const;
 
+    void paintChannelOversampled
+    (LayerGeometryProvider *, QPainter *paint, QRect rect, int channel,
+     sv_frame_t frame0, sv_frame_t frame1) const;
+    
     void paintChannelScaleGuides(LayerGeometryProvider *, QPainter *paint,
                                  QRect rect, int channel) const;
     
@@ -242,9 +247,13 @@
     Scale        m_scale;
     double       m_middleLineHeight;
     bool         m_aggressive;
+    int          m_oversampleRate;
+    int          m_oversampleTail;
 
     mutable std::vector<float> m_effectiveGains;
 
+    mutable breakfastquay::Resampler *m_oversampler;
+
     mutable QPixmap *m_cache;
     mutable bool m_cacheValid;
     mutable ZoomLevel m_cacheZoomLevel;