Mercurial > hg > qm-vamp-plugins
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 |