annotate plugins/AdaptiveSpectrogram.h @ 104:d8ad747eb907

* first crack at threading cut code
author Chris Cannam <c.cannam@qmul.ac.uk>
date Tue, 12 May 2009 17:57:41 +0000
parents ef22bed1626a
children abbc482aaad2
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@104 17 #include "thread/Thread.h"
c@104 18
c@92 19 class AdaptiveSpectrogram : public Vamp::Plugin
c@92 20 {
c@92 21 public:
c@92 22 AdaptiveSpectrogram(float inputSampleRate);
c@92 23 virtual ~AdaptiveSpectrogram();
c@92 24
c@92 25 bool initialise(size_t channels, size_t stepSize, size_t blockSize);
c@92 26 void reset();
c@92 27
c@92 28 InputDomain getInputDomain() const { return TimeDomain; }
c@92 29
c@92 30 std::string getIdentifier() const;
c@92 31 std::string getName() const;
c@92 32 std::string getDescription() const;
c@92 33 std::string getMaker() const;
c@92 34 int getPluginVersion() const;
c@92 35 std::string getCopyright() const;
c@92 36
c@92 37 size_t getPreferredStepSize() const;
c@92 38 size_t getPreferredBlockSize() const;
c@92 39
c@92 40 ParameterList getParameterDescriptors() const;
c@92 41 float getParameter(std::string id) const;
c@92 42 void setParameter(std::string id, float value);
c@92 43
c@92 44 OutputList getOutputDescriptors() const;
c@92 45
c@92 46 FeatureSet process(const float *const *inputBuffers,
c@92 47 Vamp::RealTime timestamp);
c@92 48
c@92 49 FeatureSet getRemainingFeatures();
c@92 50
c@92 51 protected:
c@92 52 int m_w;
c@92 53 int m_n;
c@92 54
c@100 55 struct Spectrogram
c@100 56 {
c@100 57 int resolution;
c@100 58 int width;
c@100 59 double **data;
c@100 60
c@100 61 Spectrogram(int r, int w) :
c@100 62 resolution(r), width(w) {
c@100 63 data = new double *[width];
c@100 64 for (int i = 0; i < width; ++i) data[i] = new double[resolution];
c@100 65 }
c@100 66
c@100 67 ~Spectrogram() {
c@100 68 for (int i = 0; i < width; ++i) delete[] data[i];
c@100 69 delete[] data;
c@100 70 }
c@100 71 };
c@100 72
c@100 73 struct Spectrograms
c@100 74 {
c@100 75 int minres;
c@100 76 int maxres;
c@100 77 int n;
c@100 78 Spectrogram **spectrograms;
c@100 79
c@100 80 Spectrograms(int mn, int mx, int widthofmax) :
c@100 81 minres(mn), maxres(mx) {
c@100 82 n = log2(maxres/minres) + 1;
c@100 83 spectrograms = new Spectrogram *[n];
c@100 84 int r = mn;
c@100 85 for (int i = 0; i < n; ++i) {
c@100 86 spectrograms[i] = new Spectrogram(r, widthofmax * (mx / r));
c@100 87 r = r * 2;
c@100 88 }
c@100 89 }
c@100 90 ~Spectrograms() {
c@100 91 for (int i = 0; i < n; ++i) {
c@100 92 delete spectrograms[i];
c@100 93 }
c@100 94 delete[] spectrograms;
c@100 95 }
c@100 96 };
c@100 97
c@100 98 struct Cutting
c@100 99 {
c@100 100 enum Cut { Horizontal, Vertical, Finished };
c@100 101 Cut cut;
c@100 102 Cutting *first;
c@100 103 Cutting *second;
c@100 104 double cost;
c@100 105 double value;
c@100 106
c@100 107 ~Cutting() {
c@100 108 delete first;
c@100 109 delete second;
c@100 110 }
c@100 111 };
c@100 112
c@104 113 class CutThread : public Thread
c@104 114 {
c@104 115 public:
c@104 116 CutThread(const AdaptiveSpectrogram *as) :
c@104 117 m_as(as),
c@104 118 // m_busy(false),
c@104 119 // m_computed(false),
c@104 120 m_result(0),
c@104 121 m_workToDoC("CutThread: work to do"),
c@104 122 m_workToDo(false),
c@104 123 m_workDoneC("CutThread: work done"),
c@104 124 m_workDone(false),
c@104 125 m_finishing(false)
c@104 126 { }
c@104 127 ~CutThread() { }
c@104 128
c@104 129 void cut(const Spectrograms &s, int res, int x, int y, int h) {
c@104 130 m_workToDoC.lock();
c@104 131 // std::cerr << "locked in main thread" << std::endl;
c@104 132 m_s = &s;
c@104 133 m_res = res;
c@104 134 m_x = x;
c@104 135 m_y = y;
c@104 136 m_h = h;
c@104 137 // m_busy = true;
c@104 138 // m_computed = false;
c@104 139 m_workToDo = true;
c@104 140 m_workDone = false;
c@104 141 m_workToDoC.signal();
c@104 142 m_workDoneC.lock();
c@104 143 m_workToDoC.unlock();
c@104 144 }
c@104 145
c@104 146 Cutting *get() {
c@104 147 // std::cerr << "about to wait within main thread" << std::endl;
c@104 148 // m_workDoneC must be locked from prior call to cut()
c@104 149 while (!m_workDone) m_workDoneC.wait();
c@104 150 // std::cerr << "waited within main thread" << std::endl;
c@104 151 // m_workDoneC.lock();
c@104 152 // while (!m_computed) {
c@104 153 // std::cerr << "waiting within main thread" << std::endl;
c@104 154 // m_condition.wait();
c@104 155 // }
c@104 156 Cutting *c = m_result;
c@104 157 m_result = 0;
c@104 158 m_workDoneC.unlock();
c@104 159 return c;
c@104 160 }
c@104 161 /*
c@104 162 bool busy() {
c@104 163 return m_busy;
c@104 164 }
c@104 165 */
c@104 166 void finish() {
c@104 167 m_finishing = true;
c@104 168 m_workToDoC.signal();
c@104 169 }
c@104 170
c@104 171 protected:
c@104 172 virtual void run() {
c@104 173 m_workToDoC.lock();
c@104 174 // std::cerr << "locked within run function" << std::endl;
c@104 175 while (!m_finishing) {
c@104 176 // if (!m_busy) {
c@104 177 // std::cerr << "waiting within run function" << std::endl;
c@104 178 // m_condition.wait();
c@104 179 // }
c@104 180 while (!m_workToDo && !m_finishing) m_workToDoC.wait();
c@104 181 // std::cerr << "waited within run function" << std::endl;
c@104 182 if (m_finishing) {
c@104 183 break;
c@104 184 }
c@104 185 if (m_workToDo) {
c@104 186 // std::cerr << "cut thread " << this << ": calling cut" << std::endl;
c@104 187 m_result = m_as->cut(*m_s, m_res, m_x, m_y, m_h);
c@104 188 // std::cerr << "cut returning" << std::endl;
c@104 189 // m_computed = true;
c@104 190 // m_busy = false;
c@104 191 m_workToDo = false;
c@104 192 m_workDone = true;
c@104 193 // std::cerr << "signalling completion from run function" << std::endl;
c@104 194 m_workDoneC.signal();
c@104 195 }
c@104 196 }
c@104 197 m_workToDoC.unlock();
c@104 198 }
c@104 199
c@104 200 const AdaptiveSpectrogram *m_as;
c@104 201 const Spectrograms *m_s;
c@104 202 int m_res;
c@104 203 int m_x;
c@104 204 int m_y;
c@104 205 int m_h;
c@104 206 // bool m_busy;
c@104 207 // bool m_computed;
c@104 208 Cutting *m_result;
c@104 209 Condition m_workToDoC;
c@104 210 bool m_workToDo;
c@104 211 Condition m_workDoneC;
c@104 212 bool m_workDone;
c@104 213 bool m_finishing;
c@104 214 };
c@104 215 mutable std::vector<CutThread *> m_cutThreads;//!!! mutable blargh
c@104 216
c@104 217 ///!!! Mutex m_threadMutex;
c@104 218 mutable bool m_first; //!!! gross
c@104 219
c@104 220 double xlogx(double x) const {
c@104 221 if (x == 0.0) return 0.0;
c@104 222 else return x * log(x);
c@104 223 }
c@104 224
c@104 225 double cost(const Spectrogram &s, int x, int y) const {
c@100 226 return xlogx(s.data[x][y]);
c@100 227 }
c@100 228
c@104 229 double value(const Spectrogram &s, int x, int y) const {
c@100 230 return s.data[x][y];
c@100 231 }
c@100 232
c@104 233 Cutting *cut(const Spectrograms &, int res, int x, int y, int h) const;
c@100 234
c@104 235 void getSubCuts(const Spectrograms &, int res, int x, int y, int h,
c@104 236 Cutting *&top, Cutting *&bottom,
c@104 237 Cutting *&left, Cutting *&right) const;
c@100 238
c@104 239 void printCutting(Cutting *, std::string) const;
c@104 240
c@104 241 void assemble(const Spectrograms &, const Cutting *,
c@104 242 std::vector<std::vector<float> > &,
c@104 243 int x, int y, int w, int h) const;
c@104 244 };
c@92 245
c@92 246
c@92 247 #endif