comparison 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
comparison
equal deleted inserted replaced
104:d8ad747eb907 105:abbc482aaad2
11 #define _ADAPTIVE_SPECTROGRAM_H_ 11 #define _ADAPTIVE_SPECTROGRAM_H_
12 12
13 #include <vamp-sdk/Plugin.h> 13 #include <vamp-sdk/Plugin.h>
14 #include <cmath> 14 #include <cmath>
15 #include <vector> 15 #include <vector>
16
17 #include <dsp/transforms/FFT.h>//!!!
16 18
17 #include "thread/Thread.h" 19 #include "thread/Thread.h"
18 20
19 class AdaptiveSpectrogram : public Vamp::Plugin 21 class AdaptiveSpectrogram : public Vamp::Plugin
20 { 22 {
108 delete first; 110 delete first;
109 delete second; 111 delete second;
110 } 112 }
111 }; 113 };
112 114
113 class CutThread : public Thread 115 class FFTThread : public AsynchronousTask
114 { 116 {
115 public: 117 public:
116 CutThread(const AdaptiveSpectrogram *as) : 118 FFTThread() { }
117 m_as(as), 119 ~FFTThread() { }
118 // m_busy(false), 120
119 // m_computed(false), 121 void calculate(const float *timeDomain, Spectrograms &s,
120 m_result(0), 122 int res, int width, int maxwidth) {
121 m_workToDoC("CutThread: work to do"), 123 m_in = timeDomain;
122 m_workToDo(false), 124 m_s = &s;
123 m_workDoneC("CutThread: work done"), 125 m_res = res;
124 m_workDone(false), 126 m_w = width;
125 m_finishing(false) 127 m_maxwid = maxwidth;
126 { } 128 startTask();
129 }
130
131 void await() {
132 awaitTask();
133 }
134
135 protected:
136 void performTask() {
137
138 double *tmpin = new double[m_w];
139 double *tmprout = new double[m_w];
140 double *tmpiout = new double[m_w];
141
142 //!!! use window object
143
144 for (int i = 0; i < m_maxwid / m_w; ++i) {
145 int origin = m_maxwid/4 - m_w/4; // for 50% overlap
146 for (int j = 0; j < m_w; ++j) {
147 double mul = 0.50 - 0.50 * cos((2 * M_PI * j) / m_w);
148 tmpin[j] = m_in[origin + i * m_w/2 + j] * mul;
149 }
150 FFT::process(m_w, false, tmpin, 0, tmprout, tmpiout);
151 for (int j = 0; j < m_w/2; ++j) {
152 int k = j+1; // include Nyquist but not DC
153 double mag = sqrt(tmprout[k] * tmprout[k] +
154 tmpiout[k] * tmpiout[k]);
155 double scaled = mag / (m_w/2);
156 m_s->spectrograms[m_res]->data[i][j] = scaled;
157 }
158 }
159
160 delete[] tmpin;
161 delete[] tmprout;
162 delete[] tmpiout;
163 }
164
165 private:
166 const float *m_in;
167 Spectrograms *m_s;
168 int m_res;
169 int m_w;
170 int m_maxwid;
171 };
172
173 std::vector<FFTThread *> m_fftThreads;
174
175 class CutThread : public AsynchronousTask
176 {
177 public:
178 CutThread(const AdaptiveSpectrogram *as) : m_as(as), m_result(0) { }
127 ~CutThread() { } 179 ~CutThread() { }
128 180
129 void cut(const Spectrograms &s, int res, int x, int y, int h) { 181 void cut(const Spectrograms &s, int res, int x, int y, int h) {
130 m_workToDoC.lock();
131 // std::cerr << "locked in main thread" << std::endl;
132 m_s = &s; 182 m_s = &s;
133 m_res = res; 183 m_res = res;
134 m_x = x; 184 m_x = x;
135 m_y = y; 185 m_y = y;
136 m_h = h; 186 m_h = h;
137 // m_busy = true; 187 startTask();
138 // m_computed = false;
139 m_workToDo = true;
140 m_workDone = false;
141 m_workToDoC.signal();
142 m_workDoneC.lock();
143 m_workToDoC.unlock();
144 } 188 }
145 189
146 Cutting *get() { 190 Cutting *get() {
147 // std::cerr << "about to wait within main thread" << std::endl; 191 awaitTask();
148 // m_workDoneC must be locked from prior call to cut() 192 return m_result;
149 while (!m_workDone) m_workDoneC.wait();
150 // std::cerr << "waited within main thread" << std::endl;
151 // m_workDoneC.lock();
152 // while (!m_computed) {
153 // std::cerr << "waiting within main thread" << std::endl;
154 // m_condition.wait();
155 // }
156 Cutting *c = m_result;
157 m_result = 0;
158 m_workDoneC.unlock();
159 return c;
160 }
161 /*
162 bool busy() {
163 return m_busy;
164 }
165 */
166 void finish() {
167 m_finishing = true;
168 m_workToDoC.signal();
169 } 193 }
170 194
171 protected: 195 protected:
172 virtual void run() { 196 void performTask() {
173 m_workToDoC.lock(); 197 m_result = m_as->cut(*m_s, m_res, m_x, m_y, m_h);
174 // std::cerr << "locked within run function" << std::endl; 198 }
175 while (!m_finishing) { 199
176 // if (!m_busy) { 200 private:
177 // std::cerr << "waiting within run function" << std::endl;
178 // m_condition.wait();
179 // }
180 while (!m_workToDo && !m_finishing) m_workToDoC.wait();
181 // std::cerr << "waited within run function" << std::endl;
182 if (m_finishing) {
183 break;
184 }
185 if (m_workToDo) {
186 // std::cerr << "cut thread " << this << ": calling cut" << std::endl;
187 m_result = m_as->cut(*m_s, m_res, m_x, m_y, m_h);
188 // std::cerr << "cut returning" << std::endl;
189 // m_computed = true;
190 // m_busy = false;
191 m_workToDo = false;
192 m_workDone = true;
193 // std::cerr << "signalling completion from run function" << std::endl;
194 m_workDoneC.signal();
195 }
196 }
197 m_workToDoC.unlock();
198 }
199
200 const AdaptiveSpectrogram *m_as; 201 const AdaptiveSpectrogram *m_as;
201 const Spectrograms *m_s; 202 const Spectrograms *m_s;
202 int m_res; 203 int m_res;
203 int m_x; 204 int m_x;
204 int m_y; 205 int m_y;
205 int m_h; 206 int m_h;
206 // bool m_busy;
207 // bool m_computed;
208 Cutting *m_result; 207 Cutting *m_result;
209 Condition m_workToDoC; 208 };
210 bool m_workToDo; 209
211 Condition m_workDoneC;
212 bool m_workDone;
213 bool m_finishing;
214 };
215 mutable std::vector<CutThread *> m_cutThreads;//!!! mutable blargh 210 mutable std::vector<CutThread *> m_cutThreads;//!!! mutable blargh
216 211
217 ///!!! Mutex m_threadMutex; 212 ///!!! Mutex m_threadMutex;
218 mutable bool m_first; //!!! gross 213 mutable bool m_first; //!!! gross
219 214