annotate data/fft/FFTMemoryCache.h @ 335:02d2ad95ea52 spectrogram-cache-rejig

* Get storage advice for each cache in an FFT data server. Allows us to be more confident about the actual memory situation and cut over from memory to disc part way through an FFT calculation if necessary. StorageAdviser is now a bit too optimistic though (it's too keen to allocate large numbers of small blocks in memory).
author Chris Cannam
date Tue, 13 Nov 2007 13:54:10 +0000
parents aa8dbac62024
children 115f60df1e4d
rev   line source
Chris@159 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@159 2
Chris@159 3 /*
Chris@159 4 Sonic Visualiser
Chris@159 5 An audio file viewer and annotation editor.
Chris@159 6 Centre for Digital Music, Queen Mary, University of London.
Chris@159 7 This file copyright 2006 Chris Cannam.
Chris@159 8
Chris@159 9 This program is free software; you can redistribute it and/or
Chris@159 10 modify it under the terms of the GNU General Public License as
Chris@159 11 published by the Free Software Foundation; either version 2 of the
Chris@159 12 License, or (at your option) any later version. See the file
Chris@159 13 COPYING included with this distribution for more information.
Chris@159 14 */
Chris@159 15
Chris@159 16 #ifndef _FFT_MEMORY_CACHE_H_
Chris@159 17 #define _FFT_MEMORY_CACHE_H_
Chris@159 18
Chris@159 19 #include "FFTCache.h"
Chris@159 20
Chris@159 21 #include "base/ResizeableBitset.h"
Chris@159 22
Chris@159 23 /**
Chris@253 24 * In-memory FFT cache. For this we want to cache magnitude with
Chris@159 25 * enough resolution to have gain applied afterwards and determine
Chris@159 26 * whether something is a peak or not, and also cache phase rather
Chris@159 27 * than only phase-adjusted frequency so that we don't have to
Chris@159 28 * recalculate if switching between phase and magnitude displays. At
Chris@159 29 * the same time, we don't want to take up too much memory. It's not
Chris@159 30 * expected to be accurate enough to be used as input for DSP or
Chris@159 31 * resynthesis code.
Chris@159 32 *
Chris@159 33 * This implies probably 16 bits for a normalized magnitude and at
Chris@159 34 * most 16 bits for phase.
Chris@159 35 *
Chris@159 36 * Each column's magnitudes are expected to be stored normalized
Chris@159 37 * to [0,1] with respect to the column, so the normalization
Chris@159 38 * factor should be calculated before all values in a column, and
Chris@159 39 * set appropriately.
Chris@159 40 */
Chris@159 41
Chris@159 42 class FFTMemoryCache : public FFTCache
Chris@159 43 {
Chris@159 44 public:
Chris@264 45 enum StorageType {
Chris@264 46 Compact, // 16 bits normalized polar
Chris@334 47 Rectangular, // floating point real+imag
Chris@334 48 Polar // floating point mag+phase
Chris@264 49 };
Chris@264 50
Chris@264 51 FFTMemoryCache(StorageType storageType); // of size zero, call resize() before using
Chris@159 52 virtual ~FFTMemoryCache();
Chris@159 53
Chris@159 54 virtual size_t getWidth() const { return m_width; }
Chris@159 55 virtual size_t getHeight() const { return m_height; }
Chris@159 56
Chris@159 57 virtual void resize(size_t width, size_t height);
Chris@159 58 virtual void reset(); // zero-fill or 1-fill as appropriate without changing size
Chris@159 59
Chris@159 60 virtual float getMagnitudeAt(size_t x, size_t y) const {
Chris@334 61 if (m_storageType == Rectangular) {
Chris@334 62 return sqrt(m_freal[x][y] * m_freal[x][y] +
Chris@334 63 m_fimag[x][y] * m_fimag[x][y]);
Chris@334 64 } else {
Chris@334 65 return getNormalizedMagnitudeAt(x, y) * m_factor[x];
Chris@334 66 }
Chris@159 67 }
Chris@159 68
Chris@159 69 virtual float getNormalizedMagnitudeAt(size_t x, size_t y) const {
Chris@334 70 if (m_storageType == Rectangular) return getMagnitudeAt(x, y) / m_factor[x];
Chris@334 71 else if (m_storageType == Polar) return m_fmagnitude[x][y];
Chris@264 72 else return float(m_magnitude[x][y]) / 65535.0;
Chris@159 73 }
Chris@159 74
Chris@159 75 virtual float getMaximumMagnitudeAt(size_t x) const {
Chris@159 76 return m_factor[x];
Chris@159 77 }
Chris@159 78
Chris@159 79 virtual float getPhaseAt(size_t x, size_t y) const {
Chris@334 80 if (m_storageType == Rectangular) {
Chris@334 81 return atan2f(m_fimag[x][y], m_freal[x][y]);
Chris@334 82 } else if (m_storageType == Polar) {
Chris@334 83 return m_fphase[x][y];
Chris@334 84 } else {
Chris@334 85 int16_t i = (int16_t)m_phase[x][y];
Chris@334 86 return (float(i) / 32767.0) * M_PI;
Chris@334 87 }
Chris@159 88 }
Chris@159 89
Chris@159 90 virtual void getValuesAt(size_t x, size_t y, float &real, float &imag) const {
Chris@334 91 if (m_storageType == Rectangular) {
Chris@334 92 real = m_freal[x][y];
Chris@334 93 imag = m_fimag[x][y];
Chris@334 94 } else {
Chris@334 95 float mag = getMagnitudeAt(x, y);
Chris@334 96 float phase = getPhaseAt(x, y);
Chris@334 97 real = mag * cosf(phase);
Chris@334 98 imag = mag * sinf(phase);
Chris@334 99 }
Chris@159 100 }
Chris@159 101
Chris@334 102 virtual bool haveSetColumnAt(size_t x) const {
Chris@334 103 return m_colset.get(x);
Chris@334 104 }
Chris@334 105
Chris@334 106 virtual void setColumnAt(size_t x, float *mags, float *phases, float factor);
Chris@334 107
Chris@334 108 virtual void setColumnAt(size_t x, float *reals, float *imags);
Chris@334 109
Chris@334 110 static size_t getCacheSize(size_t width, size_t height, StorageType type);
Chris@334 111
Chris@335 112 virtual Type getType() { return MemoryCache; }
Chris@335 113
Chris@334 114 private:
Chris@334 115 size_t m_width;
Chris@334 116 size_t m_height;
Chris@334 117 uint16_t **m_magnitude;
Chris@334 118 uint16_t **m_phase;
Chris@334 119 float **m_fmagnitude;
Chris@334 120 float **m_fphase;
Chris@334 121 float **m_freal;
Chris@334 122 float **m_fimag;
Chris@334 123 float *m_factor;
Chris@334 124 StorageType m_storageType;
Chris@334 125 ResizeableBitset m_colset;
Chris@334 126
Chris@159 127 virtual void setNormalizationFactor(size_t x, float factor) {
Chris@159 128 if (x < m_width) m_factor[x] = factor;
Chris@159 129 }
Chris@159 130
Chris@159 131 virtual void setMagnitudeAt(size_t x, size_t y, float mag) {
Chris@159 132 // norm factor must already be set
Chris@159 133 setNormalizedMagnitudeAt(x, y, mag / m_factor[x]);
Chris@159 134 }
Chris@159 135
Chris@159 136 virtual void setNormalizedMagnitudeAt(size_t x, size_t y, float norm) {
Chris@159 137 if (x < m_width && y < m_height) {
Chris@264 138 if (m_storageType == Polar) m_fmagnitude[x][y] = norm;
Chris@264 139 else m_magnitude[x][y] = uint16_t(norm * 65535.0);
Chris@159 140 }
Chris@159 141 }
Chris@159 142
Chris@159 143 virtual void setPhaseAt(size_t x, size_t y, float phase) {
Chris@159 144 // phase in range -pi -> pi
Chris@159 145 if (x < m_width && y < m_height) {
Chris@264 146 if (m_storageType == Polar) m_fphase[x][y] = phase;
Chris@264 147 else m_phase[x][y] = uint16_t(int16_t((phase * 32767) / M_PI));
Chris@159 148 }
Chris@159 149 }
Chris@159 150
Chris@159 151 void resize(uint16_t **&, size_t, size_t);
Chris@264 152 void resize(float **&, size_t, size_t);
Chris@159 153 };
Chris@159 154
Chris@159 155
Chris@159 156 #endif
Chris@159 157