svcore  1.9
FFTModel.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.
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_MODEL_H_
00017 #define _FFT_MODEL_H_
00018 
00019 #include "data/fft/FFTDataServer.h"
00020 #include "DenseThreeDimensionalModel.h"
00021 
00022 #include <set>
00023 #include <map>
00024 
00033 class FFTModel : public DenseThreeDimensionalModel
00034 {
00035     Q_OBJECT
00036 
00037 public:
00058     FFTModel(const DenseTimeValueModel *model,
00059              int channel,
00060              WindowType windowType,
00061              int windowSize,
00062              int windowIncrement,
00063              int fftSize,
00064              bool polar,
00065              StorageAdviser::Criteria criteria = StorageAdviser::NoCriteria,
00066              int fillFromColumn = 0);
00067     ~FFTModel();
00068 
00069     inline float getMagnitudeAt(int x, int y) {
00070         return m_server->getMagnitudeAt(x << m_xshift, y << m_yshift);
00071     }
00072     inline float getNormalizedMagnitudeAt(int x, int y) {
00073         return m_server->getNormalizedMagnitudeAt(x << m_xshift, y << m_yshift);
00074     }
00075     inline float getMaximumMagnitudeAt(int x) {
00076         return m_server->getMaximumMagnitudeAt(x << m_xshift);
00077     }
00078     inline float getPhaseAt(int x, int y) {
00079         return m_server->getPhaseAt(x << m_xshift, y << m_yshift);
00080     }
00081     inline void getValuesAt(int x, int y, float &real, float &imaginary) {
00082         m_server->getValuesAt(x << m_xshift, y << m_yshift, real, imaginary);
00083     }
00084     inline bool isColumnAvailable(int x) const {
00085         return m_server->isColumnReady(x << m_xshift);
00086     }
00087 
00088     inline bool getMagnitudesAt(int x, float *values, int minbin = 0, int count = 0) {
00089         return m_server->getMagnitudesAt(x << m_xshift, values, minbin << m_yshift, count, getYRatio());
00090     }
00091     inline bool getNormalizedMagnitudesAt(int x, float *values, int minbin = 0, int count = 0) {
00092         return m_server->getNormalizedMagnitudesAt(x << m_xshift, values, minbin << m_yshift, count, getYRatio());
00093     }
00094     inline bool getPhasesAt(int x, float *values, int minbin = 0, int count = 0) {
00095         return m_server->getPhasesAt(x << m_xshift, values, minbin << m_yshift, count, getYRatio());
00096     }
00097     inline bool getValuesAt(int x, float *reals, float *imaginaries, int minbin = 0, int count = 0) {
00098         return m_server->getValuesAt(x << m_xshift, reals, imaginaries, minbin << m_yshift, count, getYRatio());
00099     }
00100 
00101     inline int getFillExtent() const { return m_server->getFillExtent(); }
00102 
00103     // DenseThreeDimensionalModel and Model methods:
00104     //
00105     inline virtual int getWidth() const {
00106         return m_server->getWidth() >> m_xshift;
00107     }
00108     inline virtual int getHeight() const {
00109         // If there is no y-shift, the server's height (based on its
00110         // fftsize/2 + 1) is correct.  If there is a shift, then the
00111         // server is using a larger fft size than we want, so we shift
00112         // it right as many times as necessary, but then we need to
00113         // re-add the "+1" part (because ((fftsize*2)/2 + 1) / 2 !=
00114         // fftsize/2 + 1).
00115         return (m_server->getHeight() >> m_yshift) + (m_yshift > 0 ? 1 : 0);
00116     }
00117     virtual float getValueAt(int x, int y) const {
00118         return const_cast<FFTModel *>(this)->getMagnitudeAt(x, y);
00119     }
00120     virtual bool isOK() const {
00121         return m_server && m_server->getModel();
00122     }
00123     virtual int getStartFrame() const {
00124         return 0;
00125     }
00126     virtual int getEndFrame() const {
00127         return getWidth() * getResolution() + getResolution();
00128     }
00129     virtual int getSampleRate() const;
00130     virtual int getResolution() const {
00131         return m_server->getWindowIncrement() << m_xshift;
00132     }
00133     virtual int getYBinCount() const {
00134         return getHeight();
00135     }
00136     virtual float getMinimumLevel() const {
00137         return 0.f; // Can't provide
00138     }
00139     virtual float getMaximumLevel() const {
00140         return 1.f; // Can't provide
00141     }
00142     virtual Column getColumn(int x) const;
00143     virtual QString getBinName(int n) const;
00144 
00145     virtual bool shouldUseLogValueScale() const {
00146         return true; // Although obviously it's up to the user...
00147     }
00148 
00154     virtual bool estimateStableFrequency(int x, int y, float &frequency);
00155 
00156     enum PeakPickType
00157     {
00158         AllPeaks,                
00159         MajorPeaks,              
00160         MajorPitchAdaptivePeaks  
00161     };
00162 
00163     typedef std::set<int> PeakLocationSet; // bin
00164     typedef std::map<int, float> PeakSet; // bin -> freq
00165 
00170     virtual PeakLocationSet getPeaks(PeakPickType type, int x,
00171                                      int ymin = 0, int ymax = 0);
00172 
00176     virtual PeakSet getPeakFrequencies(PeakPickType type, int x,
00177                                        int ymin = 0, int ymax = 0);
00178 
00179     virtual int getCompletion() const { return m_server->getFillCompletion(); }
00180     virtual QString getError() const { return m_server->getError(); }
00181 
00182     virtual Model *clone() const;
00183 
00184     virtual void suspend() { m_server->suspend(); }
00185     virtual void suspendWrites() { m_server->suspendWrites(); }
00186     virtual void resume() { m_server->resume(); }
00187 
00188     QString getTypeName() const { return tr("FFT"); }
00189 
00190 public slots:
00191     void sourceModelAboutToBeDeleted();
00192 
00193 private:
00194     FFTModel(const FFTModel &); // not implemented
00195     FFTModel &operator=(const FFTModel &); // not implemented
00196 
00197     FFTDataServer *m_server;
00198     int m_xshift;
00199     int m_yshift;
00200 
00201     FFTDataServer *getServer(const DenseTimeValueModel *,
00202                              int, WindowType, int, int, int,
00203                              bool, StorageAdviser::Criteria, int);
00204 
00205     int getPeakPickWindowSize(PeakPickType type, int sampleRate,
00206                                  int bin, float &percentile) const;
00207 
00208     int getYRatio() {
00209         int ys = m_yshift;
00210         int r = 1;
00211         while (ys) { --ys; r <<= 1; }
00212         return r;
00213     }
00214 };
00215 
00216 #endif