annotate base/FFTCache.h @ 87:7de62a884810

* 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
children 6a1803d578e0
rev   line source
Chris@87 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@87 2
Chris@87 3 /*
Chris@87 4 Sonic Visualiser
Chris@87 5 An audio file viewer and annotation editor.
Chris@87 6 Centre for Digital Music, Queen Mary, University of London.
Chris@87 7 This file copyright 2006 Chris Cannam.
Chris@87 8
Chris@87 9 This program is free software; you can redistribute it and/or
Chris@87 10 modify it under the terms of the GNU General Public License as
Chris@87 11 published by the Free Software Foundation; either version 2 of the
Chris@87 12 License, or (at your option) any later version. See the file
Chris@87 13 COPYING included with this distribution for more information.
Chris@87 14 */
Chris@87 15
Chris@87 16 #ifndef _FFT_CACHE_H_
Chris@87 17 #define _FFT_CACHE_H_
Chris@87 18
Chris@87 19 #include <QColor>
Chris@87 20 #include <stdint.h>
Chris@87 21
Chris@87 22 class FFTCacheBase
Chris@87 23 {
Chris@87 24 public:
Chris@87 25 virtual ~FFTCacheBase() { }
Chris@87 26
Chris@87 27 virtual size_t getWidth() const = 0;
Chris@87 28 virtual size_t getHeight() const = 0;
Chris@87 29
Chris@87 30 virtual void resize(size_t width, size_t height) = 0;
Chris@87 31 virtual void reset() = 0; // zero-fill or 1-fill as appropriate without changing size
Chris@87 32
Chris@87 33 virtual float getMagnitudeAt(size_t x, size_t y) const = 0;
Chris@87 34 virtual float getNormalizedMagnitudeAt(size_t x, size_t y) const = 0;
Chris@87 35 virtual float getPhaseAt(size_t x, size_t y) const = 0;
Chris@87 36
Chris@87 37 virtual bool isLocalPeak(size_t x, size_t y) const = 0;
Chris@87 38 virtual bool isOverThreshold(size_t x, size_t y, float threshold) const = 0;
Chris@87 39
Chris@87 40 virtual void setNormalizationFactor(size_t x, float factor) = 0;
Chris@87 41 virtual void setMagnitudeAt(size_t x, size_t y, float mag) = 0;
Chris@87 42 virtual void setNormalizedMagnitudeAt(size_t x, size_t y, float norm) = 0;
Chris@87 43 virtual void setPhaseAt(size_t x, size_t y, float phase) = 0;
Chris@87 44
Chris@87 45 virtual QColor getColour(unsigned char index) const = 0;
Chris@87 46 virtual void setColour(unsigned char index, QColor colour) = 0;
Chris@87 47
Chris@87 48 protected:
Chris@87 49 FFTCacheBase() { }
Chris@87 50 };
Chris@87 51
Chris@87 52
Chris@87 53 /**
Chris@87 54 * For the in-memory FFT cache, we would like to cache magnitude with
Chris@87 55 * enough resolution to have gain applied afterwards and determine
Chris@87 56 * whether something is a peak or not, and also cache phase rather
Chris@87 57 * than only phase-adjusted frequency so that we don't have to
Chris@87 58 * recalculate if switching between phase and magnitude displays. At
Chris@87 59 * the same time, we don't want to take up too much memory. It's not
Chris@87 60 * expected to be accurate enough to be used as input for DSP or
Chris@87 61 * resynthesis code.
Chris@87 62 *
Chris@87 63 * This implies probably 16 bits for a normalized magnitude and at
Chris@87 64 * most 16 bits for phase.
Chris@87 65 *
Chris@87 66 * Each column's magnitudes are expected to be stored normalized
Chris@87 67 * to [0,1] with respect to the column, so the normalization
Chris@87 68 * factor should be calculated before all values in a column, and
Chris@87 69 * set appropriately.
Chris@87 70 */
Chris@87 71
Chris@87 72 class FFTMemoryCache : public FFTCacheBase
Chris@87 73 {
Chris@87 74 public:
Chris@87 75 FFTMemoryCache(); // of size zero, call resize() before using
Chris@87 76 virtual ~FFTMemoryCache();
Chris@87 77
Chris@87 78 virtual size_t getWidth() const { return m_width; }
Chris@87 79 virtual size_t getHeight() const { return m_height; }
Chris@87 80
Chris@87 81 virtual void resize(size_t width, size_t height);
Chris@87 82 virtual void reset(); // zero-fill or 1-fill as appropriate without changing size
Chris@87 83
Chris@87 84 virtual float getMagnitudeAt(size_t x, size_t y) const {
Chris@87 85 return getNormalizedMagnitudeAt(x, y) * m_factor[x];
Chris@87 86 }
Chris@87 87
Chris@87 88 virtual float getNormalizedMagnitudeAt(size_t x, size_t y) const {
Chris@87 89 return float(m_magnitude[x][y]) / 65535.0;
Chris@87 90 }
Chris@87 91
Chris@87 92 virtual float getPhaseAt(size_t x, size_t y) const {
Chris@87 93 int16_t i = (int16_t)m_phase[x][y];
Chris@87 94 return (float(i) / 32767.0) * M_PI;
Chris@87 95 }
Chris@87 96
Chris@87 97 virtual bool isLocalPeak(size_t x, size_t y) const {
Chris@87 98 if (y > 0 && m_magnitude[x][y] < m_magnitude[x][y-1]) return false;
Chris@87 99 if (y < m_height-1 && m_magnitude[x][y] < m_magnitude[x][y+1]) return false;
Chris@87 100 return true;
Chris@87 101 }
Chris@87 102
Chris@87 103 virtual bool isOverThreshold(size_t x, size_t y, float threshold) const {
Chris@87 104 if (threshold == 0.0) return true;
Chris@87 105 return getMagnitudeAt(x, y) > threshold;
Chris@87 106 }
Chris@87 107
Chris@87 108 virtual void setNormalizationFactor(size_t x, float factor) {
Chris@87 109 if (x < m_width) m_factor[x] = factor;
Chris@87 110 }
Chris@87 111
Chris@87 112 virtual void setMagnitudeAt(size_t x, size_t y, float mag) {
Chris@87 113 // norm factor must already be set
Chris@87 114 setNormalizedMagnitudeAt(x, y, mag / m_factor[x]);
Chris@87 115 }
Chris@87 116
Chris@87 117 virtual void setNormalizedMagnitudeAt(size_t x, size_t y, float norm) {
Chris@87 118 if (x < m_width && y < m_height) {
Chris@87 119 m_magnitude[x][y] = uint16_t(norm * 65535.0);
Chris@87 120 }
Chris@87 121 }
Chris@87 122
Chris@87 123 virtual void setPhaseAt(size_t x, size_t y, float phase) {
Chris@87 124 // phase in range -pi -> pi
Chris@87 125 if (x < m_width && y < m_height) {
Chris@87 126 m_phase[x][y] = uint16_t(int16_t((phase * 32767) / M_PI));
Chris@87 127 }
Chris@87 128 }
Chris@87 129
Chris@87 130 virtual QColor getColour(unsigned char index) const {
Chris@87 131 return m_colours[index];
Chris@87 132 }
Chris@87 133
Chris@87 134 virtual void setColour(unsigned char index, QColor colour) {
Chris@87 135 m_colours[index] = colour;
Chris@87 136 }
Chris@87 137
Chris@87 138 private:
Chris@87 139 size_t m_width;
Chris@87 140 size_t m_height;
Chris@87 141 uint16_t **m_magnitude;
Chris@87 142 uint16_t **m_phase;
Chris@87 143 float *m_factor;
Chris@87 144 QColor m_colours[256];
Chris@87 145
Chris@87 146 void resize(uint16_t **&, size_t, size_t);
Chris@87 147 };
Chris@87 148
Chris@87 149 #endif