Mercurial > hg > svcore
comparison data/fft/FFTDataServer.h @ 148:1a42221a1522
* Reorganising code base. This revision will not compile.
author | Chris Cannam |
---|---|
date | Mon, 31 Jul 2006 11:49:58 +0000 |
parents | |
children | 21792a550ec9 |
comparison
equal
deleted
inserted
replaced
147:3a13b0d4934e | 148:1a42221a1522 |
---|---|
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. | |
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 <fftw3.h> | |
23 | |
24 #include <QMutex> | |
25 #include <QWaitCondition> | |
26 #include <QString> | |
27 | |
28 #include <vector> | |
29 #include <deque> | |
30 | |
31 class DenseTimeValueModel; | |
32 class FFTCache; | |
33 | |
34 class FFTDataServer | |
35 { | |
36 public: | |
37 static FFTDataServer *getInstance(const DenseTimeValueModel *model, | |
38 int channel, | |
39 WindowType windowType, | |
40 size_t windowSize, | |
41 size_t windowIncrement, | |
42 size_t fftSize, | |
43 bool polar, | |
44 size_t fillFromColumn = 0); | |
45 | |
46 static FFTDataServer *getFuzzyInstance(const DenseTimeValueModel *model, | |
47 int channel, | |
48 WindowType windowType, | |
49 size_t windowSize, | |
50 size_t windowIncrement, | |
51 size_t fftSize, | |
52 bool polar, | |
53 size_t fillFromColumn = 0); | |
54 | |
55 static void releaseInstance(FFTDataServer *); | |
56 | |
57 const DenseTimeValueModel *getModel() const { return m_model; } | |
58 int getChannel() const { return m_channel; } | |
59 WindowType getWindowType() const { return m_windower.getType(); } | |
60 size_t getWindowSize() const { return m_windowSize; } | |
61 size_t getWindowIncrement() const { return m_windowIncrement; } | |
62 size_t getFFTSize() const { return m_fftSize; } | |
63 bool getPolar() const { return m_polar; } | |
64 | |
65 size_t getWidth() const { return m_width; } | |
66 size_t getHeight() const { return m_height; } | |
67 | |
68 float getMagnitudeAt(size_t x, size_t y); | |
69 float getNormalizedMagnitudeAt(size_t x, size_t y); | |
70 float getMaximumMagnitudeAt(size_t x); | |
71 float getPhaseAt(size_t x, size_t y); | |
72 void getValuesAt(size_t x, size_t y, float &real, float &imaginary); | |
73 bool isColumnReady(size_t x); | |
74 | |
75 void suspend(); | |
76 | |
77 // Convenience functions: | |
78 | |
79 bool isLocalPeak(size_t x, size_t y) { | |
80 float mag = getMagnitudeAt(x, y); | |
81 if (y > 0 && mag < getMagnitudeAt(x, y - 1)) return false; | |
82 if (y < getHeight()-1 && mag < getMagnitudeAt(x, y + 1)) return false; | |
83 return true; | |
84 } | |
85 bool isOverThreshold(size_t x, size_t y, float threshold) { | |
86 return getMagnitudeAt(x, y) > threshold; | |
87 } | |
88 | |
89 size_t getFillCompletion() const; | |
90 size_t getFillExtent() const; | |
91 | |
92 private: | |
93 FFTDataServer(QString fileBaseName, | |
94 const DenseTimeValueModel *model, | |
95 int channel, | |
96 WindowType windowType, | |
97 size_t windowSize, | |
98 size_t windowIncrement, | |
99 size_t fftSize, | |
100 bool polar, | |
101 size_t fillFromColumn = 0); | |
102 | |
103 virtual ~FFTDataServer(); | |
104 | |
105 FFTDataServer(const FFTDataServer &); // not implemented | |
106 FFTDataServer &operator=(const FFTDataServer &); // not implemented | |
107 | |
108 typedef float fftsample; | |
109 | |
110 QString m_fileBaseName; | |
111 const DenseTimeValueModel *m_model; | |
112 int m_channel; | |
113 | |
114 Window<fftsample> m_windower; | |
115 | |
116 size_t m_windowSize; | |
117 size_t m_windowIncrement; | |
118 size_t m_fftSize; | |
119 bool m_polar; | |
120 | |
121 size_t m_width; | |
122 size_t m_height; | |
123 size_t m_cacheWidth; | |
124 | |
125 typedef std::vector<FFTCache *> CacheVector; | |
126 CacheVector m_caches; | |
127 | |
128 typedef std::deque<int> IntQueue; | |
129 IntQueue m_dormantCaches; | |
130 | |
131 int m_lastUsedCache; | |
132 FFTCache *getCache(size_t x, size_t &col) { | |
133 if (m_suspended) resume(); | |
134 col = x % m_cacheWidth; | |
135 int c = x / m_cacheWidth; | |
136 // The only use of m_lastUsedCache without a lock is to | |
137 // establish whether a cache has been created at all (they're | |
138 // created on demand, but not destroyed until the server is). | |
139 if (c == m_lastUsedCache) return m_caches[c]; | |
140 else return getCacheAux(c); | |
141 } | |
142 bool haveCache(size_t x) { | |
143 int c = x / m_cacheWidth; | |
144 if (c == m_lastUsedCache) return true; | |
145 else return (m_caches[c] != 0); | |
146 } | |
147 | |
148 FFTCache *getCacheAux(size_t c); | |
149 QMutex m_writeMutex; | |
150 QWaitCondition m_condition; | |
151 | |
152 fftsample *m_fftInput; | |
153 fftwf_complex *m_fftOutput; | |
154 float *m_workbuffer; | |
155 fftwf_plan m_fftPlan; | |
156 | |
157 class FillThread : public Thread | |
158 { | |
159 public: | |
160 FillThread(FFTDataServer &server, size_t fillFromColumn) : | |
161 m_server(server), m_extent(0), m_completion(0), | |
162 m_fillFrom(fillFromColumn) { } | |
163 | |
164 size_t getExtent() const { return m_extent; } | |
165 size_t getCompletion() const { return m_completion ? m_completion : 1; } | |
166 virtual void run(); | |
167 | |
168 protected: | |
169 FFTDataServer &m_server; | |
170 size_t m_extent; | |
171 size_t m_completion; | |
172 size_t m_fillFrom; | |
173 }; | |
174 | |
175 bool m_exiting; | |
176 bool m_suspended; | |
177 FillThread *m_fillThread; | |
178 | |
179 void deleteProcessingData(); | |
180 void fillColumn(size_t x); | |
181 void resume(); | |
182 | |
183 QString generateFileBasename() const; | |
184 static QString generateFileBasename(const DenseTimeValueModel *model, | |
185 int channel, | |
186 WindowType windowType, | |
187 size_t windowSize, | |
188 size_t windowIncrement, | |
189 size_t fftSize, | |
190 bool polar); | |
191 | |
192 typedef std::pair<FFTDataServer *, int> ServerCountPair; | |
193 typedef std::map<QString, ServerCountPair> ServerMap; | |
194 | |
195 static ServerMap m_servers; | |
196 static QMutex m_serverMapMutex; | |
197 static FFTDataServer *findServer(QString); // call with serverMapMutex held | |
198 static void purgeLimbo(int maxSize = 3); // call with serverMapMutex held | |
199 }; | |
200 | |
201 #endif |