annotate data/fft/FFTMemoryCache.h @ 295:a2dc34ce146a

* Window should be centred on its nominal time. I'm not sure what the reasoning was behind the previous formulations of these two lines.
author Chris Cannam
date Thu, 06 Sep 2007 15:14:47 +0000
parents 260032c26c4f
children aa8dbac62024
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@264 47 Polar, // floating point mag+phase
Chris@264 48 };
Chris@264 49
Chris@264 50 FFTMemoryCache(StorageType storageType); // of size zero, call resize() before using
Chris@159 51 virtual ~FFTMemoryCache();
Chris@159 52
Chris@159 53 virtual size_t getWidth() const { return m_width; }
Chris@159 54 virtual size_t getHeight() const { return m_height; }
Chris@159 55
Chris@159 56 virtual void resize(size_t width, size_t height);
Chris@159 57 virtual void reset(); // zero-fill or 1-fill as appropriate without changing size
Chris@159 58
Chris@159 59 virtual float getMagnitudeAt(size_t x, size_t y) const {
Chris@159 60 return getNormalizedMagnitudeAt(x, y) * m_factor[x];
Chris@159 61 }
Chris@159 62
Chris@159 63 virtual float getNormalizedMagnitudeAt(size_t x, size_t y) const {
Chris@264 64 if (m_storageType == Polar) return m_fmagnitude[x][y];
Chris@264 65 else return float(m_magnitude[x][y]) / 65535.0;
Chris@159 66 }
Chris@159 67
Chris@159 68 virtual float getMaximumMagnitudeAt(size_t x) const {
Chris@159 69 return m_factor[x];
Chris@159 70 }
Chris@159 71
Chris@159 72 virtual float getPhaseAt(size_t x, size_t y) const {
Chris@264 73 if (m_storageType == Polar) return m_fphase[x][y];
Chris@159 74 int16_t i = (int16_t)m_phase[x][y];
Chris@159 75 return (float(i) / 32767.0) * M_PI;
Chris@159 76 }
Chris@159 77
Chris@159 78 virtual void getValuesAt(size_t x, size_t y, float &real, float &imag) const {
Chris@159 79 float mag = getMagnitudeAt(x, y);
Chris@159 80 float phase = getPhaseAt(x, y);
Chris@159 81 real = mag * cosf(phase);
Chris@159 82 imag = mag * sinf(phase);
Chris@159 83 }
Chris@159 84
Chris@159 85 virtual void setNormalizationFactor(size_t x, float factor) {
Chris@159 86 if (x < m_width) m_factor[x] = factor;
Chris@159 87 }
Chris@159 88
Chris@159 89 virtual void setMagnitudeAt(size_t x, size_t y, float mag) {
Chris@159 90 // norm factor must already be set
Chris@159 91 setNormalizedMagnitudeAt(x, y, mag / m_factor[x]);
Chris@159 92 }
Chris@159 93
Chris@159 94 virtual void setNormalizedMagnitudeAt(size_t x, size_t y, float norm) {
Chris@159 95 if (x < m_width && y < m_height) {
Chris@264 96 if (m_storageType == Polar) m_fmagnitude[x][y] = norm;
Chris@264 97 else m_magnitude[x][y] = uint16_t(norm * 65535.0);
Chris@159 98 }
Chris@159 99 }
Chris@159 100
Chris@159 101 virtual void setPhaseAt(size_t x, size_t y, float phase) {
Chris@159 102 // phase in range -pi -> pi
Chris@159 103 if (x < m_width && y < m_height) {
Chris@264 104 if (m_storageType == Polar) m_fphase[x][y] = phase;
Chris@264 105 else m_phase[x][y] = uint16_t(int16_t((phase * 32767) / M_PI));
Chris@159 106 }
Chris@159 107 }
Chris@159 108
Chris@159 109 virtual bool haveSetColumnAt(size_t x) const {
Chris@159 110 return m_colset.get(x);
Chris@159 111 }
Chris@159 112
Chris@159 113 virtual void setColumnAt(size_t x, float *mags, float *phases, float factor) {
Chris@159 114 setNormalizationFactor(x, factor);
Chris@159 115 for (size_t y = 0; y < m_height; ++y) {
Chris@159 116 setMagnitudeAt(x, y, mags[y]);
Chris@159 117 setPhaseAt(x, y, phases[y]);
Chris@159 118 }
Chris@159 119 m_colset.set(x);
Chris@159 120 }
Chris@159 121
Chris@159 122 virtual void setColumnAt(size_t x, float *reals, float *imags);
Chris@159 123
Chris@264 124 static size_t getCacheSize(size_t width, size_t height, StorageType type);
Chris@170 125
Chris@159 126 private:
Chris@159 127 size_t m_width;
Chris@159 128 size_t m_height;
Chris@159 129 uint16_t **m_magnitude;
Chris@159 130 uint16_t **m_phase;
Chris@264 131 float **m_fmagnitude;
Chris@264 132 float **m_fphase;
Chris@159 133 float *m_factor;
Chris@264 134 StorageType m_storageType;
Chris@159 135 ResizeableBitset m_colset;
Chris@159 136
Chris@159 137 void resize(uint16_t **&, size_t, size_t);
Chris@264 138 void resize(float **&, size_t, size_t);
Chris@159 139 };
Chris@159 140
Chris@159 141
Chris@159 142 #endif
Chris@159 143