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
|