svcore
1.9
|
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