Mercurial > hg > easaier-soundaccess
comparison data/fft/FFTDataServer.h @ 0:fc9323a41f5a
start base : Sonic Visualiser sv1-1.0rc1
author | lbajardsilogic |
---|---|
date | Fri, 11 May 2007 09:08:14 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:fc9323a41f5a |
---|---|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ | |
2 | |
3 /* | |
4 Sonic Visualiser | |
5 An audio file viewer and annotation editor. | |
6 Centre for Digital Music, Queen Mary, University of London. | |
7 This file copyright 2006 Chris Cannam and QMUL. | |
8 | |
9 This program is free software; you can redistribute it and/or | |
10 modify it under the terms of the GNU General Public License as | |
11 published by the Free Software Foundation; either version 2 of the | |
12 License, or (at your option) any later version. See the file | |
13 COPYING included with this distribution for more information. | |
14 */ | |
15 | |
16 #ifndef _FFT_DATA_SERVER_H_ | |
17 #define _FFT_DATA_SERVER_H_ | |
18 | |
19 #include "base/Window.h" | |
20 #include "base/Thread.h" | |
21 | |
22 #include "FFTapi.h" | |
23 | |
24 #include <QMutex> | |
25 #include <QWaitCondition> | |
26 #include <QString> | |
27 | |
28 #include <vector> | |
29 #include <deque> | |
30 | |
31 class DenseTimeValueModel; | |
32 class Model; | |
33 class FFTCache; | |
34 | |
35 class FFTDataServer | |
36 { | |
37 public: | |
38 static FFTDataServer *getInstance(const DenseTimeValueModel *model, | |
39 int channel, | |
40 WindowType windowType, | |
41 size_t windowSize, | |
42 size_t windowIncrement, | |
43 size_t fftSize, | |
44 bool polar, | |
45 size_t fillFromColumn = 0); | |
46 | |
47 static FFTDataServer *getFuzzyInstance(const DenseTimeValueModel *model, | |
48 int channel, | |
49 WindowType windowType, | |
50 size_t windowSize, | |
51 size_t windowIncrement, | |
52 size_t fftSize, | |
53 bool polar, | |
54 size_t fillFromColumn = 0); | |
55 | |
56 static void claimInstance(FFTDataServer *); | |
57 static void releaseInstance(FFTDataServer *); | |
58 | |
59 static void modelAboutToBeDeleted(Model *); | |
60 | |
61 const DenseTimeValueModel *getModel() const { return m_model; } | |
62 int getChannel() const { return m_channel; } | |
63 WindowType getWindowType() const { return m_windower.getType(); } | |
64 size_t getWindowSize() const { return m_windowSize; } | |
65 size_t getWindowIncrement() const { return m_windowIncrement; } | |
66 size_t getFFTSize() const { return m_fftSize; } | |
67 bool getPolar() const { return m_polar; } | |
68 | |
69 size_t getWidth() const { return m_width; } | |
70 size_t getHeight() const { return m_height; } | |
71 | |
72 float getMagnitudeAt(size_t x, size_t y); | |
73 float getNormalizedMagnitudeAt(size_t x, size_t y); | |
74 float getMaximumMagnitudeAt(size_t x); | |
75 float getPhaseAt(size_t x, size_t y); | |
76 void getValuesAt(size_t x, size_t y, float &real, float &imaginary); | |
77 bool isColumnReady(size_t x); | |
78 | |
79 void suspend(); | |
80 void suspendWrites(); | |
81 void resume(); // also happens automatically if new data needed | |
82 | |
83 // Convenience functions: | |
84 | |
85 bool isLocalPeak(size_t x, size_t y) { | |
86 float mag = getMagnitudeAt(x, y); | |
87 if (y > 0 && mag < getMagnitudeAt(x, y - 1)) return false; | |
88 if (y < getHeight()-1 && mag < getMagnitudeAt(x, y + 1)) return false; | |
89 return true; | |
90 } | |
91 bool isOverThreshold(size_t x, size_t y, float threshold) { | |
92 return getMagnitudeAt(x, y) > threshold; | |
93 } | |
94 | |
95 size_t getFillCompletion() const; | |
96 size_t getFillExtent() const; | |
97 | |
98 private: | |
99 FFTDataServer(QString fileBaseName, | |
100 const DenseTimeValueModel *model, | |
101 int channel, | |
102 WindowType windowType, | |
103 size_t windowSize, | |
104 size_t windowIncrement, | |
105 size_t fftSize, | |
106 bool polar, | |
107 size_t fillFromColumn = 0); | |
108 | |
109 virtual ~FFTDataServer(); | |
110 | |
111 FFTDataServer(const FFTDataServer &); // not implemented | |
112 FFTDataServer &operator=(const FFTDataServer &); // not implemented | |
113 | |
114 typedef float fftsample; | |
115 | |
116 QString m_fileBaseName; | |
117 const DenseTimeValueModel *m_model; | |
118 int m_channel; | |
119 | |
120 Window<fftsample> m_windower; | |
121 | |
122 size_t m_windowSize; | |
123 size_t m_windowIncrement; | |
124 size_t m_fftSize; | |
125 bool m_polar; | |
126 | |
127 size_t m_width; | |
128 size_t m_height; | |
129 size_t m_cacheWidth; | |
130 size_t m_cacheWidthPower; | |
131 size_t m_cacheWidthMask; | |
132 bool m_memoryCache; | |
133 bool m_compactCache; | |
134 | |
135 typedef std::vector<FFTCache *> CacheVector; | |
136 CacheVector m_caches; | |
137 | |
138 typedef std::deque<int> IntQueue; | |
139 IntQueue m_dormantCaches; | |
140 | |
141 int m_lastUsedCache; | |
142 FFTCache *getCache(size_t x, size_t &col) { | |
143 col = x % m_cacheWidth; | |
144 int c = x / m_cacheWidth; | |
145 // The only use of m_lastUsedCache without a lock is to | |
146 // establish whether a cache has been created at all (they're | |
147 // created on demand, but not destroyed until the server is). | |
148 if (c == m_lastUsedCache) return m_caches[c]; | |
149 else return getCacheAux(c); | |
150 } | |
151 bool haveCache(size_t x) { | |
152 int c = x / m_cacheWidth; | |
153 if (c == m_lastUsedCache) return true; | |
154 else return (m_caches[c] != 0); | |
155 } | |
156 | |
157 FFTCache *getCacheAux(size_t c); | |
158 QMutex m_writeMutex; | |
159 QWaitCondition m_condition; | |
160 | |
161 fftsample *m_fftInput; | |
162 fftf_complex *m_fftOutput; | |
163 float *m_workbuffer; | |
164 fftf_plan m_fftPlan; | |
165 | |
166 class FillThread : public Thread | |
167 { | |
168 public: | |
169 FillThread(FFTDataServer &server, size_t fillFromColumn) : | |
170 m_server(server), m_extent(0), m_completion(0), | |
171 m_fillFrom(fillFromColumn) { } | |
172 | |
173 size_t getExtent() const { return m_extent; } | |
174 size_t getCompletion() const { return m_completion ? m_completion : 1; } | |
175 virtual void run(); | |
176 | |
177 protected: | |
178 FFTDataServer &m_server; | |
179 size_t m_extent; | |
180 size_t m_completion; | |
181 size_t m_fillFrom; | |
182 }; | |
183 | |
184 bool m_exiting; | |
185 bool m_suspended; | |
186 FillThread *m_fillThread; | |
187 | |
188 void deleteProcessingData(); | |
189 void fillColumn(size_t x); | |
190 | |
191 QString generateFileBasename() const; | |
192 static QString generateFileBasename(const DenseTimeValueModel *model, | |
193 int channel, | |
194 WindowType windowType, | |
195 size_t windowSize, | |
196 size_t windowIncrement, | |
197 size_t fftSize, | |
198 bool polar); | |
199 | |
200 typedef std::pair<FFTDataServer *, int> ServerCountPair; | |
201 typedef std::map<QString, ServerCountPair> ServerMap; | |
202 typedef std::deque<FFTDataServer *> ServerQueue; | |
203 | |
204 static ServerMap m_servers; | |
205 static ServerQueue m_releasedServers; // these are still in m_servers as well, with zero refcount | |
206 static QMutex m_serverMapMutex; | |
207 static FFTDataServer *findServer(QString); // call with serverMapMutex held | |
208 static void purgeLimbo(int maxSize = 3); // call with serverMapMutex held | |
209 | |
210 static void claimInstance(FFTDataServer *, bool needLock); | |
211 static void releaseInstance(FFTDataServer *, bool needLock); | |
212 | |
213 }; | |
214 | |
215 #endif |