annotate data/model/FFTModel.h @ 360:ac300d385ab2

* Various fixes to object lifetime management, particularly in the spectrum layer and for notification of main model deletion. The main purpose of this is to improve the behaviour of the spectrum, but I think it may also help with #1840922 Various crashes in Layer Summary window.
author Chris Cannam
date Wed, 23 Jan 2008 15:43:27 +0000
parents 700cd3350391
children 7aa1de571880
rev   line source
Chris@152 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@152 2
Chris@152 3 /*
Chris@152 4 Sonic Visualiser
Chris@152 5 An audio file viewer and annotation editor.
Chris@152 6 Centre for Digital Music, Queen Mary, University of London.
Chris@152 7 This file copyright 2006 Chris Cannam.
Chris@152 8
Chris@152 9 This program is free software; you can redistribute it and/or
Chris@152 10 modify it under the terms of the GNU General Public License as
Chris@152 11 published by the Free Software Foundation; either version 2 of the
Chris@152 12 License, or (at your option) any later version. See the file
Chris@152 13 COPYING included with this distribution for more information.
Chris@152 14 */
Chris@152 15
Chris@152 16 #ifndef _FFT_MODEL_H_
Chris@152 17 #define _FFT_MODEL_H_
Chris@152 18
Chris@152 19 #include "data/fft/FFTDataServer.h"
Chris@152 20 #include "DenseThreeDimensionalModel.h"
Chris@152 21
Chris@275 22 #include <set>
Chris@275 23 #include <map>
Chris@275 24
Chris@254 25 /**
Chris@254 26 * An implementation of DenseThreeDimensionalModel that makes FFT data
Chris@254 27 * derived from a DenseTimeValueModel available as a generic data grid.
Chris@254 28 * The FFT data is acquired using FFTDataServer.
Chris@254 29 */
Chris@254 30
Chris@152 31 class FFTModel : public DenseThreeDimensionalModel
Chris@152 32 {
Chris@247 33 Q_OBJECT
Chris@247 34
Chris@152 35 public:
Chris@254 36 /**
Chris@254 37 * Construct an FFT model derived from the given
Chris@254 38 * DenseTimeValueModel, with the given window parameters and FFT
Chris@254 39 * size (which may exceed the window size, for zero-padded FFTs).
Chris@254 40 *
Chris@254 41 * If the model has multiple channels use only the given channel,
Chris@254 42 * unless the channel is -1 in which case merge all available
Chris@254 43 * channels.
Chris@254 44 *
Chris@254 45 * If polar is true, the data will normally be retrieved from the
Chris@254 46 * FFT model in magnitude/phase form; otherwise it will normally
Chris@254 47 * be retrieved in "cartesian" real/imaginary form. The results
Chris@254 48 * should be the same either way, but a "polar" model addressed in
Chris@254 49 * "cartesian" form or vice versa may suffer a performance
Chris@254 50 * penalty.
Chris@254 51 *
Chris@254 52 * The fillFromColumn argument gives a hint that the FFT data
Chris@254 53 * server should aim to start calculating FFT data at that column
Chris@254 54 * number if possible, as that is likely to be requested first.
Chris@254 55 */
Chris@152 56 FFTModel(const DenseTimeValueModel *model,
Chris@152 57 int channel,
Chris@152 58 WindowType windowType,
Chris@152 59 size_t windowSize,
Chris@152 60 size_t windowIncrement,
Chris@152 61 size_t fftSize,
Chris@152 62 bool polar,
Chris@334 63 StorageAdviser::Criteria criteria = StorageAdviser::NoCriteria,
Chris@152 64 size_t fillFromColumn = 0);
Chris@152 65 ~FFTModel();
Chris@152 66
Chris@152 67 float getMagnitudeAt(size_t x, size_t y) {
Chris@152 68 return m_server->getMagnitudeAt(x << m_xshift, y << m_yshift);
Chris@152 69 }
Chris@152 70 float getNormalizedMagnitudeAt(size_t x, size_t y) {
Chris@152 71 return m_server->getNormalizedMagnitudeAt(x << m_xshift, y << m_yshift);
Chris@152 72 }
Chris@152 73 float getMaximumMagnitudeAt(size_t x) {
Chris@152 74 return m_server->getMaximumMagnitudeAt(x << m_xshift);
Chris@152 75 }
Chris@152 76 float getPhaseAt(size_t x, size_t y) {
Chris@152 77 return m_server->getPhaseAt(x << m_xshift, y << m_yshift);
Chris@152 78 }
Chris@152 79 void getValuesAt(size_t x, size_t y, float &real, float &imaginary) {
Chris@152 80 m_server->getValuesAt(x << m_xshift, y << m_yshift, real, imaginary);
Chris@152 81 }
Chris@182 82 bool isColumnAvailable(size_t x) const {
Chris@152 83 return m_server->isColumnReady(x << m_xshift);
Chris@152 84 }
Chris@152 85
Chris@152 86 size_t getFillExtent() const { return m_server->getFillExtent(); }
Chris@152 87
Chris@152 88 // DenseThreeDimensionalModel and Model methods:
Chris@152 89 //
Chris@182 90 virtual size_t getWidth() const {
Chris@182 91 return m_server->getWidth() >> m_xshift;
Chris@182 92 }
Chris@182 93 virtual size_t getHeight() const {
Chris@212 94 // If there is no y-shift, the server's height (based on its
Chris@212 95 // fftsize/2 + 1) is correct. If there is a shift, then the
Chris@212 96 // server is using a larger fft size than we want, so we shift
Chris@212 97 // it right as many times as necessary, but then we need to
Chris@212 98 // re-add the "+1" part (because ((fftsize*2)/2 + 1) / 2 !=
Chris@212 99 // fftsize/2 + 1).
Chris@212 100 return (m_server->getHeight() >> m_yshift) + (m_yshift > 0 ? 1 : 0);
Chris@182 101 }
Chris@182 102 virtual float getValueAt(size_t x, size_t y) const {
Chris@182 103 return const_cast<FFTModel *>(this)->getMagnitudeAt(x, y);
Chris@182 104 }
Chris@152 105 virtual bool isOK() const {
Chris@152 106 return m_server && m_server->getModel();
Chris@152 107 }
Chris@152 108 virtual size_t getStartFrame() const {
Chris@152 109 return 0;
Chris@152 110 }
Chris@152 111 virtual size_t getEndFrame() const {
Chris@152 112 return getWidth() * getResolution() + getResolution();
Chris@152 113 }
Chris@152 114 virtual size_t getSampleRate() const;
Chris@152 115 virtual size_t getResolution() const {
Chris@152 116 return m_server->getWindowIncrement() << m_xshift;
Chris@152 117 }
Chris@152 118 virtual size_t getYBinCount() const {
Chris@152 119 return getHeight();
Chris@152 120 }
Chris@152 121 virtual float getMinimumLevel() const {
Chris@152 122 return 0.f; // Can't provide
Chris@152 123 }
Chris@152 124 virtual float getMaximumLevel() const {
Chris@152 125 return 1.f; // Can't provide
Chris@152 126 }
Chris@182 127 virtual void getColumn(size_t x, Column &result) const;
Chris@152 128 virtual QString getBinName(size_t n) const;
Chris@152 129
Chris@275 130 /**
Chris@275 131 * Calculate an estimated frequency for a stable signal in this
Chris@275 132 * bin, using phase unwrapping. This will be completely wrong if
Chris@275 133 * the signal is not stable here.
Chris@275 134 */
Chris@275 135 virtual bool estimateStableFrequency(size_t x, size_t y, float &frequency);
Chris@275 136
Chris@275 137 enum PeakPickType
Chris@275 138 {
Chris@275 139 AllPeaks, /// Any bin exceeding its immediate neighbours
Chris@275 140 MajorPeaks, /// Peaks picked using sliding median window
Chris@275 141 MajorPitchAdaptivePeaks /// Bigger window for higher frequencies
Chris@275 142 };
Chris@275 143
Chris@275 144 typedef std::set<size_t> PeakLocationSet;
Chris@275 145 typedef std::map<size_t, float> PeakSet;
Chris@275 146
Chris@275 147 /**
Chris@275 148 * Return locations of peak bins in the range [ymin,ymax]. If
Chris@275 149 * ymax is zero, getHeight()-1 will be used.
Chris@275 150 */
Chris@275 151 virtual PeakLocationSet getPeaks(PeakPickType type, size_t x,
Chris@275 152 size_t ymin = 0, size_t ymax = 0);
Chris@275 153
Chris@275 154 /**
Chris@275 155 * Return locations and estimated stable frequencies of peak bins.
Chris@275 156 */
Chris@275 157 virtual PeakSet getPeakFrequencies(PeakPickType type, size_t x,
Chris@275 158 size_t ymin = 0, size_t ymax = 0);
Chris@273 159
Chris@152 160 virtual int getCompletion() const { return m_server->getFillCompletion(); }
Chris@152 161
Chris@152 162 virtual Model *clone() const;
Chris@152 163
Chris@154 164 virtual void suspend() { m_server->suspend(); }
Chris@155 165 virtual void suspendWrites() { m_server->suspendWrites(); }
Chris@154 166 virtual void resume() { m_server->resume(); }
Chris@154 167
Chris@345 168 QString getTypeName() const { return tr("FFT"); }
Chris@345 169
Chris@360 170 public slots:
Chris@360 171 void sourceModelAboutToBeDeleted();
Chris@360 172
Chris@152 173 private:
Chris@297 174 FFTModel(const FFTModel &); // not implemented
Chris@152 175 FFTModel &operator=(const FFTModel &); // not implemented
Chris@152 176
Chris@152 177 FFTDataServer *m_server;
Chris@152 178 int m_xshift;
Chris@152 179 int m_yshift;
Chris@275 180
Chris@297 181 FFTDataServer *getServer(const DenseTimeValueModel *,
Chris@297 182 int, WindowType, size_t, size_t, size_t,
Chris@334 183 bool, StorageAdviser::Criteria, size_t);
Chris@297 184
Chris@280 185 size_t getPeakPickWindowSize(PeakPickType type, size_t sampleRate,
Chris@280 186 size_t bin, float &percentile) const;
Chris@152 187 };
Chris@152 188
Chris@152 189 #endif