Mercurial > hg > svcore
comparison data/model/FFTModel.h @ 1090:420fc961c0c4 simple-fft-model
Gut the old code, but don't replace it yet (so nothing will link yet)
author | Chris Cannam |
---|---|
date | Fri, 12 Jun 2015 14:51:46 +0100 |
parents | 9f4505ac9072 |
children | bdebff3265ae |
comparison
equal
deleted
inserted
replaced
1089:655cd4e68e9a | 1090:420fc961c0c4 |
---|---|
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" | |
21 | 23 |
22 #include <set> | 24 #include <set> |
23 #include <map> | 25 #include <map> |
24 | 26 |
25 /** | 27 /** |
26 * An implementation of DenseThreeDimensionalModel that makes FFT data | 28 * An implementation of DenseThreeDimensionalModel that makes FFT data |
27 * derived from a DenseTimeValueModel available as a generic data | 29 * derived from a DenseTimeValueModel available as a generic data |
28 * grid. The FFT data is acquired using FFTDataServer. Note that any | 30 * grid. |
29 * of the accessor functions may throw AllocationFailed if a cache | |
30 * resize fails. | |
31 */ | 31 */ |
32 | |
33 class FFTModel : public DenseThreeDimensionalModel | 32 class FFTModel : public DenseThreeDimensionalModel |
34 { | 33 { |
35 Q_OBJECT | 34 Q_OBJECT |
36 | 35 |
37 public: | 36 public: |
41 * size (which may exceed the window size, for zero-padded FFTs). | 40 * size (which may exceed the window size, for zero-padded FFTs). |
42 * | 41 * |
43 * If the model has multiple channels use only the given channel, | 42 * If the model has multiple channels use only the given channel, |
44 * unless the channel is -1 in which case merge all available | 43 * unless the channel is -1 in which case merge all available |
45 * channels. | 44 * 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 */ | 45 */ |
58 FFTModel(const DenseTimeValueModel *model, | 46 FFTModel(const DenseTimeValueModel *model, |
59 int channel, | 47 int channel, |
60 WindowType windowType, | 48 WindowType windowType, |
61 int windowSize, | 49 int windowSize, |
62 int windowIncrement, | 50 int windowIncrement, |
63 int fftSize, | 51 int fftSize); |
64 bool polar, | |
65 StorageAdviser::Criteria criteria = StorageAdviser::NoCriteria, | |
66 sv_frame_t fillFromFrame = 0); | |
67 ~FFTModel(); | 52 ~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 | 53 |
103 // DenseThreeDimensionalModel and Model methods: | 54 // DenseThreeDimensionalModel and Model methods: |
104 // | 55 // |
105 inline virtual int getWidth() const { | 56 virtual int getWidth() const; |
106 return m_server->getWidth() >> m_xshift; | 57 virtual int getHeight() const; |
107 } | 58 virtual float getValueAt(int x, int y) const { return getMagnitudeAt(x, y); } |
108 inline virtual int getHeight() const { | 59 virtual bool isOK() const { return m_model && m_model->isOK(); } |
109 // If there is no y-shift, the server's height (based on its | 60 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 true if the model was constructed successfully (not | |
122 // necessarily whether an error has occurred since | |
123 // construction, use getError for that) | |
124 return m_server && m_server->getModel(); | |
125 } | |
126 virtual sv_frame_t getStartFrame() const { | |
127 return 0; | |
128 } | |
129 virtual sv_frame_t getEndFrame() const { | 61 virtual sv_frame_t getEndFrame() const { |
130 return sv_frame_t(getWidth()) * getResolution() + getResolution(); | 62 return sv_frame_t(getWidth()) * getResolution() + getResolution(); |
131 } | 63 } |
132 virtual sv_samplerate_t getSampleRate() const; | 64 virtual sv_samplerate_t getSampleRate() const { |
133 virtual int getResolution() const { | 65 return isOK() ? m_model->getSampleRate() : 0; |
134 return m_server->getWindowIncrement() << m_xshift; | |
135 } | 66 } |
136 virtual int getYBinCount() const { | 67 virtual int getResolution() const { return m_windowIncrement; } |
137 return getHeight(); | 68 virtual int getYBinCount() const { return getHeight(); } |
69 virtual float getMinimumLevel() const { return 0.f; } // Can't provide | |
70 virtual float getMaximumLevel() const { return 1.f; } // Can't provide | |
71 virtual Column getColumn(int x) const; // magnitudes | |
72 virtual QString getBinName(int n) const; | |
73 virtual bool shouldUseLogValueScale() const { return true; } | |
74 virtual int getCompletion() const { | |
75 int c = 100; | |
76 if (m_model) (void)m_model->isReady(&c); | |
77 return c; | |
138 } | 78 } |
139 virtual float getMinimumLevel() const { | 79 virtual QString getError() const { return ""; } //!!!??? |
140 return 0.f; // Can't provide | 80 virtual sv_frame_t getFillExtent() const { return getEndFrame(); } |
141 } | |
142 virtual float getMaximumLevel() const { | |
143 return 1.f; // Can't provide | |
144 } | |
145 virtual Column getColumn(int x) const; | |
146 virtual QString getBinName(int n) const; | |
147 | 81 |
148 virtual bool shouldUseLogValueScale() const { | 82 // FFTModel methods: |
149 return true; // Although obviously it's up to the user... | 83 // |
150 } | 84 int getChannel() const { return m_channel; } |
85 WindowType getWindowType() const { return m_windowType; } | |
86 int getWindowSize() const { return m_windowSize; } | |
87 int getWindowIncrement() const { return m_windowIncrement; } | |
88 int getFFTSize() const { return m_fftSize; } | |
89 | |
90 float getMagnitudeAt(int x, int y) const; | |
91 float getNormalizedMagnitudeAt(int x, int y) const; | |
92 float getMaximumMagnitudeAt(int x) const; | |
93 float getPhaseAt(int x, int y) const; | |
94 void getValuesAt(int x, int y, float &real, float &imaginary) const; | |
95 bool isColumnAvailable(int x) const; | |
96 bool getMagnitudesAt(int x, float *values, int minbin = 0, int count = 0) const; | |
97 bool getNormalizedMagnitudesAt(int x, float *values, int minbin = 0, int count = 0) const; | |
98 bool getPhasesAt(int x, float *values, int minbin = 0, int count = 0) const; | |
99 bool getValuesAt(int x, float *reals, float *imaginaries, int minbin = 0, int count = 0) const; | |
151 | 100 |
152 /** | 101 /** |
153 * Calculate an estimated frequency for a stable signal in this | 102 * Calculate an estimated frequency for a stable signal in this |
154 * bin, using phase unwrapping. This will be completely wrong if | 103 * bin, using phase unwrapping. This will be completely wrong if |
155 * the signal is not stable here. | 104 * the signal is not stable here. |
177 * Return locations and estimated stable frequencies of peak bins. | 126 * Return locations and estimated stable frequencies of peak bins. |
178 */ | 127 */ |
179 virtual PeakSet getPeakFrequencies(PeakPickType type, int x, | 128 virtual PeakSet getPeakFrequencies(PeakPickType type, int x, |
180 int ymin = 0, int ymax = 0); | 129 int ymin = 0, int ymax = 0); |
181 | 130 |
182 virtual int getCompletion() const { return m_server->getFillCompletion(); } | |
183 virtual QString getError() const { return m_server->getError(); } | |
184 | |
185 virtual void suspend() { m_server->suspend(); } | |
186 virtual void suspendWrites() { m_server->suspendWrites(); } | |
187 virtual void resume() { m_server->resume(); } | |
188 | |
189 QString getTypeName() const { return tr("FFT"); } | 131 QString getTypeName() const { return tr("FFT"); } |
190 | 132 |
191 public slots: | 133 public slots: |
192 void sourceModelAboutToBeDeleted(); | 134 void sourceModelAboutToBeDeleted(); |
193 | 135 |
194 private: | 136 private: |
195 FFTModel(const FFTModel &); // not implemented | 137 FFTModel(const FFTModel &); // not implemented |
196 FFTModel &operator=(const FFTModel &); // not implemented | 138 FFTModel &operator=(const FFTModel &); // not implemented |
197 | 139 |
198 FFTDataServer *m_server; | 140 const DenseTimeValueModel *m_model; |
199 int m_xshift; | 141 int m_channel; |
200 int m_yshift; | 142 WindowType m_windowType; |
201 | 143 int m_windowSize; |
202 FFTDataServer *getServer(const DenseTimeValueModel *, | 144 int m_windowIncrement; |
203 int, WindowType, int, int, int, | 145 int m_fftSize; |
204 bool, StorageAdviser::Criteria, sv_frame_t); | 146 Window<float> m_windower; |
205 | 147 |
206 int getPeakPickWindowSize(PeakPickType type, sv_samplerate_t sampleRate, | 148 int getPeakPickWindowSize(PeakPickType type, sv_samplerate_t sampleRate, |
207 int bin, float &percentile) const; | 149 int bin, float &percentile) const; |
208 | |
209 int getYRatio() { | |
210 int ys = m_yshift; | |
211 int r = 1; | |
212 while (ys) { --ys; r <<= 1; } | |
213 return r; | |
214 } | |
215 }; | 150 }; |
216 | 151 |
217 #endif | 152 #endif |