annotate data/model/FFTModel.h @ 1346:75ad55315db4 3.0-integration

More work on getting tests (especially file encoding ones) running on Windows. Various problems here to do with interaction with test filenames in Hg repos
author Chris Cannam
date Fri, 06 Jan 2017 15:44:55 +0000
parents 54af1e21705c
children fad8f533ca13
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@1086 16 #ifndef FFT_MODEL_H
Chris@1086 17 #define FFT_MODEL_H
Chris@152 18
Chris@152 19 #include "DenseThreeDimensionalModel.h"
Chris@1090 20 #include "DenseTimeValueModel.h"
Chris@1090 21
Chris@1090 22 #include "base/Window.h"
Chris@152 23
Chris@1270 24 #include <bqfft/FFT.h>
Chris@1326 25 #include <bqvec/Allocators.h>
Chris@1091 26
Chris@275 27 #include <set>
Chris@1091 28 #include <vector>
Chris@1091 29 #include <complex>
Chris@1093 30 #include <deque>
Chris@275 31
Chris@254 32 /**
Chris@254 33 * An implementation of DenseThreeDimensionalModel that makes FFT data
Chris@387 34 * derived from a DenseTimeValueModel available as a generic data
Chris@1090 35 * grid.
Chris@254 36 */
Chris@152 37 class FFTModel : public DenseThreeDimensionalModel
Chris@152 38 {
Chris@247 39 Q_OBJECT
Chris@247 40
Chris@1092 41 //!!! threading requirements?
Chris@1092 42 //!!! doubles? since we're not caching much
Chris@1092 43
Chris@152 44 public:
Chris@254 45 /**
Chris@254 46 * Construct an FFT model derived from the given
Chris@254 47 * DenseTimeValueModel, with the given window parameters and FFT
Chris@254 48 * size (which may exceed the window size, for zero-padded FFTs).
Chris@254 49 *
Chris@254 50 * If the model has multiple channels use only the given channel,
Chris@254 51 * unless the channel is -1 in which case merge all available
Chris@254 52 * channels.
Chris@254 53 */
Chris@152 54 FFTModel(const DenseTimeValueModel *model,
Chris@152 55 int channel,
Chris@152 56 WindowType windowType,
Chris@929 57 int windowSize,
Chris@929 58 int windowIncrement,
Chris@1090 59 int fftSize);
Chris@152 60 ~FFTModel();
Chris@152 61
Chris@152 62 // DenseThreeDimensionalModel and Model methods:
Chris@152 63 //
Chris@1090 64 virtual int getWidth() const;
Chris@1090 65 virtual int getHeight() const;
Chris@1090 66 virtual float getValueAt(int x, int y) const { return getMagnitudeAt(x, y); }
Chris@1090 67 virtual bool isOK() const { return m_model && m_model->isOK(); }
Chris@1090 68 virtual sv_frame_t getStartFrame() const { return 0; }
Chris@1038 69 virtual sv_frame_t getEndFrame() const {
Chris@1038 70 return sv_frame_t(getWidth()) * getResolution() + getResolution();
Chris@152 71 }
Chris@1090 72 virtual sv_samplerate_t getSampleRate() const {
Chris@1090 73 return isOK() ? m_model->getSampleRate() : 0;
Chris@152 74 }
Chris@1090 75 virtual int getResolution() const { return m_windowIncrement; }
Chris@1090 76 virtual int getYBinCount() const { return getHeight(); }
Chris@1090 77 virtual float getMinimumLevel() const { return 0.f; } // Can't provide
Chris@1090 78 virtual float getMaximumLevel() const { return 1.f; } // Can't provide
Chris@1090 79 virtual Column getColumn(int x) const; // magnitudes
Chris@1200 80 virtual Column getPhases(int x) const;
Chris@1090 81 virtual QString getBinName(int n) const;
Chris@1090 82 virtual bool shouldUseLogValueScale() const { return true; }
Chris@1090 83 virtual int getCompletion() const {
Chris@1090 84 int c = 100;
Chris@1093 85 if (m_model) {
Chris@1093 86 if (m_model->isReady(&c)) return 100;
Chris@1093 87 }
Chris@1090 88 return c;
Chris@152 89 }
Chris@1090 90 virtual QString getError() const { return ""; } //!!!???
Chris@1090 91 virtual sv_frame_t getFillExtent() const { return getEndFrame(); }
Chris@152 92
Chris@1090 93 // FFTModel methods:
Chris@1090 94 //
Chris@1090 95 int getChannel() const { return m_channel; }
Chris@1090 96 WindowType getWindowType() const { return m_windowType; }
Chris@1090 97 int getWindowSize() const { return m_windowSize; }
Chris@1090 98 int getWindowIncrement() const { return m_windowIncrement; }
Chris@1090 99 int getFFTSize() const { return m_fftSize; }
Chris@1200 100
Chris@1200 101 //!!! review which of these are ever actually called
Chris@1090 102
Chris@1090 103 float getMagnitudeAt(int x, int y) const;
Chris@1090 104 float getMaximumMagnitudeAt(int x) const;
Chris@1090 105 float getPhaseAt(int x, int y) const;
Chris@1090 106 void getValuesAt(int x, int y, float &real, float &imaginary) const;
Chris@1090 107 bool getMagnitudesAt(int x, float *values, int minbin = 0, int count = 0) const;
Chris@1090 108 bool getPhasesAt(int x, float *values, int minbin = 0, int count = 0) const;
Chris@1090 109 bool getValuesAt(int x, float *reals, float *imaginaries, int minbin = 0, int count = 0) const;
Chris@478 110
Chris@275 111 /**
Chris@275 112 * Calculate an estimated frequency for a stable signal in this
Chris@275 113 * bin, using phase unwrapping. This will be completely wrong if
Chris@275 114 * the signal is not stable here.
Chris@275 115 */
Chris@1045 116 virtual bool estimateStableFrequency(int x, int y, double &frequency);
Chris@275 117
Chris@275 118 enum PeakPickType
Chris@275 119 {
Chris@275 120 AllPeaks, /// Any bin exceeding its immediate neighbours
Chris@275 121 MajorPeaks, /// Peaks picked using sliding median window
Chris@275 122 MajorPitchAdaptivePeaks /// Bigger window for higher frequencies
Chris@275 123 };
Chris@275 124
Chris@929 125 typedef std::set<int> PeakLocationSet; // bin
Chris@1045 126 typedef std::map<int, double> PeakSet; // bin -> freq
Chris@275 127
Chris@275 128 /**
Chris@275 129 * Return locations of peak bins in the range [ymin,ymax]. If
Chris@275 130 * ymax is zero, getHeight()-1 will be used.
Chris@275 131 */
Chris@929 132 virtual PeakLocationSet getPeaks(PeakPickType type, int x,
Chris@1191 133 int ymin = 0, int ymax = 0) const;
Chris@275 134
Chris@275 135 /**
Chris@275 136 * Return locations and estimated stable frequencies of peak bins.
Chris@275 137 */
Chris@929 138 virtual PeakSet getPeakFrequencies(PeakPickType type, int x,
Chris@1191 139 int ymin = 0, int ymax = 0) const;
Chris@273 140
Chris@345 141 QString getTypeName() const { return tr("FFT"); }
Chris@345 142
Chris@360 143 public slots:
Chris@360 144 void sourceModelAboutToBeDeleted();
Chris@360 145
Chris@152 146 private:
Chris@297 147 FFTModel(const FFTModel &); // not implemented
Chris@152 148 FFTModel &operator=(const FFTModel &); // not implemented
Chris@152 149
Chris@1090 150 const DenseTimeValueModel *m_model;
Chris@1090 151 int m_channel;
Chris@1090 152 WindowType m_windowType;
Chris@1090 153 int m_windowSize;
Chris@1090 154 int m_windowIncrement;
Chris@1090 155 int m_fftSize;
Chris@1090 156 Window<float> m_windower;
Chris@1270 157 mutable breakfastquay::FFT m_fft;
Chris@1090 158
Chris@1040 159 int getPeakPickWindowSize(PeakPickType type, sv_samplerate_t sampleRate,
Chris@1040 160 int bin, float &percentile) const;
Chris@1091 161
Chris@1091 162 std::pair<sv_frame_t, sv_frame_t> getSourceSampleRange(int column) const {
Chris@1091 163 sv_frame_t startFrame = m_windowIncrement * sv_frame_t(column);
Chris@1091 164 sv_frame_t endFrame = startFrame + m_windowSize;
Chris@1091 165 // Cols are centred on the audio sample (e.g. col 0 is centred at sample 0)
Chris@1091 166 startFrame -= m_windowSize / 2;
Chris@1091 167 endFrame -= m_windowSize / 2;
Chris@1091 168 return { startFrame, endFrame };
Chris@1091 169 }
Chris@1091 170
Chris@1326 171 typedef std::vector<float, breakfastquay::StlAllocator<float>> fvec;
Chris@1326 172 typedef std::vector<std::complex<float>,
Chris@1326 173 breakfastquay::StlAllocator<std::complex<float>>> cvec;
Chris@1326 174
Chris@1326 175 cvec getFFTColumn(int column) const;
Chris@1326 176 fvec getSourceSamples(int column) const;
Chris@1326 177 fvec getSourceData(std::pair<sv_frame_t, sv_frame_t>) const;
Chris@1326 178 fvec getSourceDataUncached(std::pair<sv_frame_t, sv_frame_t>) const;
Chris@1093 179
Chris@1094 180 struct SavedSourceData {
Chris@1094 181 std::pair<sv_frame_t, sv_frame_t> range;
Chris@1326 182 fvec data;
Chris@1094 183 };
Chris@1094 184 mutable SavedSourceData m_savedData;
Chris@1094 185
Chris@1093 186 struct SavedColumn {
Chris@1093 187 int n;
Chris@1326 188 cvec col;
Chris@1093 189 };
Chris@1093 190 mutable std::deque<SavedColumn> m_cached;
Chris@1093 191 size_t m_cacheSize;
Chris@152 192 };
Chris@152 193
Chris@152 194 #endif