annotate data/model/FFTModel.h @ 1878:231c6bcf0fa2

Comment only
author Chris Cannam
date Thu, 25 Jun 2020 09:30:17 +0100
parents 1b688ab5f1b3
children
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@275 30
Chris@254 31 /**
Chris@254 32 * An implementation of DenseThreeDimensionalModel that makes FFT data
Chris@387 33 * derived from a DenseTimeValueModel available as a generic data
Chris@1090 34 * grid.
Chris@254 35 */
Chris@152 36 class FFTModel : public DenseThreeDimensionalModel
Chris@152 37 {
Chris@247 38 Q_OBJECT
Chris@247 39
Chris@1092 40 //!!! threading requirements?
Chris@1092 41 //!!! doubles? since we're not caching much
Chris@1092 42
Chris@152 43 public:
Chris@254 44 /**
Chris@254 45 * Construct an FFT model derived from the given
Chris@254 46 * DenseTimeValueModel, with the given window parameters and FFT
Chris@254 47 * size (which may exceed the window size, for zero-padded FFTs).
Chris@254 48 *
Chris@254 49 * If the model has multiple channels use only the given channel,
Chris@254 50 * unless the channel is -1 in which case merge all available
Chris@254 51 * channels.
Chris@254 52 */
Chris@1744 53 FFTModel(ModelId model, // a DenseTimeValueModel
Chris@152 54 int channel,
Chris@152 55 WindowType windowType,
Chris@929 56 int windowSize,
Chris@929 57 int windowIncrement,
Chris@1090 58 int fftSize);
Chris@152 59 ~FFTModel();
Chris@152 60
Chris@152 61 // DenseThreeDimensionalModel and Model methods:
Chris@152 62 //
Chris@1790 63 bool isOK() const override;
Chris@1790 64 int getCompletion() const override;
Chris@1790 65
Chris@1580 66 int getWidth() const override;
Chris@1580 67 int getHeight() const override;
Chris@1790 68
Chris@1790 69 float getValueAt(int x, int y) const override {
Chris@1790 70 return getMagnitudeAt(x, y);
Chris@1790 71 }
Chris@1790 72 sv_frame_t getStartFrame() const override {
Chris@1790 73 return 0;
Chris@1790 74 }
Chris@1725 75 sv_frame_t getTrueEndFrame() const override {
Chris@1038 76 return sv_frame_t(getWidth()) * getResolution() + getResolution();
Chris@152 77 }
Chris@1790 78 sv_samplerate_t getSampleRate() const override {
Chris@1790 79 return m_sampleRate;
Chris@1790 80 }
Chris@1790 81 int getResolution() const override {
Chris@1790 82 return m_windowIncrement;
Chris@1790 83 }
Chris@1790 84
Chris@1580 85 float getMinimumLevel() const override { return 0.f; } // Can't provide
Chris@1580 86 float getMaximumLevel() const override { return 1.f; } // Can't provide
Chris@1790 87
Chris@1580 88 Column getColumn(int x) const override; // magnitudes
Chris@1790 89
Chris@1790 90 bool hasBinValues() const override {
Chris@1790 91 return true;
Chris@1790 92 }
Chris@1790 93 QString getBinValueUnit() const override {
Chris@1790 94 return "Hz";
Chris@1790 95 }
Chris@1790 96 bool shouldUseLogValueScale() const override {
Chris@1790 97 return true;
Chris@1790 98 }
Chris@1790 99 float getBinValue(int n) const override;
Chris@1580 100 QString getBinName(int n) const override;
Chris@1790 101
Chris@1833 102 QVector<QString>
Chris@1833 103 getStringExportHeaders(DataExportOptions) const override {
Chris@1833 104 return {};
Chris@1815 105 }
Chris@1833 106
Chris@1833 107 QVector<QVector<QString>>
Chris@1833 108 toStringExportRows(DataExportOptions, sv_frame_t, sv_frame_t) const override {
Chris@1833 109 return {};
Chris@1679 110 }
Chris@152 111
Chris@1090 112 // FFTModel methods:
Chris@1090 113 //
Chris@1790 114 QString getError() const { return m_error; }
Chris@1790 115
Chris@1090 116 int getChannel() const { return m_channel; }
Chris@1090 117 WindowType getWindowType() const { return m_windowType; }
Chris@1090 118 int getWindowSize() const { return m_windowSize; }
Chris@1090 119 int getWindowIncrement() const { return m_windowIncrement; }
Chris@1090 120 int getFFTSize() const { return m_fftSize; }
Chris@1200 121
Chris@1780 122 void setMaximumFrequency(double freq);
Chris@1780 123 double getMaximumFrequency() const { return m_maximumFrequency; }
Chris@1780 124
Chris@1200 125 //!!! review which of these are ever actually called
Chris@1090 126
Chris@1090 127 float getMagnitudeAt(int x, int y) const;
Chris@1090 128 float getMaximumMagnitudeAt(int x) const;
Chris@1790 129 Column getPhases(int x) const;
Chris@1090 130 float getPhaseAt(int x, int y) const;
Chris@1090 131 void getValuesAt(int x, int y, float &real, float &imaginary) const;
Chris@1090 132 bool getMagnitudesAt(int x, float *values, int minbin = 0, int count = 0) const;
Chris@1090 133 bool getPhasesAt(int x, float *values, int minbin = 0, int count = 0) const;
Chris@1090 134 bool getValuesAt(int x, float *reals, float *imaginaries, int minbin = 0, int count = 0) const;
Chris@478 135
Chris@275 136 /**
Chris@275 137 * Calculate an estimated frequency for a stable signal in this
Chris@275 138 * bin, using phase unwrapping. This will be completely wrong if
Chris@275 139 * the signal is not stable here.
Chris@275 140 */
Chris@1045 141 virtual bool estimateStableFrequency(int x, int y, double &frequency);
Chris@275 142
Chris@275 143 enum PeakPickType
Chris@275 144 {
Chris@275 145 AllPeaks, /// Any bin exceeding its immediate neighbours
Chris@275 146 MajorPeaks, /// Peaks picked using sliding median window
Chris@275 147 MajorPitchAdaptivePeaks /// Bigger window for higher frequencies
Chris@275 148 };
Chris@275 149
Chris@929 150 typedef std::set<int> PeakLocationSet; // bin
Chris@1045 151 typedef std::map<int, double> PeakSet; // bin -> freq
Chris@275 152
Chris@275 153 /**
Chris@275 154 * Return locations of peak bins in the range [ymin,ymax]. If
Chris@275 155 * ymax is zero, getHeight()-1 will be used.
Chris@275 156 */
Chris@929 157 virtual PeakLocationSet getPeaks(PeakPickType type, int x,
Chris@1191 158 int ymin = 0, int ymax = 0) const;
Chris@275 159
Chris@275 160 /**
Chris@275 161 * Return locations and estimated stable frequencies of peak bins.
Chris@275 162 */
Chris@929 163 virtual PeakSet getPeakFrequencies(PeakPickType type, int x,
Chris@1191 164 int ymin = 0, int ymax = 0) const;
Chris@273 165
Chris@1580 166 QString getTypeName() const override { return tr("FFT"); }
Chris@345 167
Chris@1744 168 private:
Chris@1744 169 FFTModel(const FFTModel &) =delete;
Chris@1744 170 FFTModel &operator=(const FFTModel &) =delete;
Chris@360 171
Chris@1744 172 const ModelId m_model; // a DenseTimeValueModel
Chris@1780 173 sv_samplerate_t m_sampleRate;
Chris@1090 174 int m_channel;
Chris@1090 175 WindowType m_windowType;
Chris@1090 176 int m_windowSize;
Chris@1090 177 int m_windowIncrement;
Chris@1090 178 int m_fftSize;
Chris@1090 179 Window<float> m_windower;
Chris@1270 180 mutable breakfastquay::FFT m_fft;
Chris@1780 181 double m_maximumFrequency;
Chris@1784 182 mutable QString m_error;
Chris@1090 183
Chris@1040 184 int getPeakPickWindowSize(PeakPickType type, sv_samplerate_t sampleRate,
Chris@1576 185 int bin, double &dist) const;
Chris@1091 186
Chris@1091 187 std::pair<sv_frame_t, sv_frame_t> getSourceSampleRange(int column) const {
Chris@1091 188 sv_frame_t startFrame = m_windowIncrement * sv_frame_t(column);
Chris@1091 189 sv_frame_t endFrame = startFrame + m_windowSize;
Chris@1091 190 // Cols are centred on the audio sample (e.g. col 0 is centred at sample 0)
Chris@1091 191 startFrame -= m_windowSize / 2;
Chris@1091 192 endFrame -= m_windowSize / 2;
Chris@1091 193 return { startFrame, endFrame };
Chris@1091 194 }
Chris@1091 195
Chris@1837 196 const complexvec_t &getFFTColumn(int column) const;
Chris@1837 197 floatvec_t getSourceSamples(int column) const;
Chris@1837 198 floatvec_t getSourceData(std::pair<sv_frame_t, sv_frame_t>) const;
Chris@1837 199 floatvec_t getSourceDataUncached(std::pair<sv_frame_t, sv_frame_t>) const;
Chris@1093 200
Chris@1094 201 struct SavedSourceData {
Chris@1094 202 std::pair<sv_frame_t, sv_frame_t> range;
Chris@1837 203 floatvec_t data;
Chris@1094 204 };
Chris@1094 205 mutable SavedSourceData m_savedData;
Chris@1371 206
Chris@1093 207 struct SavedColumn {
Chris@1093 208 int n;
Chris@1837 209 complexvec_t col;
Chris@1093 210 };
Chris@1371 211 mutable std::vector<SavedColumn> m_cached;
Chris@1371 212 mutable size_t m_cacheWriteIndex;
Chris@1093 213 size_t m_cacheSize;
Chris@1837 214
Chris@1837 215 void clearCaches();
Chris@152 216 };
Chris@152 217
Chris@152 218 #endif