cannam@0
|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
cannam@0
|
2
|
cannam@0
|
3 #include "Processor.h"
|
cannam@0
|
4
|
Chris@16
|
5 #include <vamp-hostsdk/PluginLoader.h>
|
cannam@0
|
6
|
cannam@4
|
7 //#define DEBUG_RUN_PROCESSOR 1
|
cannam@4
|
8
|
Chris@16
|
9 using Vamp::HostExt::PluginLoader;
|
Chris@16
|
10
|
cannam@0
|
11 using std::cout;
|
cannam@0
|
12 using std::cerr;
|
cannam@0
|
13 using std::endl;
|
cannam@0
|
14
|
cannam@1
|
15 void printFeatures(int, int, int, int, Vamp::Plugin::FeatureSet &);
|
cannam@0
|
16 void transformInput(float *, size_t);
|
cannam@0
|
17 void fft(unsigned int, bool, double *, double *, double *, double *);
|
cannam@0
|
18
|
cannam@0
|
19 Processor::Processor(BufferingAudioCallbackRecordTarget *audioRecordTarget) :
|
cannam@0
|
20 m_exiting(false),
|
cannam@0
|
21 m_audioRecordTarget(audioRecordTarget),
|
cannam@0
|
22 m_nextNumber(1),
|
cannam@1
|
23 m_havePlugins(false),
|
cannam@1
|
24 m_minBlockSize(0),
|
cannam@1
|
25 m_maxBlockSize(0)
|
cannam@0
|
26 {
|
cannam@5
|
27 for (int i = 0; i < MAX_DISTINCT_STEP_SIZES; ++i) {
|
cannam@5
|
28 m_unusedReaders.insert(i);
|
cannam@5
|
29 }
|
cannam@0
|
30 }
|
cannam@0
|
31
|
cannam@0
|
32 Processor::~Processor()
|
cannam@0
|
33 {
|
cannam@0
|
34 m_exiting = true;
|
cannam@0
|
35 wait();
|
Chris@15
|
36
|
Chris@15
|
37 for (RuleSet::const_iterator i = m_rules.begin(); i != m_rules.end(); ++i) {
|
Chris@15
|
38 delete *i;
|
cannam@7
|
39 }
|
cannam@0
|
40 }
|
cannam@0
|
41
|
cannam@0
|
42 void
|
cannam@0
|
43 Processor::run()
|
cannam@0
|
44 {
|
cannam@0
|
45 while (!m_exiting) {
|
cannam@0
|
46
|
cannam@1
|
47 if (!m_havePlugins) {
|
cannam@0
|
48 msleep(100);
|
cannam@0
|
49 continue;
|
cannam@0
|
50 }
|
cannam@0
|
51
|
cannam@1
|
52 size_t nframes = 0;
|
cannam@0
|
53
|
cannam@1
|
54 for (StepSizeReaderMap::iterator i = m_stepSizeReaderMap.begin();
|
cannam@1
|
55 i != m_stepSizeReaderMap.end(); ++i) {
|
cannam@1
|
56 size_t here = m_audioRecordTarget->samplesReady(i->second);
|
cannam@1
|
57 if (here > nframes) {
|
cannam@1
|
58 nframes = here;
|
cannam@1
|
59 }
|
cannam@1
|
60 }
|
cannam@0
|
61
|
cannam@1
|
62 if (nframes > m_minBlockSize) {
|
cannam@1
|
63 if (!runPlugins()) {
|
cannam@1
|
64 msleep(10);
|
cannam@1
|
65 }
|
cannam@0
|
66 } else {
|
cannam@0
|
67 msleep(50);
|
cannam@0
|
68 }
|
cannam@5
|
69
|
cannam@5
|
70 m_mutex.lock();
|
cannam@5
|
71 for (ReaderSet::iterator i = m_unusedReaders.begin();
|
cannam@5
|
72 i != m_unusedReaders.end(); ++i) {
|
cannam@5
|
73 size_t ch = m_audioRecordTarget->getChannelCount();
|
cannam@5
|
74 for (size_t c = 0; c < ch; ++c) {
|
cannam@5
|
75 m_audioRecordTarget->skipAllSamples(c, *i);
|
cannam@5
|
76 }
|
cannam@5
|
77 }
|
cannam@5
|
78 m_mutex.unlock();
|
cannam@0
|
79 }
|
cannam@0
|
80 }
|
cannam@0
|
81
|
cannam@1
|
82 bool
|
cannam@0
|
83 Processor::runPlugins()
|
cannam@0
|
84 {
|
cannam@0
|
85 QMutexLocker locker(&m_mutex);
|
cannam@0
|
86
|
cannam@1
|
87 static std::map<int, size_t> frame; // reader -> frame
|
cannam@1
|
88 if (frame.empty()) {
|
cannam@1
|
89 for (int i = 0; i < MAX_DISTINCT_STEP_SIZES; ++i) {
|
cannam@1
|
90 frame[i] = 0;
|
cannam@1
|
91 }
|
cannam@1
|
92 }
|
cannam@0
|
93
|
cannam@0
|
94 size_t sr = m_audioRecordTarget->getSourceSampleRate();
|
cannam@0
|
95
|
cannam@1
|
96 // cerr << "max block size " << m_maxBlockSize << endl;
|
cannam@1
|
97
|
cannam@1
|
98 //!!!
|
cannam@0
|
99 size_t ch = m_audioRecordTarget->getChannelCount();
|
cannam@0
|
100 float **buffers = new float *[ch];
|
cannam@0
|
101 for (size_t c = 0; c < ch; ++c) {
|
cannam@1
|
102 buffers[c] = new float[m_maxBlockSize];
|
cannam@1
|
103 }
|
cannam@1
|
104
|
cannam@1
|
105 bool doneWork = false;
|
cannam@1
|
106
|
cannam@1
|
107 for (StepSizePluginMap::iterator i = m_processingMap.begin();
|
cannam@1
|
108 i != m_processingMap.end(); ++i) {
|
cannam@1
|
109
|
cannam@1
|
110 size_t step = i->first;
|
cannam@1
|
111 if (m_stepSizeReaderMap.find(step) == m_stepSizeReaderMap.end()) {
|
cannam@1
|
112 cerr << "ERROR: Unrecorded step size " << step << endl;
|
cannam@1
|
113 continue;
|
cannam@0
|
114 }
|
cannam@0
|
115
|
cannam@1
|
116 int reader = m_stepSizeReaderMap[step];
|
cannam@1
|
117 size_t maxBlock = 0;
|
cannam@0
|
118
|
cannam@1
|
119 for (BlockSizePluginMap::iterator j = i->second.begin();
|
cannam@1
|
120 j != i->second.end(); ++j) {
|
cannam@1
|
121
|
cannam@1
|
122 if (j == i->second.begin() || j->first > maxBlock) {
|
cannam@1
|
123 maxBlock = j->first;
|
cannam@0
|
124 }
|
cannam@0
|
125 }
|
cannam@0
|
126
|
cannam@1
|
127 if (maxBlock == 0) {
|
cannam@1
|
128 cerr << "ERROR: maxBlock == 0 for step " << step << endl;
|
cannam@1
|
129 continue;
|
cannam@1
|
130 }
|
cannam@0
|
131
|
cannam@1
|
132 // int counter = 0;
|
cannam@1
|
133
|
cannam@1
|
134 while (m_audioRecordTarget->samplesReady(reader) >= maxBlock) {
|
cannam@1
|
135 // && counter < 10) {
|
cannam@1
|
136
|
cannam@1
|
137 // ++counter;
|
cannam@1
|
138
|
cannam@4
|
139 #ifdef DEBUG_RUN_PROCESSOR
|
cannam@4
|
140 cerr << "enough samples for max block " << maxBlock
|
cannam@4
|
141 << " for step " << step << endl;
|
cannam@4
|
142 #endif
|
cannam@1
|
143
|
cannam@1
|
144 for (size_t c = 0; c < ch; ++c) {
|
cannam@5
|
145 size_t got = m_audioRecordTarget->peekSamples(c, maxBlock, buffers[c], reader);
|
cannam@5
|
146 if (got < maxBlock) {
|
cannam@5
|
147 cerr << "ERROR: Requested " << maxBlock << " samples on channel " << c << " reader " << reader << ", only got " << got << endl;
|
cannam@5
|
148 }
|
cannam@5
|
149 size_t skipped = m_audioRecordTarget->skipSamples(c, step, reader);
|
cannam@5
|
150 if (skipped < step) {
|
cannam@5
|
151 cerr << "ERROR: Requested skip of " << step << " samples on channel " << c << " reader " << reader << ", only skipped " << skipped << endl;
|
cannam@5
|
152 }
|
cannam@1
|
153 }
|
cannam@1
|
154
|
cannam@1
|
155 for (BlockSizePluginMap::iterator j = i->second.begin();
|
cannam@1
|
156 j != i->second.end(); ++j) {
|
cannam@1
|
157
|
cannam@1
|
158 size_t block = j->first;
|
cannam@1
|
159 size_t toUse = maxBlock;
|
cannam@1
|
160 size_t off = 0;
|
cannam@1
|
161
|
cannam@1
|
162 while (toUse >= block) {
|
cannam@1
|
163
|
cannam@14
|
164 bool silentInput = true;
|
cannam@14
|
165 for (size_t s = 0; s < block; ++s) {
|
cannam@14
|
166 for (size_t c = 0; c < ch; ++c) {
|
cannam@14
|
167 if (fabsf(buffers[c][s + off]) > 0.00001) {
|
cannam@14
|
168 silentInput = false;
|
cannam@14
|
169 break;
|
cannam@14
|
170 }
|
cannam@14
|
171 }
|
cannam@14
|
172 if (!silentInput) break;
|
cannam@14
|
173 }
|
cannam@14
|
174
|
cannam@1
|
175 for (PluginSet::iterator k = j->second.begin();
|
cannam@1
|
176 k != j->second.end(); ++k) {
|
cannam@1
|
177
|
cannam@4
|
178 #ifdef DEBUG_RUN_PROCESSOR
|
cannam@4
|
179 cerr << "block inner loop for block " << block
|
cannam@4
|
180 << " (toUse = " << toUse << ")" << endl;
|
cannam@4
|
181 #endif
|
cannam@1
|
182
|
cannam@1
|
183 Vamp::Plugin *plugin = *k;
|
cannam@1
|
184 Vamp::Plugin::FeatureSet fs;
|
cannam@1
|
185 Vamp::RealTime timestamp =
|
cannam@1
|
186 Vamp::RealTime::frame2RealTime(frame[reader], sr);
|
cannam@1
|
187
|
cannam@4
|
188 #ifdef DEBUG_RUN_PROCESSOR
|
Chris@16
|
189 cerr << "running " << plugin->getName() << " frame = " << frame[reader] << endl;
|
cannam@4
|
190 #endif
|
Chris@16
|
191 float *tmp[10];
|
Chris@16
|
192 for (size_t c = 0; c < ch; ++c) {
|
Chris@16
|
193 tmp[c] = buffers[c] + off;
|
cannam@5
|
194 }
|
Chris@16
|
195 fs = plugin->process(tmp, timestamp);
|
cannam@5
|
196
|
cannam@5
|
197 int pluginIndex = m_pluginRMap[plugin];
|
cannam@5
|
198
|
cannam@5
|
199 if (fs.empty()) {
|
cannam@5
|
200 for (OutputStateMap::iterator oi =
|
cannam@5
|
201 m_pluginStates[pluginIndex].begin();
|
cannam@5
|
202 oi != m_pluginStates[pluginIndex].end(); ++oi) {
|
cannam@5
|
203 int output = oi->first;
|
cannam@5
|
204 OutputState currentState = oi->second;
|
cannam@5
|
205
|
cannam@5
|
206 Vamp::RealTime rt =
|
cannam@5
|
207 Vamp::RealTime::frame2RealTime(frame[reader], sr);
|
cannam@5
|
208
|
cannam@13
|
209 // bool changed = currentState.present;
|
cannam@13
|
210 bool changed = false;
|
cannam@14
|
211 if (currentState.silentInput && !silentInput) {
|
cannam@14
|
212 changed = true;
|
cannam@14
|
213 }
|
cannam@5
|
214 Vamp::RealTime gap = rt - currentState.laststamp;
|
cannam@5
|
215 m_pluginStates[pluginIndex][output] =
|
cannam@14
|
216 OutputState(false, silentInput, changed, currentState.value, currentState.laststamp, currentState.gap);
|
cannam@1
|
217 }
|
cannam@1
|
218 }
|
cannam@5
|
219
|
cannam@1
|
220 for (Vamp::Plugin::FeatureSet::iterator fi = fs.begin();
|
cannam@1
|
221 fi != fs.end(); ++fi) {
|
cannam@4
|
222
|
cannam@4
|
223 int output = fi->first;
|
cannam@4
|
224
|
cannam@4
|
225 //!!! For each output, we need to step
|
cannam@4
|
226 //through the returned features one by one
|
cannam@4
|
227 //and update the plugin state for each,
|
cannam@4
|
228 //then run the rules each time a timestamp
|
cannam@4
|
229 //changes. But it has to do this with the
|
cannam@4
|
230 //features in the order of their
|
cannam@4
|
231 //timestamps, not in order of
|
cannam@4
|
232 //plugin/output enumeration.
|
cannam@4
|
233 //
|
cannam@4
|
234 // But we don't do that yet, we just use
|
cannam@4
|
235 // the first feature in the block (if any)
|
cannam@4
|
236
|
cannam@4
|
237 Vamp::RealTime rt =
|
cannam@4
|
238 Vamp::RealTime::frame2RealTime(frame[reader], sr);
|
cannam@4
|
239
|
cannam@4
|
240 Vamp::Plugin::FeatureList fl(fi->second);
|
cannam@4
|
241
|
cannam@4
|
242 OutputState currentState =
|
cannam@4
|
243 m_pluginStates[pluginIndex][output];
|
cannam@5
|
244
|
cannam@4
|
245 if (fl.empty()) {
|
cannam@13
|
246 // bool changed = currentState.present;
|
cannam@13
|
247 bool changed = false;
|
cannam@14
|
248 if (currentState.silentInput && !silentInput) {
|
cannam@14
|
249 changed = true;
|
cannam@14
|
250 }
|
cannam@4
|
251 Vamp::RealTime gap = rt - currentState.laststamp;
|
cannam@4
|
252 m_pluginStates[pluginIndex][output] =
|
cannam@14
|
253 OutputState(false, silentInput, changed, currentState.value, currentState.laststamp, currentState.gap);
|
cannam@4
|
254 } else {
|
cannam@4
|
255
|
cannam@4
|
256 if (fl[0].hasTimestamp) {
|
cannam@4
|
257 rt = fl[0].timestamp;
|
cannam@4
|
258 }
|
cannam@4
|
259 float value = 0.f;
|
cannam@4
|
260 if (!fl[0].values.empty()) {
|
cannam@4
|
261 value = fl[0].values[0];
|
cannam@4
|
262 }
|
cannam@5
|
263 bool changed =
|
cannam@13
|
264 // (!currentState.present ||
|
cannam@5
|
265 (fabsf(currentState.value - value) >
|
cannam@13
|
266 0.000001)
|
cannam@13
|
267 // )
|
cannam@13
|
268 ;
|
cannam@14
|
269 if (currentState.silentInput && !silentInput) {
|
cannam@14
|
270 changed = true;
|
cannam@14
|
271 }
|
cannam@13
|
272 if (changed) {
|
cannam@13
|
273 std::cerr << "changed: " <<currentState.value << " -> " << value << std::endl;
|
cannam@13
|
274 }
|
cannam@4
|
275 Vamp::RealTime gap = rt - currentState.laststamp;
|
cannam@9
|
276 // std::cerr << "gap = " << gap << std::endl;
|
cannam@4
|
277 m_pluginStates[pluginIndex][output] =
|
cannam@14
|
278 OutputState(true, silentInput, changed, value, rt, gap);
|
cannam@4
|
279 }
|
cannam@4
|
280
|
Chris@15
|
281 printFeatures(pluginIndex, frame[reader], sr, output, fs);
|
cannam@1
|
282 }
|
cannam@1
|
283
|
cannam@4
|
284 processRules();
|
cannam@4
|
285
|
cannam@1
|
286 doneWork = true;
|
cannam@1
|
287 }
|
cannam@1
|
288
|
cannam@1
|
289 toUse -= block;
|
cannam@1
|
290 off += block;
|
cannam@1
|
291 }
|
cannam@1
|
292 }
|
cannam@1
|
293
|
cannam@1
|
294 frame[reader] += step;
|
cannam@0
|
295 }
|
cannam@1
|
296
|
cannam@0
|
297 }
|
cannam@0
|
298
|
cannam@0
|
299 for (size_t c = 0; c < ch; ++c) {
|
cannam@0
|
300 delete[] buffers[c];
|
cannam@0
|
301 }
|
cannam@0
|
302 delete[] buffers;
|
cannam@1
|
303
|
cannam@1
|
304 return doneWork;
|
cannam@0
|
305 }
|
cannam@0
|
306
|
cannam@0
|
307 int
|
cannam@0
|
308 Processor::addPlugin(QString pluginId)
|
cannam@0
|
309 {
|
cannam@0
|
310 QMutexLocker locker(&m_mutex);
|
cannam@0
|
311
|
cannam@0
|
312 size_t sr = m_audioRecordTarget->getSourceSampleRate();
|
cannam@0
|
313
|
cannam@0
|
314 if (!sr) {
|
cannam@0
|
315 cerr << "ERROR: Processor::addPlugin: Source sample rate is not defined" << endl;
|
cannam@0
|
316 return 0;
|
cannam@0
|
317 }
|
cannam@0
|
318
|
Chris@16
|
319 if (pluginId.startsWith("vamp:")) {
|
Chris@16
|
320 pluginId = pluginId.right(pluginId.size() - 5);
|
cannam@0
|
321 }
|
cannam@0
|
322
|
Chris@16
|
323 PluginLoader *loader = PluginLoader::getInstance();
|
Chris@16
|
324 Vamp::Plugin *plugin = loader->loadPlugin
|
Chris@16
|
325 (pluginId.toStdString(), sr, PluginLoader::ADAPT_ALL_SAFE);
|
cannam@0
|
326
|
cannam@0
|
327 if (!plugin) {
|
cannam@0
|
328 cerr << "ERROR: Processor::addPlugin: Failed to instantiate plugin \"" << pluginId.toStdString() << "\"" << endl;
|
cannam@0
|
329 return 0;
|
cannam@0
|
330 }
|
cannam@0
|
331
|
cannam@1
|
332 size_t block = plugin->getPreferredBlockSize();
|
cannam@1
|
333 if (block == 0) block = m_audioRecordTarget->getSourceBlockSize();
|
cannam@0
|
334
|
cannam@1
|
335 size_t step = plugin->getPreferredStepSize();
|
Chris@16
|
336 if (step == 0) step = block;
|
cannam@0
|
337
|
cannam@1
|
338 if (m_stepSizeReaderMap.find(step) == m_stepSizeReaderMap.end()) {
|
cannam@5
|
339 if (m_unusedReaders.empty()) {
|
cannam@1
|
340 cerr << "ERROR: Processor::addPlugin: Run out of distinct step size slots: increase MAX_DISTINCT_STEP_SIZES and recompile" << endl;
|
cannam@1
|
341 delete plugin;
|
cannam@1
|
342 return 0;
|
cannam@1
|
343 }
|
cannam@5
|
344 int reader = *m_unusedReaders.begin();
|
cannam@5
|
345 m_unusedReaders.erase(reader);
|
cannam@5
|
346 m_stepSizeReaderMap[step] = reader;
|
cannam@1
|
347 }
|
cannam@0
|
348
|
cannam@1
|
349 size_t ch = m_audioRecordTarget->getChannelCount();
|
cannam@0
|
350
|
cannam@1
|
351 if (!plugin->initialise(ch, step, block)) {
|
cannam@1
|
352 cerr << "ERROR: Processor::addPlugin: Initialisation failed with step size " << step << ", block size " << block << ", channels " << ch << endl;
|
cannam@0
|
353 delete plugin;
|
cannam@0
|
354 return 0;
|
cannam@0
|
355 }
|
cannam@0
|
356
|
cannam@1
|
357 if (!m_havePlugins || block < m_minBlockSize) m_minBlockSize = block;
|
cannam@1
|
358 if (!m_havePlugins || block > m_maxBlockSize) m_maxBlockSize = block;
|
cannam@0
|
359
|
cannam@5
|
360 std::cerr << "initialised plugin \"" << pluginId.toStdString()
|
cannam@5
|
361 << "\" with step \"" << step << "\" block \"" << block << "\""
|
cannam@5
|
362 << std::endl;
|
cannam@5
|
363
|
cannam@0
|
364 int number = m_nextNumber++;
|
cannam@1
|
365 m_plugins[number] = plugin;
|
cannam@4
|
366 m_pluginRMap[plugin] = number;
|
cannam@1
|
367 m_processingMap[step][block].insert(plugin);
|
cannam@0
|
368
|
cannam@1
|
369 m_havePlugins = true;
|
cannam@0
|
370 return number;
|
cannam@0
|
371 }
|
cannam@0
|
372
|
cannam@0
|
373 void
|
cannam@0
|
374 Processor::removePlugin(int number)
|
cannam@0
|
375 {
|
cannam@0
|
376 QMutexLocker locker(&m_mutex);
|
cannam@0
|
377
|
cannam@0
|
378 if (m_plugins.find(number) == m_plugins.end()) {
|
cannam@0
|
379 cerr << "ERROR: Processor::removePlugin: No such plugin number "
|
cannam@0
|
380 << number << endl;
|
cannam@0
|
381 return;
|
cannam@0
|
382 }
|
cannam@0
|
383
|
cannam@0
|
384 Vamp::Plugin *plugin = m_plugins[number];
|
cannam@1
|
385 bool done = false;
|
cannam@1
|
386
|
cannam@1
|
387 for (StepSizePluginMap::iterator i = m_processingMap.begin();
|
cannam@1
|
388 i != m_processingMap.end(); ++i) {
|
cannam@1
|
389
|
cannam@1
|
390 BlockSizePluginMap::iterator j;
|
cannam@1
|
391
|
cannam@1
|
392 for (j = i->second.begin(); j != i->second.end(); ++j) {
|
cannam@1
|
393
|
cannam@1
|
394 if (j->second.find(plugin) != j->second.end()) {
|
cannam@1
|
395
|
cannam@1
|
396 j->second.erase(plugin);
|
cannam@1
|
397
|
cannam@1
|
398 if (j->second.empty()) { // no plugins with this step & block
|
cannam@1
|
399
|
cannam@1
|
400 i->second.erase(j->first);
|
cannam@1
|
401
|
cannam@1
|
402 if (i->second.empty()) { // no plugins with this step
|
cannam@1
|
403
|
cannam@1
|
404 m_processingMap.erase(i->first);
|
cannam@1
|
405 m_stepSizeReaderMap.erase(i->first);
|
cannam@5
|
406 m_unusedReaders.insert(i->first);
|
cannam@1
|
407 }
|
cannam@1
|
408 }
|
cannam@1
|
409
|
cannam@1
|
410 done = true;
|
cannam@1
|
411 break;
|
cannam@1
|
412 }
|
cannam@1
|
413 }
|
cannam@1
|
414
|
cannam@1
|
415 if (done) break;
|
cannam@1
|
416 }
|
cannam@1
|
417
|
cannam@0
|
418 m_plugins.erase(number);
|
cannam@4
|
419 m_pluginRMap.erase(plugin);
|
cannam@1
|
420 if (m_plugins.empty()) m_havePlugins = false;
|
cannam@0
|
421 delete plugin;
|
cannam@0
|
422 }
|
cannam@0
|
423
|
cannam@4
|
424 void
|
cannam@7
|
425 Processor::addRule(Rule *rule)
|
cannam@4
|
426 {
|
Chris@15
|
427 cerr << "adding rule " << rule << endl;
|
cannam@7
|
428 m_rules.insert(rule);
|
cannam@4
|
429 }
|
cannam@4
|
430
|
cannam@4
|
431 bool
|
cannam@4
|
432 Processor::processRules()
|
cannam@4
|
433 {
|
cannam@7
|
434 for (RuleSet::iterator i = m_rules.begin(); i != m_rules.end(); ++i) {
|
cannam@4
|
435
|
cannam@7
|
436 Rule *rule(*i);
|
cannam@4
|
437
|
cannam@7
|
438 bool passed = false;
|
cannam@13
|
439 bool oneChanged = false;
|
cannam@4
|
440
|
cannam@7
|
441 for (Rule::ConditionList::const_iterator j = rule->getConditions().begin();
|
cannam@7
|
442 j != rule->getConditions().end(); ++j) {
|
cannam@7
|
443
|
cannam@7
|
444 Condition condition(*j);
|
cannam@7
|
445
|
cannam@7
|
446 int pluginIndex = condition.getPluginIndex();
|
cannam@7
|
447 int outputNumber = condition.getOutputNumber();
|
cannam@7
|
448 Condition::Type type = condition.getType();
|
cannam@7
|
449 float argument = condition.getArgument();
|
cannam@7
|
450
|
cannam@7
|
451 OutputState state = m_pluginStates[pluginIndex][outputNumber];
|
cannam@4
|
452
|
cannam@5
|
453 #ifdef DEBUG_RUN_PROCESSOR
|
cannam@7
|
454 std::cerr << "Present = " << state.present << ", changed = " << state.changed << ", value = " << state.value << std::endl;
|
cannam@5
|
455 #endif
|
cannam@5
|
456
|
cannam@7
|
457 passed = false;
|
cannam@5
|
458
|
cannam@14
|
459 if (state.silentInput) {
|
cannam@14
|
460 break;
|
cannam@14
|
461 }
|
cannam@14
|
462
|
cannam@13
|
463 if (state.changed) {
|
cannam@13
|
464 // std::cerr << "State changed with present = " << state.present << ", value = " << state.value << std::endl;
|
cannam@13
|
465 oneChanged = true;
|
cannam@13
|
466 }
|
cannam@5
|
467
|
cannam@7
|
468 switch (type) {
|
cannam@5
|
469
|
cannam@7
|
470 case Condition::GreaterThan:
|
cannam@7
|
471 passed = (state.value > argument);
|
cannam@7
|
472 break;
|
cannam@7
|
473
|
cannam@7
|
474 case Condition::LessThan:
|
cannam@7
|
475 passed = (state.value < argument);
|
cannam@7
|
476 break;
|
cannam@7
|
477
|
cannam@7
|
478 case Condition::EqualTo:
|
cannam@7
|
479 passed = fabsf(state.value - argument) < 0.000001;
|
cannam@7
|
480 break;
|
cannam@7
|
481
|
cannam@7
|
482 case Condition::NotEqualTo:
|
cannam@7
|
483 passed = fabsf(state.value - argument) > 0.000001;
|
cannam@7
|
484 break;
|
cannam@7
|
485
|
cannam@7
|
486 case Condition::Present:
|
cannam@7
|
487 passed = state.present;
|
cannam@13
|
488 if (passed) oneChanged = true;
|
cannam@7
|
489 break;
|
cannam@7
|
490
|
cannam@7
|
491 case Condition::Changed:
|
cannam@13
|
492 passed = state.changed;
|
cannam@7
|
493 break;
|
cannam@7
|
494
|
cannam@7
|
495 case Condition::GapGreaterThan:
|
cannam@7
|
496 passed = (state.gap > Vamp::RealTime::fromSeconds(argument));
|
cannam@7
|
497 break;
|
cannam@7
|
498
|
cannam@7
|
499 case Condition::GapLessThan:
|
cannam@9
|
500 std::cout << "GapLessThan: gap is " << state.gap << ", argument is " << argument << std::endl;
|
cannam@7
|
501 passed = (state.gap < Vamp::RealTime::fromSeconds(argument));
|
cannam@7
|
502 break;
|
cannam@7
|
503 }
|
cannam@5
|
504
|
cannam@7
|
505 if (!passed) break;
|
cannam@5
|
506 }
|
cannam@5
|
507
|
cannam@13
|
508 if (passed && oneChanged) {
|
cannam@9
|
509 for (Rule::ActionList::const_iterator ai = rule->getActions().begin();
|
cannam@9
|
510 ai != rule->getActions().end(); ++ai) {
|
cannam@9
|
511 Action *action = *ai;
|
cannam@9
|
512 if (action) {
|
cannam@9
|
513 // std::cerr << "FIRING RULE: " << action->getName().toStdString() << "!" << std::endl;
|
cannam@9
|
514 action->fire();
|
cannam@9
|
515 }
|
cannam@7
|
516 }
|
cannam@4
|
517 }
|
cannam@4
|
518 }
|
cannam@4
|
519
|
cannam@4
|
520 return true;
|
cannam@4
|
521 }
|
cannam@0
|
522
|
cannam@0
|
523 void
|
cannam@1
|
524 printFeatures(int plugno, int frame, int sr, int output, Vamp::Plugin::FeatureSet &features)
|
cannam@0
|
525 {
|
cannam@9
|
526 return;//!!!
|
cannam@5
|
527
|
cannam@5
|
528 if (output > 0) return;//!!!
|
cannam@5
|
529
|
cannam@0
|
530 for (unsigned int i = 0; i < features[output].size(); ++i) {
|
cannam@0
|
531 Vamp::RealTime rt = Vamp::RealTime::frame2RealTime(frame, sr);
|
cannam@0
|
532 if (features[output][i].hasTimestamp) {
|
cannam@0
|
533 rt = features[output][i].timestamp;
|
cannam@0
|
534 }
|
cannam@1
|
535 cout << plugno << ":" << output << " -" << rt.toString() << ":";
|
cannam@0
|
536 for (unsigned int j = 0; j < features[output][i].values.size(); ++j) {
|
cannam@0
|
537 cout << " " << features[output][i].values[j];
|
cannam@0
|
538 }
|
cannam@0
|
539 cout << endl;
|
cannam@0
|
540 }
|
cannam@0
|
541 }
|
cannam@0
|
542
|