1 /*
2  *  Copyright (C) 2015, Mike Walters <mike@flomp.net>
3  *
4  *  This file is part of inspectrum.
5  *
6  *  This program is free software: you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation, either version 3 of the License, or
9  *  (at your option) any later version.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #pragma once
21 
22 #include <QCache>
23 #include <QWidget>
24 #include "fft.h"
25 #include "inputsource.h"
26 #include "plot.h"
27 #include "tuner.h"
28 #include "tunertransform.h"
29 
30 #include <memory>
31 #include <array>
32 #include <math.h>
33 
34 class TileCacheKey;
35 
36 class SpectrogramPlot : public Plot
37 {
38     Q_OBJECT
39 
40 public:
41     SpectrogramPlot(std::shared_ptr<SampleSource<std::complex<float>>> src);
42     void invalidateEvent() override;
43     std::shared_ptr<AbstractSampleSource> output() override;
44     void paintFront(QPainter &painter, QRect &rect, range_t<size_t> sampleRange) override;
45     void paintMid(QPainter &painter, QRect &rect, range_t<size_t> sampleRange) override;
46     bool mouseEvent(QEvent::Type type, QMouseEvent event) override;
input()47     std::shared_ptr<SampleSource<std::complex<float>>> input() { return inputSource; };
48     void setSampleRate(size_t sampleRate);
49     bool tunerEnabled();
50     void enableScales(bool enabled);
51 
52 public slots:
53     void setFFTSize(int size);
54     void setPowerMax(int power);
55     void setPowerMin(int power);
56     void setZoomLevel(int zoom);
57     void tunerMoved();
58 
59 private:
60     const int linesPerGraduation = 50;
61     static const int tileSize = 65536; // This must be a multiple of the maximum FFT size
62 
63     std::shared_ptr<SampleSource<std::complex<float>>> inputSource;
64     std::unique_ptr<FFT> fft;
65     std::unique_ptr<float[]> window;
66     QCache<TileCacheKey, QPixmap> pixmapCache;
67     QCache<TileCacheKey, std::array<float, tileSize>> fftCache;
68     uint colormap[256];
69 
70     int fftSize;
71     int zoomLevel;
72     float powerMax;
73     float powerMin;
74     size_t sampleRate;
75     bool frequencyScaleEnabled;
76 
77     Tuner tuner;
78     std::shared_ptr<TunerTransform> tunerTransform;
79 
80     QPixmap* getPixmapTile(size_t tile);
81     float* getFFTTile(size_t tile);
82     void getLine(float *dest, size_t sample);
83     int getStride();
84     float getTunerPhaseInc();
85     std::vector<float> getTunerTaps();
86     int linesPerTile();
87     void paintFrequencyScale(QPainter &painter, QRect &rect);
88 };
89 
90 class TileCacheKey
91 {
92 
93 public:
TileCacheKey(int fftSize,int zoomLevel,size_t sample)94     TileCacheKey(int fftSize, int zoomLevel, size_t sample) {
95         this->fftSize = fftSize;
96         this->zoomLevel = zoomLevel;
97         this->sample = sample;
98     }
99 
100     bool operator==(const TileCacheKey &k2) const {
101         return (this->fftSize == k2.fftSize) &&
102                (this->zoomLevel == k2.zoomLevel) &&
103                (this->sample == k2.sample);
104     }
105 
106     int fftSize;
107     int zoomLevel;
108     size_t sample;
109 };
110