FFTDataServer.h

Go to the documentation of this file.
00001 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
00002 
00003 /*
00004     Sonic Visualiser
00005     An audio file viewer and annotation editor.
00006     Centre for Digital Music, Queen Mary, University of London.
00007     This file copyright 2006 Chris Cannam and QMUL.
00008     
00009     This program is free software; you can redistribute it and/or
00010     modify it under the terms of the GNU General Public License as
00011     published by the Free Software Foundation; either version 2 of the
00012     License, or (at your option) any later version.  See the file
00013     COPYING included with this distribution for more information.
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(); // also happens automatically if new data needed
00087 
00088     // Convenience functions:
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 &); // not implemented
00118     FFTDataServer &operator=(const FFTDataServer &); // not implemented
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         // The only use of m_lastUsedCache without a lock is to
00144         // establish whether a cache has been created at all (they're
00145         // created on demand, but not destroyed until the server is).
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; // these are still in m_servers as well, with zero refcount
00214     static QMutex m_serverMapMutex;
00215     static FFTDataServer *findServer(QString); // call with serverMapMutex held
00216     static void purgeLimbo(int maxSize = 3); // call with serverMapMutex held
00217 
00218     static void claimInstance(FFTDataServer *, bool needLock);
00219     static void releaseInstance(FFTDataServer *, bool needLock);
00220 
00221 };
00222 
00223 #endif

Generated on Wed Feb 20 15:45:25 2008 for SonicVisualiser by  doxygen 1.5.1