00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #ifndef _FFT_DATA_SERVER_H_
00017 #define _FFT_DATA_SERVER_H_
00018
00019 #include "base/Window.h"
00020 #include "base/Thread.h"
00021 #include "base/StorageAdviser.h"
00022
00023 #include "FFTapi.h"
00024
00025 #include <QMutex>
00026 #include <QWaitCondition>
00027 #include <QString>
00028
00029 #include <vector>
00030 #include <deque>
00031
00032 class DenseTimeValueModel;
00033 class Model;
00034 class FFTCache;
00035
00036 class FFTDataServer
00037 {
00038 public:
00039 static FFTDataServer *getInstance(const DenseTimeValueModel *model,
00040 int channel,
00041 WindowType windowType,
00042 size_t windowSize,
00043 size_t windowIncrement,
00044 size_t fftSize,
00045 bool polar,
00046 StorageAdviser::Criteria criteria =
00047 StorageAdviser::NoCriteria,
00048 size_t fillFromColumn = 0);
00049
00050 static FFTDataServer *getFuzzyInstance(const DenseTimeValueModel *model,
00051 int channel,
00052 WindowType windowType,
00053 size_t windowSize,
00054 size_t windowIncrement,
00055 size_t fftSize,
00056 bool polar,
00057 StorageAdviser::Criteria criteria =
00058 StorageAdviser::NoCriteria,
00059 size_t fillFromColumn = 0);
00060
00061 static void claimInstance(FFTDataServer *);
00062 static void releaseInstance(FFTDataServer *);
00063
00064 static void modelAboutToBeDeleted(Model *);
00065
00066 const DenseTimeValueModel *getModel() const { return m_model; }
00067 int getChannel() const { return m_channel; }
00068 WindowType getWindowType() const { return m_windower.getType(); }
00069 size_t getWindowSize() const { return m_windowSize; }
00070 size_t getWindowIncrement() const { return m_windowIncrement; }
00071 size_t getFFTSize() const { return m_fftSize; }
00072 bool getPolar() const { return m_polar; }
00073
00074 size_t getWidth() const { return m_width; }
00075 size_t getHeight() const { return m_height; }
00076
00077 float getMagnitudeAt(size_t x, size_t y);
00078 float getNormalizedMagnitudeAt(size_t x, size_t y);
00079 float getMaximumMagnitudeAt(size_t x);
00080 float getPhaseAt(size_t x, size_t y);
00081 void getValuesAt(size_t x, size_t y, float &real, float &imaginary);
00082 bool isColumnReady(size_t x);
00083
00084 void suspend();
00085 void suspendWrites();
00086 void resume();
00087
00088
00089
00090 bool isLocalPeak(size_t x, size_t y) {
00091 float mag = getMagnitudeAt(x, y);
00092 if (y > 0 && mag < getMagnitudeAt(x, y - 1)) return false;
00093 if (y < getHeight()-1 && mag < getMagnitudeAt(x, y + 1)) return false;
00094 return true;
00095 }
00096 bool isOverThreshold(size_t x, size_t y, float threshold) {
00097 return getMagnitudeAt(x, y) > threshold;
00098 }
00099
00100 size_t getFillCompletion() const;
00101 size_t getFillExtent() const;
00102
00103 private:
00104 FFTDataServer(QString fileBaseName,
00105 const DenseTimeValueModel *model,
00106 int channel,
00107 WindowType windowType,
00108 size_t windowSize,
00109 size_t windowIncrement,
00110 size_t fftSize,
00111 bool polar,
00112 StorageAdviser::Criteria criteria,
00113 size_t fillFromColumn = 0);
00114
00115 virtual ~FFTDataServer();
00116
00117 FFTDataServer(const FFTDataServer &);
00118 FFTDataServer &operator=(const FFTDataServer &);
00119
00120 typedef float fftsample;
00121
00122 QString m_fileBaseName;
00123 const DenseTimeValueModel *m_model;
00124 int m_channel;
00125
00126 Window<fftsample> m_windower;
00127
00128 size_t m_windowSize;
00129 size_t m_windowIncrement;
00130 size_t m_fftSize;
00131 bool m_polar;
00132
00133 size_t m_width;
00134 size_t m_height;
00135 size_t m_cacheWidth;
00136 size_t m_cacheWidthPower;
00137 size_t m_cacheWidthMask;
00138
00139 int m_lastUsedCache;
00140 FFTCache *getCache(size_t x, size_t &col) {
00141 col = x & m_cacheWidthMask;
00142 int c = x >> m_cacheWidthPower;
00143
00144
00145
00146 if (c == m_lastUsedCache) return m_caches[c];
00147 else return getCacheAux(c);
00148 }
00149 bool haveCache(size_t x) {
00150 int c = x >> m_cacheWidthPower;
00151 if (c == m_lastUsedCache) return true;
00152 else return (m_caches[c] != 0);
00153 }
00154
00155 typedef std::vector<FFTCache *> CacheVector;
00156 CacheVector m_caches;
00157
00158 typedef std::deque<int> IntQueue;
00159 IntQueue m_dormantCaches;
00160
00161 StorageAdviser::Criteria m_criteria;
00162
00163 void getStorageAdvice(size_t w, size_t h, bool &memory, bool &compact);
00164
00165 FFTCache *getCacheAux(size_t c);
00166 QMutex m_writeMutex;
00167 QWaitCondition m_condition;
00168
00169 fftsample *m_fftInput;
00170 fftf_complex *m_fftOutput;
00171 float *m_workbuffer;
00172 fftf_plan m_fftPlan;
00173
00174 class FillThread : public Thread
00175 {
00176 public:
00177 FillThread(FFTDataServer &server, size_t fillFromColumn) :
00178 m_server(server), m_extent(0), m_completion(0),
00179 m_fillFrom(fillFromColumn) { }
00180
00181 size_t getExtent() const { return m_extent; }
00182 size_t getCompletion() const { return m_completion ? m_completion : 1; }
00183 virtual void run();
00184
00185 protected:
00186 FFTDataServer &m_server;
00187 size_t m_extent;
00188 size_t m_completion;
00189 size_t m_fillFrom;
00190 };
00191
00192 bool m_exiting;
00193 bool m_suspended;
00194 FillThread *m_fillThread;
00195
00196 void deleteProcessingData();
00197 void fillColumn(size_t x);
00198
00199 QString generateFileBasename() const;
00200 static QString generateFileBasename(const DenseTimeValueModel *model,
00201 int channel,
00202 WindowType windowType,
00203 size_t windowSize,
00204 size_t windowIncrement,
00205 size_t fftSize,
00206 bool polar);
00207
00208 typedef std::pair<FFTDataServer *, int> ServerCountPair;
00209 typedef std::map<QString, ServerCountPair> ServerMap;
00210 typedef std::deque<FFTDataServer *> ServerQueue;
00211
00212 static ServerMap m_servers;
00213 static ServerQueue m_releasedServers;
00214 static QMutex m_serverMapMutex;
00215 static FFTDataServer *findServer(QString);
00216 static void purgeLimbo(int maxSize = 3);
00217
00218 static void claimInstance(FFTDataServer *, bool needLock);
00219 static void releaseInstance(FFTDataServer *, bool needLock);
00220
00221 };
00222
00223 #endif