diff --git a/src/plotview.cpp b/src/plotview.cpp index d1c6bea..3a38603 100644 --- a/src/plotview.cpp +++ b/src/plotview.cpp @@ -439,9 +439,12 @@ void PlotView::setFFTAndZoom(int size, int zoom) spectrogramPlot->setFFTSize(size); // Set new zoom level - zoomLevel = zoom; - if (spectrogramPlot != nullptr) - spectrogramPlot->setZoomLevel(zoom); + zoomLevel = std::max(1,zoom); + nfftSkip = std::max(1,-1*zoom); + if (spectrogramPlot != nullptr) { + spectrogramPlot->setZoomLevel(zoomLevel); + spectrogramPlot->setSkip(nfftSkip); + } // Update horizontal (time) scrollbar horizontalScrollBar()->setSingleStep(10); @@ -568,7 +571,7 @@ void PlotView::resizeEvent(QResizeEvent * event) size_t PlotView::samplesPerColumn() { - return fftSize / zoomLevel; + return fftSize * nfftSkip / zoomLevel; } void PlotView::scrollContentsBy(int dx, int dy) diff --git a/src/plotview.h b/src/plotview.h index 326d547..06e94e2 100644 --- a/src/plotview.h +++ b/src/plotview.h @@ -77,6 +77,7 @@ public slots: int fftSize = 1024; int zoomLevel = 1; + int nfftSkip = 1; int powerMin; int powerMax; bool cursorsEnabled; diff --git a/src/spectrogramcontrols.cpp b/src/spectrogramcontrols.cpp index 0e0f9aa..29878e0 100644 --- a/src/spectrogramcontrols.cpp +++ b/src/spectrogramcontrols.cpp @@ -52,7 +52,7 @@ SpectrogramControls::SpectrogramControls(const QString & title, QWidget * parent layout->addRow(new QLabel(tr("FFT size:")), fftSizeSlider); zoomLevelSlider = new QSlider(Qt::Horizontal, widget); - zoomLevelSlider->setRange(0, 10); + zoomLevelSlider->setRange(-6, 10); zoomLevelSlider->setPageStep(1); layout->addRow(new QLabel(tr("Zoom:")), zoomLevelSlider); @@ -151,7 +151,13 @@ void SpectrogramControls::setDefaults() void SpectrogramControls::fftOrZoomChanged(void) { int fftSize = pow(2, fftSizeSlider->value()); - int zoomLevel = std::min(fftSize, (int)pow(2, zoomLevelSlider->value())); + int zoomLevel = zoomLevelSlider->value(); + if (zoomLevel >= 0) + // zooming in by power-of-two steps + zoomLevel = std::min(fftSize, (int)pow(2, zoomLevel)); + else + // zooming out (skipping FFTs) by power-of-two steps + zoomLevel = -1*std::min(fftSize, (int)pow(2, -1*zoomLevel)); emit fftOrZoomChanged(fftSize, zoomLevel); } diff --git a/src/spectrogramplot.cpp b/src/spectrogramplot.cpp index 3ab57ec..7fd420e 100644 --- a/src/spectrogramplot.cpp +++ b/src/spectrogramplot.cpp @@ -35,6 +35,7 @@ SpectrogramPlot::SpectrogramPlot(std::shared_ptr s QPixmap* SpectrogramPlot::getPixmapTile(size_t tile) { - QPixmap *obj = pixmapCache.object(TileCacheKey(fftSize, zoomLevel, tile)); + QPixmap *obj = pixmapCache.object(TileCacheKey(fftSize, zoomLevel, nfftSkip, tile)); if (obj != 0) return obj; @@ -261,13 +262,13 @@ QPixmap* SpectrogramPlot::getPixmapTile(size_t tile) } } obj->convertFromImage(image); - pixmapCache.insert(TileCacheKey(fftSize, zoomLevel, tile), obj); + pixmapCache.insert(TileCacheKey(fftSize, zoomLevel, nfftSkip, tile), obj); return obj; } float* SpectrogramPlot::getFFTTile(size_t tile) { - std::array* obj = fftCache.object(TileCacheKey(fftSize, zoomLevel, tile)); + std::array* obj = fftCache.object(TileCacheKey(fftSize, zoomLevel, nfftSkip, tile)); if (obj != nullptr) return obj->data(); @@ -279,7 +280,7 @@ float* SpectrogramPlot::getFFTTile(size_t tile) sample += getStride(); ptr += fftSize; } - fftCache.insert(TileCacheKey(fftSize, zoomLevel, tile), destStorage); + fftCache.insert(TileCacheKey(fftSize, zoomLevel, nfftSkip, tile), destStorage); return destStorage->data(); } @@ -316,7 +317,7 @@ void SpectrogramPlot::getLine(float *dest, size_t sample) int SpectrogramPlot::getStride() { - return fftSize / zoomLevel; + return fftSize * nfftSkip / zoomLevel; } float SpectrogramPlot::getTunerPhaseInc() @@ -397,6 +398,11 @@ void SpectrogramPlot::setZoomLevel(int zoom) zoomLevel = zoom; } +void SpectrogramPlot::setSkip(int skip) +{ + nfftSkip = skip; +} + void SpectrogramPlot::setSampleRate(double rate) { sampleRate = rate; diff --git a/src/spectrogramplot.h b/src/spectrogramplot.h index 2e52cb4..9125211 100644 --- a/src/spectrogramplot.h +++ b/src/spectrogramplot.h @@ -60,6 +60,7 @@ public slots: void setPowerMax(int power); void setPowerMin(int power); void setZoomLevel(int zoom); + void setSkip(int skip); void tunerMoved(); private: @@ -76,6 +77,7 @@ public slots: int fftSize; int zoomLevel; + int nfftSkip; float powerMax; float powerMin; double sampleRate; @@ -100,20 +102,23 @@ class TileCacheKey { public: - TileCacheKey(int fftSize, int zoomLevel, size_t sample) { + TileCacheKey(int fftSize, int zoomLevel, int nfftSkip, size_t sample) { this->fftSize = fftSize; this->zoomLevel = zoomLevel; + this->nfftSkip = nfftSkip; this->sample = sample; } bool operator==(const TileCacheKey &k2) const { return (this->fftSize == k2.fftSize) && (this->zoomLevel == k2.zoomLevel) && + (this->nfftSkip == k2.nfftSkip) && (this->sample == k2.sample); } int fftSize; int zoomLevel; + int nfftSkip; size_t sample; };