Mercurial > hg > svcore
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 |