comparison layer/SpectrogramLayer.h @ 85:d31c4f5230d7

* Start factoring out the spectrogram's FFT cache into a separate set of classes that will permit a choice of disk or memory cache strategies
author Chris Cannam
date Tue, 02 May 2006 12:27:41 +0000
parents c683705adcbf
children 93a7efc75fb7
comparison
equal deleted inserted replaced
84:c683705adcbf 85:d31c4f5230d7
26 #include <QMutex> 26 #include <QMutex>
27 #include <QWaitCondition> 27 #include <QWaitCondition>
28 28
29 #include <fftw3.h> 29 #include <fftw3.h>
30 30
31 #include <stdint.h>
32
33 class View; 31 class View;
34 class QPainter; 32 class QPainter;
35 class QImage; 33 class QImage;
36 class QPixmap; 34 class QPixmap;
37 class QTimer; 35 class QTimer;
36 class FFTCacheBase;
38 37
39 /** 38 /**
40 * SpectrogramLayer represents waveform data (obtained from a 39 * SpectrogramLayer represents waveform data (obtained from a
41 * DenseTimeValueModel) in spectrogram form. 40 * DenseTimeValueModel) in spectrogram form.
42 */ 41 */
216 QColor m_crosshairColour; 215 QColor m_crosshairColour;
217 FrequencyScale m_frequencyScale; 216 FrequencyScale m_frequencyScale;
218 BinDisplay m_binDisplay; 217 BinDisplay m_binDisplay;
219 bool m_normalizeColumns; 218 bool m_normalizeColumns;
220 219
221 // We would like to cache magnitude in a way that can have gain
222 // applied afterwards and can determine whether something is a
223 // peak or not, and also cache phase rather than only
224 // phase-adjusted frequency so that we don't have to recalculate
225 // if switching between phase and magnitude displays. At the same
226 // time, we don't want to waste too much memory.
227
228 // This implies probably 16 bits for a normalized magnitude (in
229 // dB?) and at most 16 bits for phase.
230
231 // Each column's magnitudes are expected to be stored normalized
232 // to [0,1] with respect to the column, so the normalization
233 // factor should be calculated before all values in a column, and
234 // set appropriately.
235
236 class Cache {
237 public:
238 Cache(); // of size zero, call resize() before using
239 ~Cache();
240
241 size_t getWidth() const { return m_width; }
242 size_t getHeight() const { return m_height; }
243
244 void resize(size_t width, size_t height);
245 void reset(); // zero-fill or 1-fill as appropriate without changing size
246
247 float getMagnitudeAt(size_t x, size_t y) const {
248 return getNormalizedMagnitudeAt(x, y) * m_factor[x];
249 }
250
251 float getNormalizedMagnitudeAt(size_t x, size_t y) const {
252 return float(m_magnitude[x][y]) / 65535.0;
253 }
254
255 float getPhaseAt(size_t x, size_t y) const {
256 int16_t i = (int16_t)m_phase[x][y];
257 return (float(i) / 32767.0) * M_PI;
258 }
259
260 bool isLocalPeak(size_t x, size_t y) const {
261 if (y > 0 && m_magnitude[x][y] < m_magnitude[x][y-1]) return false;
262 if (y < m_height-1 && m_magnitude[x][y] < m_magnitude[x][y+1]) return false;
263 return true;
264 }
265
266 bool isOverThreshold(size_t x, size_t y, float threshold) const {
267 if (threshold == 0.0) return true;
268 return getMagnitudeAt(x, y) > threshold;
269 }
270
271 void setNormalizationFactor(size_t x, float factor) {
272 if (x < m_width) m_factor[x] = factor;
273 }
274
275 void setMagnitudeAt(size_t x, size_t y, float mag) {
276 // norm factor must already be set
277 setNormalizedMagnitudeAt(x, y, mag / m_factor[x]);
278 }
279
280 void setNormalizedMagnitudeAt(size_t x, size_t y, float norm) {
281 if (x < m_width && y < m_height) {
282 m_magnitude[x][y] = uint16_t(norm * 65535.0);
283 }
284 }
285
286 void setPhaseAt(size_t x, size_t y, float phase) {
287 // phase in range -pi -> pi
288 if (x < m_width && y < m_height) {
289 m_phase[x][y] = uint16_t(int16_t((phase * 32767) / M_PI));
290 }
291 }
292
293 QColor getColour(unsigned char index) const {
294 return m_colours[index];
295 }
296
297 void setColour(unsigned char index, QColor colour) {
298 m_colours[index] = colour;
299 }
300
301 private:
302 size_t m_width;
303 size_t m_height;
304 uint16_t **m_magnitude;
305 uint16_t **m_phase;
306 float *m_factor;
307 QColor m_colours[256];
308
309 void resize(uint16_t **&, size_t, size_t);
310 };
311
312 enum { NO_VALUE = 0 }; // colour index for unused pixels 220 enum { NO_VALUE = 0 }; // colour index for unused pixels
313 221
314 Cache *m_cache; 222 FFTCacheBase *m_cache;
315 bool m_cacheInvalid; 223 bool m_cacheInvalid;
316 224
317 class CacheFillThread : public QThread 225 class CacheFillThread : public QThread
318 { 226 {
319 public: 227 public: