annotate plugins/AdaptiveSpectrogram.h @ 105:abbc482aaad2

* Switch CutThread to AsynchronousTask; introduce FFTThread as well and make the FFT calculations concurrent
author Chris Cannam <c.cannam@qmul.ac.uk>
date Tue, 12 May 2009 21:05:44 +0000
parents d8ad747eb907
children 35f2138c6891
rev   line source
c@92 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
c@92 2
c@92 3 /*
c@92 4 QM Vamp Plugin Set
c@92 5
c@92 6 Centre for Digital Music, Queen Mary, University of London.
c@92 7 All rights reserved.
c@92 8 */
c@92 9
c@92 10 #ifndef _ADAPTIVE_SPECTROGRAM_H_
c@92 11 #define _ADAPTIVE_SPECTROGRAM_H_
c@92 12
c@92 13 #include <vamp-sdk/Plugin.h>
c@92 14 #include <cmath>
c@92 15 #include <vector>
c@92 16
c@105 17 #include <dsp/transforms/FFT.h>//!!!
c@105 18
c@104 19 #include "thread/Thread.h"
c@104 20
c@92 21 class AdaptiveSpectrogram : public Vamp::Plugin
c@92 22 {
c@92 23 public:
c@92 24 AdaptiveSpectrogram(float inputSampleRate);
c@92 25 virtual ~AdaptiveSpectrogram();
c@92 26
c@92 27 bool initialise(size_t channels, size_t stepSize, size_t blockSize);
c@92 28 void reset();
c@92 29
c@92 30 InputDomain getInputDomain() const { return TimeDomain; }
c@92 31
c@92 32 std::string getIdentifier() const;
c@92 33 std::string getName() const;
c@92 34 std::string getDescription() const;
c@92 35 std::string getMaker() const;
c@92 36 int getPluginVersion() const;
c@92 37 std::string getCopyright() const;
c@92 38
c@92 39 size_t getPreferredStepSize() const;
c@92 40 size_t getPreferredBlockSize() const;
c@92 41
c@92 42 ParameterList getParameterDescriptors() const;
c@92 43 float getParameter(std::string id) const;
c@92 44 void setParameter(std::string id, float value);
c@92 45
c@92 46 OutputList getOutputDescriptors() const;
c@92 47
c@92 48 FeatureSet process(const float *const *inputBuffers,
c@92 49 Vamp::RealTime timestamp);
c@92 50
c@92 51 FeatureSet getRemainingFeatures();
c@92 52
c@92 53 protected:
c@92 54 int m_w;
c@92 55 int m_n;
c@92 56
c@100 57 struct Spectrogram
c@100 58 {
c@100 59 int resolution;
c@100 60 int width;
c@100 61 double **data;
c@100 62
c@100 63 Spectrogram(int r, int w) :
c@100 64 resolution(r), width(w) {
c@100 65 data = new double *[width];
c@100 66 for (int i = 0; i < width; ++i) data[i] = new double[resolution];
c@100 67 }
c@100 68
c@100 69 ~Spectrogram() {
c@100 70 for (int i = 0; i < width; ++i) delete[] data[i];
c@100 71 delete[] data;
c@100 72 }
c@100 73 };
c@100 74
c@100 75 struct Spectrograms
c@100 76 {
c@100 77 int minres;
c@100 78 int maxres;
c@100 79 int n;
c@100 80 Spectrogram **spectrograms;
c@100 81
c@100 82 Spectrograms(int mn, int mx, int widthofmax) :
c@100 83 minres(mn), maxres(mx) {
c@100 84 n = log2(maxres/minres) + 1;
c@100 85 spectrograms = new Spectrogram *[n];
c@100 86 int r = mn;
c@100 87 for (int i = 0; i < n; ++i) {
c@100 88 spectrograms[i] = new Spectrogram(r, widthofmax * (mx / r));
c@100 89 r = r * 2;
c@100 90 }
c@100 91 }
c@100 92 ~Spectrograms() {
c@100 93 for (int i = 0; i < n; ++i) {
c@100 94 delete spectrograms[i];
c@100 95 }
c@100 96 delete[] spectrograms;
c@100 97 }
c@100 98 };
c@100 99
c@100 100 struct Cutting
c@100 101 {
c@100 102 enum Cut { Horizontal, Vertical, Finished };
c@100 103 Cut cut;
c@100 104 Cutting *first;
c@100 105 Cutting *second;
c@100 106 double cost;
c@100 107 double value;
c@100 108
c@100 109 ~Cutting() {
c@100 110 delete first;
c@100 111 delete second;
c@100 112 }
c@100 113 };
c@100 114
c@105 115 class FFTThread : public AsynchronousTask
c@104 116 {
c@104 117 public:
c@105 118 FFTThread() { }
c@105 119 ~FFTThread() { }
c@105 120
c@105 121 void calculate(const float *timeDomain, Spectrograms &s,
c@105 122 int res, int width, int maxwidth) {
c@105 123 m_in = timeDomain;
c@105 124 m_s = &s;
c@105 125 m_res = res;
c@105 126 m_w = width;
c@105 127 m_maxwid = maxwidth;
c@105 128 startTask();
c@105 129 }
c@105 130
c@105 131 void await() {
c@105 132 awaitTask();
c@105 133 }
c@105 134
c@105 135 protected:
c@105 136 void performTask() {
c@105 137
c@105 138 double *tmpin = new double[m_w];
c@105 139 double *tmprout = new double[m_w];
c@105 140 double *tmpiout = new double[m_w];
c@105 141
c@105 142 //!!! use window object
c@105 143
c@105 144 for (int i = 0; i < m_maxwid / m_w; ++i) {
c@105 145 int origin = m_maxwid/4 - m_w/4; // for 50% overlap
c@105 146 for (int j = 0; j < m_w; ++j) {
c@105 147 double mul = 0.50 - 0.50 * cos((2 * M_PI * j) / m_w);
c@105 148 tmpin[j] = m_in[origin + i * m_w/2 + j] * mul;
c@105 149 }
c@105 150 FFT::process(m_w, false, tmpin, 0, tmprout, tmpiout);
c@105 151 for (int j = 0; j < m_w/2; ++j) {
c@105 152 int k = j+1; // include Nyquist but not DC
c@105 153 double mag = sqrt(tmprout[k] * tmprout[k] +
c@105 154 tmpiout[k] * tmpiout[k]);
c@105 155 double scaled = mag / (m_w/2);
c@105 156 m_s->spectrograms[m_res]->data[i][j] = scaled;
c@105 157 }
c@105 158 }
c@105 159
c@105 160 delete[] tmpin;
c@105 161 delete[] tmprout;
c@105 162 delete[] tmpiout;
c@105 163 }
c@105 164
c@105 165 private:
c@105 166 const float *m_in;
c@105 167 Spectrograms *m_s;
c@105 168 int m_res;
c@105 169 int m_w;
c@105 170 int m_maxwid;
c@105 171 };
c@105 172
c@105 173 std::vector<FFTThread *> m_fftThreads;
c@105 174
c@105 175 class CutThread : public AsynchronousTask
c@105 176 {
c@105 177 public:
c@105 178 CutThread(const AdaptiveSpectrogram *as) : m_as(as), m_result(0) { }
c@104 179 ~CutThread() { }
c@105 180
c@104 181 void cut(const Spectrograms &s, int res, int x, int y, int h) {
c@104 182 m_s = &s;
c@104 183 m_res = res;
c@104 184 m_x = x;
c@104 185 m_y = y;
c@104 186 m_h = h;
c@105 187 startTask();
c@104 188 }
c@104 189
c@104 190 Cutting *get() {
c@105 191 awaitTask();
c@105 192 return m_result;
c@104 193 }
c@104 194
c@104 195 protected:
c@105 196 void performTask() {
c@105 197 m_result = m_as->cut(*m_s, m_res, m_x, m_y, m_h);
c@104 198 }
c@104 199
c@105 200 private:
c@104 201 const AdaptiveSpectrogram *m_as;
c@104 202 const Spectrograms *m_s;
c@104 203 int m_res;
c@104 204 int m_x;
c@104 205 int m_y;
c@104 206 int m_h;
c@104 207 Cutting *m_result;
c@104 208 };
c@105 209
c@104 210 mutable std::vector<CutThread *> m_cutThreads;//!!! mutable blargh
c@104 211
c@104 212 ///!!! Mutex m_threadMutex;
c@104 213 mutable bool m_first; //!!! gross
c@104 214
c@104 215 double xlogx(double x) const {
c@104 216 if (x == 0.0) return 0.0;
c@104 217 else return x * log(x);
c@104 218 }
c@104 219
c@104 220 double cost(const Spectrogram &s, int x, int y) const {
c@100 221 return xlogx(s.data[x][y]);
c@100 222 }
c@100 223
c@104 224 double value(const Spectrogram &s, int x, int y) const {
c@100 225 return s.data[x][y];
c@100 226 }
c@100 227
c@104 228 Cutting *cut(const Spectrograms &, int res, int x, int y, int h) const;
c@100 229
c@104 230 void getSubCuts(const Spectrograms &, int res, int x, int y, int h,
c@104 231 Cutting *&top, Cutting *&bottom,
c@104 232 Cutting *&left, Cutting *&right) const;
c@100 233
c@104 234 void printCutting(Cutting *, std::string) const;
c@104 235
c@104 236 void assemble(const Spectrograms &, const Cutting *,
c@104 237 std::vector<std::vector<float> > &,
c@104 238 int x, int y, int w, int h) const;
c@104 239 };
c@92 240
c@92 241
c@92 242 #endif