svcore  1.9
FFTMemoryCache.h
Go to the documentation of this file.
00001 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
00002 
00003 /*
00004     Sonic Visualiser
00005     An audio file viewer and annotation editor.
00006     Centre for Digital Music, Queen Mary, University of London.
00007     This file copyright 2006 Chris Cannam.
00008     
00009     This program is free software; you can redistribute it and/or
00010     modify it under the terms of the GNU General Public License as
00011     published by the Free Software Foundation; either version 2 of the
00012     License, or (at your option) any later version.  See the file
00013     COPYING included with this distribution for more information.
00014 */
00015 
00016 #ifndef _FFT_MEMORY_CACHE_H_
00017 #define _FFT_MEMORY_CACHE_H_
00018 
00019 #include "FFTCacheReader.h"
00020 #include "FFTCacheWriter.h"
00021 #include "FFTCacheStorageType.h"
00022 #include "base/ResizeableBitset.h"
00023 #include "base/Profiler.h"
00024 
00025 #include <QReadWriteLock>
00026 
00046 class FFTMemoryCache : public FFTCacheReader, public FFTCacheWriter
00047 {
00048 public:
00049     FFTMemoryCache(FFTCache::StorageType storageType,
00050                    int width, int height);
00051     ~FFTMemoryCache();
00052         
00053     int getWidth() const { return m_width; }
00054     int getHeight() const { return m_height; }
00055         
00056     float getMagnitudeAt(int x, int y) const {
00057         if (m_storageType == FFTCache::Rectangular) {
00058             Profiler profiler("FFTMemoryCache::getMagnitudeAt: cart to polar");
00059             return sqrtf(m_freal[x][y] * m_freal[x][y] +
00060                          m_fimag[x][y] * m_fimag[x][y]);
00061         } else {
00062             return getNormalizedMagnitudeAt(x, y) * m_factor[x];
00063         }
00064     }
00065     
00066     float getNormalizedMagnitudeAt(int x, int y) const {
00067         if (m_storageType == FFTCache::Rectangular) return getMagnitudeAt(x, y) / m_factor[x];
00068         else if (m_storageType == FFTCache::Polar) return m_fmagnitude[x][y];
00069         else return float(m_magnitude[x][y]) / 65535.0;
00070     }
00071     
00072     float getMaximumMagnitudeAt(int x) const {
00073         return m_factor[x];
00074     }
00075     
00076     float getPhaseAt(int x, int y) const {
00077         if (m_storageType == FFTCache::Rectangular) {
00078             Profiler profiler("FFTMemoryCache::getValuesAt: cart to polar");
00079             return atan2f(m_fimag[x][y], m_freal[x][y]);
00080         } else if (m_storageType == FFTCache::Polar) {
00081             return m_fphase[x][y];
00082         } else {
00083             int16_t i = (int16_t)m_phase[x][y];
00084             return (float(i) / 32767.0) * M_PI;
00085         }
00086     }
00087     
00088     void getValuesAt(int x, int y, float &real, float &imag) const {
00089         if (m_storageType == FFTCache::Rectangular) {
00090             real = m_freal[x][y];
00091             imag = m_fimag[x][y];
00092         } else {
00093             Profiler profiler("FFTMemoryCache::getValuesAt: polar to cart");
00094             float mag = getMagnitudeAt(x, y);
00095             float phase = getPhaseAt(x, y);
00096             real = mag * cosf(phase);
00097             imag = mag * sinf(phase);
00098         }
00099     }
00100 
00101     void getMagnitudesAt(int x, float *values, int minbin, int count, int step) const
00102     {
00103         if (m_storageType == FFTCache::Rectangular) {
00104             for (int i = 0; i < count; ++i) {
00105                 int y = i * step + minbin;
00106                 values[i] = sqrtf(m_freal[x][y] * m_freal[x][y] +
00107                                   m_fimag[x][y] * m_fimag[x][y]);
00108             }
00109         } else if (m_storageType == FFTCache::Polar) {
00110             for (int i = 0; i < count; ++i) {
00111                 int y = i * step + minbin;
00112                 values[i] = m_fmagnitude[x][y] * m_factor[x];
00113             }
00114         } else {
00115             for (int i = 0; i < count; ++i) {
00116                 int y = i * step + minbin;
00117                 values[i] = (float(m_magnitude[x][y]) * m_factor[x]) / 65535.0;
00118             }
00119         }
00120     }
00121 
00122     bool haveSetColumnAt(int x) const {
00123         m_colsetLock.lockForRead();
00124         bool have = m_colset.get(x);
00125         m_colsetLock.unlock();
00126         return have;
00127     }
00128 
00129     void setColumnAt(int x, float *mags, float *phases, float factor);
00130 
00131     void setColumnAt(int x, float *reals, float *imags);
00132 
00133     void allColumnsWritten() { } 
00134 
00135     static int getCacheSize(int width, int height,
00136                                FFTCache::StorageType type);
00137 
00138     FFTCache::StorageType getStorageType() const { return m_storageType; }
00139 
00140 private:
00141     int m_width;
00142     int m_height;
00143     uint16_t **m_magnitude;
00144     uint16_t **m_phase;
00145     float **m_fmagnitude;
00146     float **m_fphase;
00147     float **m_freal;
00148     float **m_fimag;
00149     float *m_factor;
00150     FFTCache::StorageType m_storageType;
00151     ResizeableBitset m_colset;
00152     mutable QReadWriteLock m_colsetLock;
00153 
00154     void initialise();
00155 
00156     void setNormalizationFactor(int x, float factor) {
00157         if (x < m_width) m_factor[x] = factor;
00158     }
00159     
00160     void setMagnitudeAt(int x, int y, float mag) {
00161          // norm factor must already be set
00162         setNormalizedMagnitudeAt(x, y, mag / m_factor[x]);
00163     }
00164     
00165     void setNormalizedMagnitudeAt(int x, int y, float norm) {
00166         if (x < m_width && y < m_height) {
00167             if (m_storageType == FFTCache::Polar) m_fmagnitude[x][y] = norm;
00168             else m_magnitude[x][y] = uint16_t(norm * 65535.0);
00169         }
00170     }
00171     
00172     void setPhaseAt(int x, int y, float phase) {
00173         // phase in range -pi -> pi
00174         if (x < m_width && y < m_height) {
00175             if (m_storageType == FFTCache::Polar) m_fphase[x][y] = phase;
00176             else m_phase[x][y] = uint16_t(int16_t((phase * 32767) / M_PI));
00177         }
00178     }
00179 
00180     void initialise(uint16_t **&);
00181     void initialise(float **&);
00182 };
00183 
00184 
00185 #endif
00186