annotate data/fft/FFTMemoryCache.h @ 263:71dfc6ab3b54

* Threaded mp3/ogg file reading. Not activated yet, as it doesn't work in context (SV needs to know the duration of its main model at the outset)
author Chris Cannam
date Thu, 24 May 2007 16:20:22 +0000
parents b36895bda652
children 260032c26c4f
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@159 45 FFTMemoryCache(); // of size zero, call resize() before using
Chris@159 46 virtual ~FFTMemoryCache();
Chris@159 47
Chris@159 48 virtual size_t getWidth() const { return m_width; }
Chris@159 49 virtual size_t getHeight() const { return m_height; }
Chris@159 50
Chris@159 51 virtual void resize(size_t width, size_t height);
Chris@159 52 virtual void reset(); // zero-fill or 1-fill as appropriate without changing size
Chris@159 53
Chris@159 54 virtual float getMagnitudeAt(size_t x, size_t y) const {
Chris@159 55 return getNormalizedMagnitudeAt(x, y) * m_factor[x];
Chris@159 56 }
Chris@159 57
Chris@159 58 virtual float getNormalizedMagnitudeAt(size_t x, size_t y) const {
Chris@159 59 return float(m_magnitude[x][y]) / 65535.0;
Chris@159 60 }
Chris@159 61
Chris@159 62 virtual float getMaximumMagnitudeAt(size_t x) const {
Chris@159 63 return m_factor[x];
Chris@159 64 }
Chris@159 65
Chris@159 66 virtual float getPhaseAt(size_t x, size_t y) const {
Chris@159 67 int16_t i = (int16_t)m_phase[x][y];
Chris@159 68 return (float(i) / 32767.0) * M_PI;
Chris@159 69 }
Chris@159 70
Chris@159 71 virtual void getValuesAt(size_t x, size_t y, float &real, float &imag) const {
Chris@159 72 float mag = getMagnitudeAt(x, y);
Chris@159 73 float phase = getPhaseAt(x, y);
Chris@159 74 real = mag * cosf(phase);
Chris@159 75 imag = mag * sinf(phase);
Chris@159 76 }
Chris@159 77
Chris@159 78 virtual void setNormalizationFactor(size_t x, float factor) {
Chris@159 79 if (x < m_width) m_factor[x] = factor;
Chris@159 80 }
Chris@159 81
Chris@159 82 virtual void setMagnitudeAt(size_t x, size_t y, float mag) {
Chris@159 83 // norm factor must already be set
Chris@159 84 setNormalizedMagnitudeAt(x, y, mag / m_factor[x]);
Chris@159 85 }
Chris@159 86
Chris@159 87 virtual void setNormalizedMagnitudeAt(size_t x, size_t y, float norm) {
Chris@159 88 if (x < m_width && y < m_height) {
Chris@159 89 m_magnitude[x][y] = uint16_t(norm * 65535.0);
Chris@159 90 }
Chris@159 91 }
Chris@159 92
Chris@159 93 virtual void setPhaseAt(size_t x, size_t y, float phase) {
Chris@159 94 // phase in range -pi -> pi
Chris@159 95 if (x < m_width && y < m_height) {
Chris@159 96 m_phase[x][y] = uint16_t(int16_t((phase * 32767) / M_PI));
Chris@159 97 }
Chris@159 98 }
Chris@159 99
Chris@159 100 virtual bool haveSetColumnAt(size_t x) const {
Chris@159 101 return m_colset.get(x);
Chris@159 102 }
Chris@159 103
Chris@159 104 virtual void setColumnAt(size_t x, float *mags, float *phases, float factor) {
Chris@159 105 setNormalizationFactor(x, factor);
Chris@159 106 for (size_t y = 0; y < m_height; ++y) {
Chris@159 107 setMagnitudeAt(x, y, mags[y]);
Chris@159 108 setPhaseAt(x, y, phases[y]);
Chris@159 109 }
Chris@159 110 m_colset.set(x);
Chris@159 111 }
Chris@159 112
Chris@159 113 virtual void setColumnAt(size_t x, float *reals, float *imags);
Chris@159 114
Chris@170 115 static size_t getCacheSize(size_t width, size_t height);
Chris@170 116
Chris@159 117 private:
Chris@159 118 size_t m_width;
Chris@159 119 size_t m_height;
Chris@159 120 uint16_t **m_magnitude;
Chris@159 121 uint16_t **m_phase;
Chris@159 122 float *m_factor;
Chris@159 123 ResizeableBitset m_colset;
Chris@159 124
Chris@159 125 void resize(uint16_t **&, size_t, size_t);
Chris@159 126 };
Chris@159 127
Chris@159 128
Chris@159 129 #endif
Chris@159 130