comparison data/fft/FFTMemoryCache.h @ 537:3cc4b7cd2aa5

* Merge from one-fftdataserver-per-fftmodel branch. This bit of reworking (which is not described very accurately by the title of the branch) turns the MatrixFile object into something that either reads or writes, but not both, and separates the FFT file cache reader and writer implementations separately. This allows the FFT data server to have a single thread owning writers and one reader per "customer" thread, and for all locking to be vastly simplified and concentrated in the data server alone (because none of the classes it makes use of is used in more than one thread at a time). The result is faster and more trustworthy code.
author Chris Cannam
date Tue, 27 Jan 2009 13:25:10 +0000
parents 6066bde1c126
children 1469caaa8e67
comparison
equal deleted inserted replaced
536:beb51f558e9c 537:3cc4b7cd2aa5
14 */ 14 */
15 15
16 #ifndef _FFT_MEMORY_CACHE_H_ 16 #ifndef _FFT_MEMORY_CACHE_H_
17 #define _FFT_MEMORY_CACHE_H_ 17 #define _FFT_MEMORY_CACHE_H_
18 18
19 #include "FFTCache.h" 19 #include "FFTCacheReader.h"
20 20 #include "FFTCacheWriter.h"
21 #include "FFTCacheStorageType.h"
21 #include "base/ResizeableBitset.h" 22 #include "base/ResizeableBitset.h"
22 #include "base/Profiler.h" 23 #include "base/Profiler.h"
24
25 #include <QMutex>
23 26
24 /** 27 /**
25 * In-memory FFT cache. For this we want to cache magnitude with 28 * In-memory FFT cache. For this we want to cache magnitude with
26 * enough resolution to have gain applied afterwards and determine 29 * enough resolution to have gain applied afterwards and determine
27 * whether something is a peak or not, and also cache phase rather 30 * whether something is a peak or not, and also cache phase rather
38 * to [0,1] with respect to the column, so the normalization 41 * to [0,1] with respect to the column, so the normalization
39 * factor should be calculated before all values in a column, and 42 * factor should be calculated before all values in a column, and
40 * set appropriately. 43 * set appropriately.
41 */ 44 */
42 45
43 class FFTMemoryCache : public FFTCache 46 class FFTMemoryCache : public FFTCacheReader, public FFTCacheWriter
44 { 47 {
45 public: 48 public:
46 FFTMemoryCache(StorageType storageType); // of size zero, call resize() before using 49 FFTMemoryCache(FFTCache::StorageType storageType,
47 virtual ~FFTMemoryCache(); 50 size_t width, size_t height);
51 ~FFTMemoryCache();
48 52
49 virtual size_t getWidth() const { return m_width; } 53 size_t getWidth() const { return m_width; }
50 virtual size_t getHeight() const { return m_height; } 54 size_t getHeight() const { return m_height; }
51 55
52 virtual void resize(size_t width, size_t height); 56 float getMagnitudeAt(size_t x, size_t y) const {
53 virtual void reset(); // zero-fill or 1-fill as appropriate without changing size 57 if (m_storageType == FFTCache::Rectangular) {
54
55 virtual float getMagnitudeAt(size_t x, size_t y) const {
56 if (m_storageType == Rectangular) {
57 Profiler profiler("FFTMemoryCache::getMagnitudeAt: cart to polar"); 58 Profiler profiler("FFTMemoryCache::getMagnitudeAt: cart to polar");
58 return sqrtf(m_freal[x][y] * m_freal[x][y] + 59 return sqrtf(m_freal[x][y] * m_freal[x][y] +
59 m_fimag[x][y] * m_fimag[x][y]); 60 m_fimag[x][y] * m_fimag[x][y]);
60 } else { 61 } else {
61 return getNormalizedMagnitudeAt(x, y) * m_factor[x]; 62 return getNormalizedMagnitudeAt(x, y) * m_factor[x];
62 } 63 }
63 } 64 }
64 65
65 virtual float getNormalizedMagnitudeAt(size_t x, size_t y) const { 66 float getNormalizedMagnitudeAt(size_t x, size_t y) const {
66 if (m_storageType == Rectangular) return getMagnitudeAt(x, y) / m_factor[x]; 67 if (m_storageType == FFTCache::Rectangular) return getMagnitudeAt(x, y) / m_factor[x];
67 else if (m_storageType == Polar) return m_fmagnitude[x][y]; 68 else if (m_storageType == FFTCache::Polar) return m_fmagnitude[x][y];
68 else return float(m_magnitude[x][y]) / 65535.0; 69 else return float(m_magnitude[x][y]) / 65535.0;
69 } 70 }
70 71
71 virtual float getMaximumMagnitudeAt(size_t x) const { 72 float getMaximumMagnitudeAt(size_t x) const {
72 return m_factor[x]; 73 return m_factor[x];
73 } 74 }
74 75
75 virtual float getPhaseAt(size_t x, size_t y) const { 76 float getPhaseAt(size_t x, size_t y) const {
76 if (m_storageType == Rectangular) { 77 if (m_storageType == FFTCache::Rectangular) {
77 Profiler profiler("FFTMemoryCache::getValuesAt: cart to polar"); 78 Profiler profiler("FFTMemoryCache::getValuesAt: cart to polar");
78 return atan2f(m_fimag[x][y], m_freal[x][y]); 79 return atan2f(m_fimag[x][y], m_freal[x][y]);
79 } else if (m_storageType == Polar) { 80 } else if (m_storageType == FFTCache::Polar) {
80 return m_fphase[x][y]; 81 return m_fphase[x][y];
81 } else { 82 } else {
82 int16_t i = (int16_t)m_phase[x][y]; 83 int16_t i = (int16_t)m_phase[x][y];
83 return (float(i) / 32767.0) * M_PI; 84 return (float(i) / 32767.0) * M_PI;
84 } 85 }
85 } 86 }
86 87
87 virtual void getValuesAt(size_t x, size_t y, float &real, float &imag) const { 88 void getValuesAt(size_t x, size_t y, float &real, float &imag) const {
88 if (m_storageType == Rectangular) { 89 if (m_storageType == FFTCache::Rectangular) {
89 real = m_freal[x][y]; 90 real = m_freal[x][y];
90 imag = m_fimag[x][y]; 91 imag = m_fimag[x][y];
91 } else { 92 } else {
92 Profiler profiler("FFTMemoryCache::getValuesAt: polar to cart"); 93 Profiler profiler("FFTMemoryCache::getValuesAt: polar to cart");
93 float mag = getMagnitudeAt(x, y); 94 float mag = getMagnitudeAt(x, y);
95 real = mag * cosf(phase); 96 real = mag * cosf(phase);
96 imag = mag * sinf(phase); 97 imag = mag * sinf(phase);
97 } 98 }
98 } 99 }
99 100
100 virtual void getMagnitudesAt(size_t x, float *values, size_t minbin, size_t count, size_t step) const 101 void getMagnitudesAt(size_t x, float *values, size_t minbin, size_t count, size_t step) const
101 { 102 {
102 if (m_storageType == Rectangular) { 103 if (m_storageType == FFTCache::Rectangular) {
103 for (size_t i = 0; i < count; ++i) { 104 for (size_t i = 0; i < count; ++i) {
104 size_t y = i * step + minbin; 105 size_t y = i * step + minbin;
105 values[i] = sqrtf(m_freal[x][y] * m_freal[x][y] + 106 values[i] = sqrtf(m_freal[x][y] * m_freal[x][y] +
106 m_fimag[x][y] * m_fimag[x][y]); 107 m_fimag[x][y] * m_fimag[x][y]);
107 } 108 }
108 } else if (m_storageType == Polar) { 109 } else if (m_storageType == FFTCache::Polar) {
109 for (size_t i = 0; i < count; ++i) { 110 for (size_t i = 0; i < count; ++i) {
110 size_t y = i * step + minbin; 111 size_t y = i * step + minbin;
111 values[i] = m_fmagnitude[x][y] * m_factor[x]; 112 values[i] = m_fmagnitude[x][y] * m_factor[x];
112 } 113 }
113 } else { 114 } else {
116 values[i] = (float(m_magnitude[x][y]) * m_factor[x]) / 65535.0; 117 values[i] = (float(m_magnitude[x][y]) * m_factor[x]) / 65535.0;
117 } 118 }
118 } 119 }
119 } 120 }
120 121
121 virtual bool haveSetColumnAt(size_t x) const { 122 bool haveSetColumnAt(size_t x) const {
122 return m_colset.get(x); 123 m_colsetMutex.lock();
124 bool have = m_colset.get(x);
125 m_colsetMutex.unlock();
126 return have;
123 } 127 }
124 128
125 virtual void setColumnAt(size_t x, float *mags, float *phases, float factor); 129 void setColumnAt(size_t x, float *mags, float *phases, float factor);
126 130
127 virtual void setColumnAt(size_t x, float *reals, float *imags); 131 void setColumnAt(size_t x, float *reals, float *imags);
128 132
129 static size_t getCacheSize(size_t width, size_t height, StorageType type); 133 void allColumnsWritten() { }
130 134
131 virtual StorageType getStorageType() { return m_storageType; } 135 static size_t getCacheSize(size_t width, size_t height,
132 virtual Type getType() { return MemoryCache; } 136 FFTCache::StorageType type);
137
138 FFTCache::StorageType getStorageType() const { return m_storageType; }
133 139
134 private: 140 private:
135 size_t m_width; 141 size_t m_width;
136 size_t m_height; 142 size_t m_height;
137 uint16_t **m_magnitude; 143 uint16_t **m_magnitude;
139 float **m_fmagnitude; 145 float **m_fmagnitude;
140 float **m_fphase; 146 float **m_fphase;
141 float **m_freal; 147 float **m_freal;
142 float **m_fimag; 148 float **m_fimag;
143 float *m_factor; 149 float *m_factor;
144 StorageType m_storageType; 150 FFTCache::StorageType m_storageType;
145 ResizeableBitset m_colset; 151 ResizeableBitset m_colset;
152 mutable QMutex m_colsetMutex;
146 153
147 virtual void setNormalizationFactor(size_t x, float factor) { 154 void initialise();
155
156 void setNormalizationFactor(size_t x, float factor) {
148 if (x < m_width) m_factor[x] = factor; 157 if (x < m_width) m_factor[x] = factor;
149 } 158 }
150 159
151 virtual void setMagnitudeAt(size_t x, size_t y, float mag) { 160 void setMagnitudeAt(size_t x, size_t y, float mag) {
152 // norm factor must already be set 161 // norm factor must already be set
153 setNormalizedMagnitudeAt(x, y, mag / m_factor[x]); 162 setNormalizedMagnitudeAt(x, y, mag / m_factor[x]);
154 } 163 }
155 164
156 virtual void setNormalizedMagnitudeAt(size_t x, size_t y, float norm) { 165 void setNormalizedMagnitudeAt(size_t x, size_t y, float norm) {
157 if (x < m_width && y < m_height) { 166 if (x < m_width && y < m_height) {
158 if (m_storageType == Polar) m_fmagnitude[x][y] = norm; 167 if (m_storageType == FFTCache::Polar) m_fmagnitude[x][y] = norm;
159 else m_magnitude[x][y] = uint16_t(norm * 65535.0); 168 else m_magnitude[x][y] = uint16_t(norm * 65535.0);
160 } 169 }
161 } 170 }
162 171
163 virtual void setPhaseAt(size_t x, size_t y, float phase) { 172 void setPhaseAt(size_t x, size_t y, float phase) {
164 // phase in range -pi -> pi 173 // phase in range -pi -> pi
165 if (x < m_width && y < m_height) { 174 if (x < m_width && y < m_height) {
166 if (m_storageType == Polar) m_fphase[x][y] = phase; 175 if (m_storageType == FFTCache::Polar) m_fphase[x][y] = phase;
167 else m_phase[x][y] = uint16_t(int16_t((phase * 32767) / M_PI)); 176 else m_phase[x][y] = uint16_t(int16_t((phase * 32767) / M_PI));
168 } 177 }
169 } 178 }
170 179
171 void resize(uint16_t **&, size_t, size_t); 180 void initialise(uint16_t **&);
172 void resize(float **&, size_t, size_t); 181 void initialise(float **&);
173 }; 182 };
174 183
175 184
176 #endif 185 #endif
177 186