comparison data/model/FFTModel.h @ 1126:39019ce29178 tony-2.0-integration

Merge through to branch for Tony 2.0
author Chris Cannam
date Thu, 20 Aug 2015 14:54:21 +0100
parents 5cbf71022679
children e94719f941ba 546d4e417346
comparison
equal deleted inserted replaced
1119:e22bfe8ca248 1126:39019ce29178
11 published by the Free Software Foundation; either version 2 of the 11 published by the Free Software Foundation; either version 2 of the
12 License, or (at your option) any later version. See the file 12 License, or (at your option) any later version. See the file
13 COPYING included with this distribution for more information. 13 COPYING included with this distribution for more information.
14 */ 14 */
15 15
16 #ifndef _FFT_MODEL_H_ 16 #ifndef FFT_MODEL_H
17 #define _FFT_MODEL_H_ 17 #define FFT_MODEL_H
18 18
19 #include "data/fft/FFTDataServer.h"
20 #include "DenseThreeDimensionalModel.h" 19 #include "DenseThreeDimensionalModel.h"
20 #include "DenseTimeValueModel.h"
21
22 #include "base/Window.h"
23
24 #include "data/fft/FFTapi.h"
21 25
22 #include <set> 26 #include <set>
23 #include <map> 27 #include <vector>
28 #include <complex>
29 #include <deque>
24 30
25 /** 31 /**
26 * An implementation of DenseThreeDimensionalModel that makes FFT data 32 * An implementation of DenseThreeDimensionalModel that makes FFT data
27 * derived from a DenseTimeValueModel available as a generic data 33 * derived from a DenseTimeValueModel available as a generic data
28 * grid. The FFT data is acquired using FFTDataServer. Note that any 34 * grid.
29 * of the accessor functions may throw AllocationFailed if a cache
30 * resize fails.
31 */ 35 */
32
33 class FFTModel : public DenseThreeDimensionalModel 36 class FFTModel : public DenseThreeDimensionalModel
34 { 37 {
35 Q_OBJECT 38 Q_OBJECT
39
40 //!!! threading requirements?
41 //!!! doubles? since we're not caching much
36 42
37 public: 43 public:
38 /** 44 /**
39 * Construct an FFT model derived from the given 45 * Construct an FFT model derived from the given
40 * DenseTimeValueModel, with the given window parameters and FFT 46 * DenseTimeValueModel, with the given window parameters and FFT
41 * size (which may exceed the window size, for zero-padded FFTs). 47 * size (which may exceed the window size, for zero-padded FFTs).
42 * 48 *
43 * If the model has multiple channels use only the given channel, 49 * If the model has multiple channels use only the given channel,
44 * unless the channel is -1 in which case merge all available 50 * unless the channel is -1 in which case merge all available
45 * channels. 51 * channels.
46 *
47 * If polar is true, the data will normally be retrieved from the
48 * FFT model in magnitude/phase form; otherwise it will normally
49 * be retrieved in "cartesian" real/imaginary form. The results
50 * should be the same either way, but a "polar" model addressed in
51 * "cartesian" form or vice versa may suffer a performance
52 * penalty.
53 *
54 * The fillFromColumn argument gives a hint that the FFT data
55 * server should aim to start calculating FFT data at that column
56 * number if possible, as that is likely to be requested first.
57 */ 52 */
58 FFTModel(const DenseTimeValueModel *model, 53 FFTModel(const DenseTimeValueModel *model,
59 int channel, 54 int channel,
60 WindowType windowType, 55 WindowType windowType,
61 int windowSize, 56 int windowSize,
62 int windowIncrement, 57 int windowIncrement,
63 int fftSize, 58 int fftSize);
64 bool polar,
65 StorageAdviser::Criteria criteria = StorageAdviser::NoCriteria,
66 sv_frame_t fillFromFrame = 0);
67 ~FFTModel(); 59 ~FFTModel();
68
69 inline float getMagnitudeAt(int x, int y) {
70 return m_server->getMagnitudeAt(x << m_xshift, y << m_yshift);
71 }
72 inline float getNormalizedMagnitudeAt(int x, int y) {
73 return m_server->getNormalizedMagnitudeAt(x << m_xshift, y << m_yshift);
74 }
75 inline float getMaximumMagnitudeAt(int x) {
76 return m_server->getMaximumMagnitudeAt(x << m_xshift);
77 }
78 inline float getPhaseAt(int x, int y) {
79 return m_server->getPhaseAt(x << m_xshift, y << m_yshift);
80 }
81 inline void getValuesAt(int x, int y, float &real, float &imaginary) {
82 m_server->getValuesAt(x << m_xshift, y << m_yshift, real, imaginary);
83 }
84 inline bool isColumnAvailable(int x) const {
85 return m_server->isColumnReady(x << m_xshift);
86 }
87
88 inline bool getMagnitudesAt(int x, float *values, int minbin = 0, int count = 0) {
89 return m_server->getMagnitudesAt(x << m_xshift, values, minbin << m_yshift, count, getYRatio());
90 }
91 inline bool getNormalizedMagnitudesAt(int x, float *values, int minbin = 0, int count = 0) {
92 return m_server->getNormalizedMagnitudesAt(x << m_xshift, values, minbin << m_yshift, count, getYRatio());
93 }
94 inline bool getPhasesAt(int x, float *values, int minbin = 0, int count = 0) {
95 return m_server->getPhasesAt(x << m_xshift, values, minbin << m_yshift, count, getYRatio());
96 }
97 inline bool getValuesAt(int x, float *reals, float *imaginaries, int minbin = 0, int count = 0) {
98 return m_server->getValuesAt(x << m_xshift, reals, imaginaries, minbin << m_yshift, count, getYRatio());
99 }
100
101 inline sv_frame_t getFillExtent() const { return m_server->getFillExtent(); }
102 60
103 // DenseThreeDimensionalModel and Model methods: 61 // DenseThreeDimensionalModel and Model methods:
104 // 62 //
105 inline virtual int getWidth() const { 63 virtual int getWidth() const;
106 return m_server->getWidth() >> m_xshift; 64 virtual int getHeight() const;
107 } 65 virtual float getValueAt(int x, int y) const { return getMagnitudeAt(x, y); }
108 inline virtual int getHeight() const { 66 virtual bool isOK() const { return m_model && m_model->isOK(); }
109 // If there is no y-shift, the server's height (based on its 67 virtual sv_frame_t getStartFrame() const { return 0; }
110 // fftsize/2 + 1) is correct. If there is a shift, then the
111 // server is using a larger fft size than we want, so we shift
112 // it right as many times as necessary, but then we need to
113 // re-add the "+1" part (because ((fftsize*2)/2 + 1) / 2 !=
114 // fftsize/2 + 1).
115 return (m_server->getHeight() >> m_yshift) + (m_yshift > 0 ? 1 : 0);
116 }
117 virtual float getValueAt(int x, int y) const {
118 return const_cast<FFTModel *>(this)->getMagnitudeAt(x, y);
119 }
120 virtual bool isOK() const {
121 return m_server && m_server->getModel();
122 }
123 virtual sv_frame_t getStartFrame() const {
124 return 0;
125 }
126 virtual sv_frame_t getEndFrame() const { 68 virtual sv_frame_t getEndFrame() const {
127 return sv_frame_t(getWidth()) * getResolution() + getResolution(); 69 return sv_frame_t(getWidth()) * getResolution() + getResolution();
128 } 70 }
129 virtual sv_samplerate_t getSampleRate() const; 71 virtual sv_samplerate_t getSampleRate() const {
130 virtual int getResolution() const { 72 return isOK() ? m_model->getSampleRate() : 0;
131 return m_server->getWindowIncrement() << m_xshift;
132 } 73 }
133 virtual int getYBinCount() const { 74 virtual int getResolution() const { return m_windowIncrement; }
134 return getHeight(); 75 virtual int getYBinCount() const { return getHeight(); }
76 virtual float getMinimumLevel() const { return 0.f; } // Can't provide
77 virtual float getMaximumLevel() const { return 1.f; } // Can't provide
78 virtual Column getColumn(int x) const; // magnitudes
79 virtual QString getBinName(int n) const;
80 virtual bool shouldUseLogValueScale() const { return true; }
81 virtual int getCompletion() const {
82 int c = 100;
83 if (m_model) {
84 if (m_model->isReady(&c)) return 100;
85 }
86 return c;
135 } 87 }
136 virtual float getMinimumLevel() const { 88 virtual QString getError() const { return ""; } //!!!???
137 return 0.f; // Can't provide 89 virtual sv_frame_t getFillExtent() const { return getEndFrame(); }
138 }
139 virtual float getMaximumLevel() const {
140 return 1.f; // Can't provide
141 }
142 virtual Column getColumn(int x) const;
143 virtual QString getBinName(int n) const;
144 90
145 virtual bool shouldUseLogValueScale() const { 91 // FFTModel methods:
146 return true; // Although obviously it's up to the user... 92 //
147 } 93 int getChannel() const { return m_channel; }
94 WindowType getWindowType() const { return m_windowType; }
95 int getWindowSize() const { return m_windowSize; }
96 int getWindowIncrement() const { return m_windowIncrement; }
97 int getFFTSize() const { return m_fftSize; }
98
99 float getMagnitudeAt(int x, int y) const;
100 float getMaximumMagnitudeAt(int x) const;
101 float getPhaseAt(int x, int y) const;
102 void getValuesAt(int x, int y, float &real, float &imaginary) const;
103 bool isColumnAvailable(int x) const;
104 bool getMagnitudesAt(int x, float *values, int minbin = 0, int count = 0) const;
105 bool getNormalizedMagnitudesAt(int x, float *values, int minbin = 0, int count = 0) const;
106 bool getPhasesAt(int x, float *values, int minbin = 0, int count = 0) const;
107 bool getValuesAt(int x, float *reals, float *imaginaries, int minbin = 0, int count = 0) const;
148 108
149 /** 109 /**
150 * Calculate an estimated frequency for a stable signal in this 110 * Calculate an estimated frequency for a stable signal in this
151 * bin, using phase unwrapping. This will be completely wrong if 111 * bin, using phase unwrapping. This will be completely wrong if
152 * the signal is not stable here. 112 * the signal is not stable here.
174 * Return locations and estimated stable frequencies of peak bins. 134 * Return locations and estimated stable frequencies of peak bins.
175 */ 135 */
176 virtual PeakSet getPeakFrequencies(PeakPickType type, int x, 136 virtual PeakSet getPeakFrequencies(PeakPickType type, int x,
177 int ymin = 0, int ymax = 0); 137 int ymin = 0, int ymax = 0);
178 138
179 virtual int getCompletion() const { return m_server->getFillCompletion(); }
180 virtual QString getError() const { return m_server->getError(); }
181
182 virtual void suspend() { m_server->suspend(); }
183 virtual void suspendWrites() { m_server->suspendWrites(); }
184 virtual void resume() { m_server->resume(); }
185
186 QString getTypeName() const { return tr("FFT"); } 139 QString getTypeName() const { return tr("FFT"); }
187 140
188 public slots: 141 public slots:
189 void sourceModelAboutToBeDeleted(); 142 void sourceModelAboutToBeDeleted();
190 143
191 private: 144 private:
192 FFTModel(const FFTModel &); // not implemented 145 FFTModel(const FFTModel &); // not implemented
193 FFTModel &operator=(const FFTModel &); // not implemented 146 FFTModel &operator=(const FFTModel &); // not implemented
194 147
195 FFTDataServer *m_server; 148 const DenseTimeValueModel *m_model;
196 int m_xshift; 149 int m_channel;
197 int m_yshift; 150 WindowType m_windowType;
198 151 int m_windowSize;
199 FFTDataServer *getServer(const DenseTimeValueModel *, 152 int m_windowIncrement;
200 int, WindowType, int, int, int, 153 int m_fftSize;
201 bool, StorageAdviser::Criteria, sv_frame_t); 154 Window<float> m_windower;
202 155 FFTForward m_fft;
156
203 int getPeakPickWindowSize(PeakPickType type, sv_samplerate_t sampleRate, 157 int getPeakPickWindowSize(PeakPickType type, sv_samplerate_t sampleRate,
204 int bin, float &percentile) const; 158 int bin, float &percentile) const;
205 159
206 int getYRatio() { 160 std::pair<sv_frame_t, sv_frame_t> getSourceSampleRange(int column) const {
207 int ys = m_yshift; 161 sv_frame_t startFrame = m_windowIncrement * sv_frame_t(column);
208 int r = 1; 162 sv_frame_t endFrame = startFrame + m_windowSize;
209 while (ys) { --ys; r <<= 1; } 163 // Cols are centred on the audio sample (e.g. col 0 is centred at sample 0)
210 return r; 164 startFrame -= m_windowSize / 2;
165 endFrame -= m_windowSize / 2;
166 return { startFrame, endFrame };
211 } 167 }
168
169 std::vector<std::complex<float> > getFFTColumn(int column) const;
170 std::vector<float> getSourceSamples(int column) const;
171 std::vector<float> getSourceData(std::pair<sv_frame_t, sv_frame_t>) const;
172 std::vector<float> getSourceDataUncached(std::pair<sv_frame_t, sv_frame_t>) const;
173
174 struct SavedSourceData {
175 std::pair<sv_frame_t, sv_frame_t> range;
176 std::vector<float> data;
177 };
178 mutable SavedSourceData m_savedData;
179
180 struct SavedColumn {
181 int n;
182 std::vector<std::complex<float> > col;
183 };
184 mutable std::deque<SavedColumn> m_cached;
185 size_t m_cacheSize;
212 }; 186 };
213 187
214 #endif 188 #endif