annotate data/fft/FFTDataServer.h @ 282:d9319859a4cf tip

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