Mercurial > hg > sonic-annotator
comparison runner/FeatureExtractionManager.cpp @ 263:68dc2d99a5b1 piper-nopiper
Debug output updates, add quiet mode
author | Chris Cannam |
---|---|
date | Tue, 22 Nov 2016 16:42:56 +0000 |
parents | 857ce6ecb163 |
children | 0be716283c61 |
comparison
equal
deleted
inserted
replaced
262:d7bbc5b03619 | 263:68dc2d99a5b1 |
---|---|
21 #include <vamp-hostsdk/PluginInputDomainAdapter.h> | 21 #include <vamp-hostsdk/PluginInputDomainAdapter.h> |
22 #include <vamp-hostsdk/PluginSummarisingAdapter.h> | 22 #include <vamp-hostsdk/PluginSummarisingAdapter.h> |
23 #include <vamp-hostsdk/PluginWrapper.h> | 23 #include <vamp-hostsdk/PluginWrapper.h> |
24 #include <vamp-hostsdk/PluginLoader.h> | 24 #include <vamp-hostsdk/PluginLoader.h> |
25 | 25 |
26 #include "base/Debug.h" | |
26 #include "base/Exceptions.h" | 27 #include "base/Exceptions.h" |
27 | 28 |
28 #include <iostream> | 29 #include <iostream> |
29 | 30 |
30 using namespace std; | 31 using namespace std; |
49 | 50 |
50 #include <QTextStream> | 51 #include <QTextStream> |
51 #include <QFile> | 52 #include <QFile> |
52 #include <QFileInfo> | 53 #include <QFileInfo> |
53 | 54 |
54 FeatureExtractionManager::FeatureExtractionManager() : | 55 FeatureExtractionManager::FeatureExtractionManager(bool verbose) : |
56 m_verbose(verbose), | |
55 m_summariesOnly(false), | 57 m_summariesOnly(false), |
56 // We can read using an arbitrary fixed block size -- | 58 // We can read using an arbitrary fixed block size -- |
57 // PluginBufferingAdapter handles this for us. But while this | 59 // PluginBufferingAdapter handles this for us. But while this |
58 // doesn't affect the step and block size actually passed to the | 60 // doesn't affect the step and block size actually passed to the |
59 // plugin, it does affect the overall time range of the audio | 61 // plugin, it does affect the overall time range of the audio |
71 { | 73 { |
72 } | 74 } |
73 | 75 |
74 FeatureExtractionManager::~FeatureExtractionManager() | 76 FeatureExtractionManager::~FeatureExtractionManager() |
75 { | 77 { |
78 SVDEBUG << "FeatureExtractionManager::~FeatureExtractionManager: cleaning up" | |
79 << endl; | |
80 | |
76 for (PluginMap::iterator pi = m_plugins.begin(); | 81 for (PluginMap::iterator pi = m_plugins.begin(); |
77 pi != m_plugins.end(); ++pi) { | 82 pi != m_plugins.end(); ++pi) { |
78 delete pi->first; | 83 delete pi->first; |
79 } | 84 } |
80 foreach (AudioFileReader *r, m_readyReaders) { | 85 foreach (AudioFileReader *r, m_readyReaders) { |
81 delete r; | 86 delete r; |
82 } | 87 } |
88 | |
89 SVDEBUG << "FeatureExtractionManager::~FeatureExtractionManager: done" << endl; | |
83 } | 90 } |
84 | 91 |
85 void FeatureExtractionManager::setChannels(int channels) | 92 void FeatureExtractionManager::setChannels(int channels) |
86 { | 93 { |
87 m_channels = channels; | 94 m_channels = channels; |
117 const PluginSummarisingAdapter::SegmentBoundaries &boundaries) | 124 const PluginSummarisingAdapter::SegmentBoundaries &boundaries) |
118 { | 125 { |
119 for (SummaryNameSet::const_iterator i = names.begin(); | 126 for (SummaryNameSet::const_iterator i = names.begin(); |
120 i != names.end(); ++i) { | 127 i != names.end(); ++i) { |
121 if (getSummaryType(*i) == PluginSummarisingAdapter::UnknownSummaryType) { | 128 if (getSummaryType(*i) == PluginSummarisingAdapter::UnknownSummaryType) { |
122 cerr << "ERROR: Unknown summary type \"" << *i << "\"" << endl; | 129 SVCERR << "ERROR: Unknown summary type \"" << *i << "\"" << endl; |
123 return false; | 130 return false; |
124 } | 131 } |
125 } | 132 } |
126 m_summaries = names; | 133 m_summaries = names; |
127 m_boundaries = boundaries; | 134 m_boundaries = boundaries; |
154 return PluginInputDomainAdapter::BlackmanHarrisWindow; | 161 return PluginInputDomainAdapter::BlackmanHarrisWindow; |
155 case GaussianWindow: | 162 case GaussianWindow: |
156 case ParzenWindow: | 163 case ParzenWindow: |
157 // Not supported in Vamp SDK, fall through | 164 // Not supported in Vamp SDK, fall through |
158 default: | 165 default: |
159 cerr << "ERROR: Unknown or unsupported window type \"" << t << "\", using Hann (\"" << HanningWindow << "\")" << endl; | 166 SVCERR << "ERROR: Unknown or unsupported window type \"" << t << "\", using Hann (\"" << HanningWindow << "\")" << endl; |
160 return PluginInputDomainAdapter::HanningWindow; | 167 return PluginInputDomainAdapter::HanningWindow; |
161 } | 168 } |
162 } | 169 } |
163 | 170 |
164 bool FeatureExtractionManager::addFeatureExtractor | 171 bool FeatureExtractionManager::addFeatureExtractor |
166 { | 173 { |
167 //!!! exceptions rather than return values? | 174 //!!! exceptions rather than return values? |
168 | 175 |
169 if (transform.getSampleRate() == 0) { | 176 if (transform.getSampleRate() == 0) { |
170 if (m_sampleRate == 0) { | 177 if (m_sampleRate == 0) { |
171 cerr << "NOTE: Transform does not specify a sample rate, using default rate of " << m_defaultSampleRate << endl; | 178 SVCERR << "NOTE: Transform does not specify a sample rate, using default rate of " << m_defaultSampleRate << endl; |
172 transform.setSampleRate(m_defaultSampleRate); | 179 transform.setSampleRate(m_defaultSampleRate); |
173 m_sampleRate = m_defaultSampleRate; | 180 m_sampleRate = m_defaultSampleRate; |
174 } else { | 181 } else { |
175 cerr << "NOTE: Transform does not specify a sample rate, using previous transform's rate of " << m_sampleRate << endl; | 182 SVCERR << "NOTE: Transform does not specify a sample rate, using previous transform's rate of " << m_sampleRate << endl; |
176 transform.setSampleRate(m_sampleRate); | 183 transform.setSampleRate(m_sampleRate); |
177 } | 184 } |
178 } | 185 } |
179 | 186 |
180 if (m_sampleRate == 0) { | 187 if (m_sampleRate == 0) { |
181 m_sampleRate = transform.getSampleRate(); | 188 m_sampleRate = transform.getSampleRate(); |
182 } | 189 } |
183 | 190 |
184 if (transform.getSampleRate() != m_sampleRate) { | 191 if (transform.getSampleRate() != m_sampleRate) { |
185 cerr << "WARNING: Transform sample rate " << transform.getSampleRate() << " does not match previously specified transform rate of " << m_sampleRate << " -- only a single rate is supported for each run" << endl; | 192 SVCERR << "WARNING: Transform sample rate " << transform.getSampleRate() << " does not match previously specified transform rate of " << m_sampleRate << " -- only a single rate is supported for each run" << endl; |
186 cerr << "WARNING: Using previous rate of " << m_sampleRate << " for this transform as well" << endl; | 193 SVCERR << "WARNING: Using previous rate of " << m_sampleRate << " for this transform as well" << endl; |
187 transform.setSampleRate(m_sampleRate); | 194 transform.setSampleRate(m_sampleRate); |
188 } | 195 } |
189 | 196 |
190 Plugin *plugin = 0; | 197 Plugin *plugin = 0; |
191 | 198 |
206 i != m_transformPluginMap.end(); ++i) { | 213 i != m_transformPluginMap.end(); ++i) { |
207 Transform test = i->first; | 214 Transform test = i->first; |
208 test.setOutput(transform.getOutput()); | 215 test.setOutput(transform.getOutput()); |
209 test.setSummaryType(transform.getSummaryType()); | 216 test.setSummaryType(transform.getSummaryType()); |
210 if (transform == test) { | 217 if (transform == test) { |
211 cerr << "NOTE: Already have transform identical to this one (for \"" | 218 SVCERR << "NOTE: Already have transform identical to this one (for \"" |
212 << transform.getIdentifier().toStdString() | 219 << transform.getIdentifier().toStdString() |
213 << "\") in every detail except output identifier and/or " | 220 << "\") in every detail except output identifier and/or " |
214 << "summary type; sharing its plugin instance" << endl; | 221 << "summary type; sharing its plugin instance" << endl; |
215 plugin = i->second; | 222 plugin = i->second; |
216 if (transform.getSummaryType() != Transform::NoSummary && | 223 if (transform.getSummaryType() != Transform::NoSummary && |
229 PluginBase *pb = tf->instantiatePluginFor(transform); | 236 PluginBase *pb = tf->instantiatePluginFor(transform); |
230 plugin = tf->downcastVampPlugin(pb); | 237 plugin = tf->downcastVampPlugin(pb); |
231 if (!plugin) { | 238 if (!plugin) { |
232 //!!! todo: handle non-Vamp plugins too, or make the main --list | 239 //!!! todo: handle non-Vamp plugins too, or make the main --list |
233 // option print out only Vamp transforms | 240 // option print out only Vamp transforms |
234 cerr << "ERROR: Failed to load plugin for transform \"" | 241 SVCERR << "ERROR: Failed to load plugin for transform \"" |
235 << transform.getIdentifier().toStdString() << "\"" << endl; | 242 << transform.getIdentifier().toStdString() << "\"" << endl; |
236 if (pb) { | 243 if (pb) { |
237 cerr << "NOTE: (A plugin was loaded, but apparently not a Vamp plugin)" << endl; | 244 SVCERR << "NOTE: (A plugin was loaded, but apparently not a Vamp plugin)" << endl; |
238 } | 245 } |
239 delete pb; | 246 delete pb; |
240 return false; | 247 return false; |
241 } | 248 } |
242 | 249 |
292 adapter->setSummarySegmentBoundaries(m_boundaries); | 299 adapter->setSummarySegmentBoundaries(m_boundaries); |
293 plugin = adapter; | 300 plugin = adapter; |
294 } | 301 } |
295 | 302 |
296 if (!plugin->initialise(m_channels, m_blockSize, m_blockSize)) { | 303 if (!plugin->initialise(m_channels, m_blockSize, m_blockSize)) { |
297 cerr << "ERROR: Plugin initialise (channels = " << m_channels << ", stepSize = " << m_blockSize << ", blockSize = " << m_blockSize << ") failed." << endl; | 304 SVCERR << "ERROR: Plugin initialise (channels = " << m_channels << ", stepSize = " << m_blockSize << ", blockSize = " << m_blockSize << ") failed." << endl; |
298 delete plugin; | 305 delete plugin; |
299 return false; | 306 return false; |
300 } | 307 } |
301 | 308 |
302 // cerr << "Initialised plugin" << endl; | 309 SVDEBUG << "Initialised plugin" << endl; |
303 | 310 |
304 size_t actualStepSize = 0; | 311 size_t actualStepSize = 0; |
305 size_t actualBlockSize = 0; | 312 size_t actualBlockSize = 0; |
306 pba->getActualStepAndBlockSizes(actualStepSize, actualBlockSize); | 313 pba->getActualStepAndBlockSizes(actualStepSize, actualBlockSize); |
307 transform.setStepSize(actualStepSize); | 314 transform.setStepSize(actualStepSize); |
308 transform.setBlockSize(actualBlockSize); | 315 transform.setBlockSize(actualBlockSize); |
309 | 316 |
310 Plugin::OutputList outputs = plugin->getOutputDescriptors(); | 317 Plugin::OutputList outputs = plugin->getOutputDescriptors(); |
311 for (int i = 0; i < (int)outputs.size(); ++i) { | 318 for (int i = 0; i < (int)outputs.size(); ++i) { |
312 | 319 |
313 // cerr << "Newly initialised plugin output " << i << " has bin count " << outputs[i].binCount << endl; | 320 SVDEBUG << "Newly initialised plugin output " << i << " has bin count " << outputs[i].binCount << endl; |
314 | 321 |
315 m_pluginOutputs[plugin][outputs[i].identifier] = outputs[i]; | 322 m_pluginOutputs[plugin][outputs[i].identifier] = outputs[i]; |
316 m_pluginOutputIndices[outputs[i].identifier] = i; | 323 m_pluginOutputIndices[outputs[i].identifier] = i; |
317 } | 324 } |
318 | 325 |
319 cerr << "NOTE: Loaded and initialised plugin for transform \"" | 326 SVCERR << "NOTE: Loaded and initialised plugin for transform \"" |
320 << transform.getIdentifier().toStdString() | 327 << transform.getIdentifier().toStdString() |
321 << "\" with plugin step size " << actualStepSize | 328 << "\" with plugin step size " << actualStepSize |
322 << " and block size " << actualBlockSize | 329 << " and block size " << actualBlockSize |
323 << " (adapter step and block size " << m_blockSize << ")" | 330 << " (adapter step and block size " << m_blockSize << ")" |
324 << endl; | 331 << endl; |
325 | 332 |
326 // cerr << "NOTE: That transform is: " << transform.toXmlString() << endl; | 333 SVDEBUG << "NOTE: That transform is: " << transform.toXmlString() << endl; |
327 | 334 |
328 if (pida) { | 335 if (pida) { |
329 cerr << "NOTE: PluginInputDomainAdapter timestamp adjustment is " | 336 SVCERR << "NOTE: PluginInputDomainAdapter timestamp adjustment is " |
330 | |
331 << pida->getTimestampAdjustment() << endl; | 337 << pida->getTimestampAdjustment() << endl; |
332 } | 338 } |
333 | 339 |
334 } else { | 340 } else { |
335 | 341 |
356 } | 362 } |
357 | 363 |
358 if (transform.getPluginVersion() != "") { | 364 if (transform.getPluginVersion() != "") { |
359 if (QString("%1").arg(plugin->getPluginVersion()) | 365 if (QString("%1").arg(plugin->getPluginVersion()) |
360 != transform.getPluginVersion()) { | 366 != transform.getPluginVersion()) { |
361 cerr << "ERROR: Transform specifies version " | 367 SVCERR << "ERROR: Transform specifies version " |
362 << transform.getPluginVersion() | 368 << transform.getPluginVersion() |
363 << " of plugin \"" << plugin->getIdentifier() | 369 << " of plugin \"" << plugin->getIdentifier() |
364 << "\", but installed plugin is version " | 370 << "\", but installed plugin is version " |
365 << plugin->getPluginVersion() | 371 << plugin->getPluginVersion() |
366 << endl; | 372 << endl; |
373 (plugin->getOutputDescriptors()[0].identifier.c_str()); | 379 (plugin->getOutputDescriptors()[0].identifier.c_str()); |
374 } else { | 380 } else { |
375 if (m_pluginOutputs[plugin].find | 381 if (m_pluginOutputs[plugin].find |
376 (transform.getOutput().toLocal8Bit().data()) == | 382 (transform.getOutput().toLocal8Bit().data()) == |
377 m_pluginOutputs[plugin].end()) { | 383 m_pluginOutputs[plugin].end()) { |
378 cerr << "ERROR: Transform requests nonexistent plugin output \"" | 384 SVCERR << "ERROR: Transform requests nonexistent plugin output \"" |
379 << transform.getOutput() | 385 << transform.getOutput() |
380 << "\"" << endl; | 386 << "\"" << endl; |
381 return false; | 387 return false; |
382 } | 388 } |
383 } | 389 } |
384 | 390 |
385 m_transformPluginMap[transform] = plugin; | 391 m_transformPluginMap[transform] = plugin; |
386 | 392 |
387 // cerr << "NOTE: Assigned plugin " << plugin << " for transform: " << transform.toXmlString() << endl; | 393 SVDEBUG << "NOTE: Assigned plugin " << plugin << " for transform: " << transform.toXmlString() << endl; |
388 | 394 |
389 if (!(originalTransform == transform)) { | 395 if (!(originalTransform == transform)) { |
390 m_transformPluginMap[originalTransform] = plugin; | 396 m_transformPluginMap[originalTransform] = plugin; |
391 // cerr << "NOTE: Also assigned plugin " << plugin << " for original transform: " << originalTransform.toXmlString() << endl; | 397 SVDEBUG << "NOTE: Also assigned plugin " << plugin << " for original transform: " << originalTransform.toXmlString() << endl; |
392 } | 398 } |
393 | 399 |
394 } else { | 400 } else { |
395 | 401 |
396 plugin = m_transformPluginMap[transform]; | 402 plugin = m_transformPluginMap[transform]; |
410 { | 416 { |
411 TransformFactory *tf = TransformFactory::getInstance(); | 417 TransformFactory *tf = TransformFactory::getInstance(); |
412 | 418 |
413 if (m_sampleRate == 0) { | 419 if (m_sampleRate == 0) { |
414 if (m_defaultSampleRate == 0) { | 420 if (m_defaultSampleRate == 0) { |
415 cerr << "ERROR: Default transform requested, but no default sample rate available" << endl; | 421 SVCERR << "ERROR: Default transform requested, but no default sample rate available" << endl; |
416 return false; | 422 return false; |
417 } else { | 423 } else { |
418 cerr << "NOTE: Using default sample rate of " << m_defaultSampleRate << " for default transform" << endl; | 424 SVCERR << "NOTE: Using default sample rate of " << m_defaultSampleRate << " for default transform" << endl; |
419 m_sampleRate = m_defaultSampleRate; | 425 m_sampleRate = m_defaultSampleRate; |
420 } | 426 } |
421 } | 427 } |
422 | 428 |
423 Transform transform = tf->getDefaultTransformFor(transformId, m_sampleRate); | 429 Transform transform = tf->getDefaultTransformFor(transformId, m_sampleRate); |
424 | 430 |
425 bool result = addFeatureExtractor(transform, writers); | 431 bool result = addFeatureExtractor(transform, writers); |
426 if (!result) { | 432 if (!result) { |
427 if (transform.getType() == Transform::UnknownType) { | 433 if (transform.getType() == Transform::UnknownType) { |
428 cerr << "(Maybe mixed up filename with transform, or --transform with --default?)" << endl; | 434 SVCERR << "(Maybe mixed up filename with transform, or --transform with --default?)" << endl; |
429 } | 435 } |
430 } | 436 } |
431 return result; | 437 return result; |
432 } | 438 } |
433 | 439 |
452 // We don't actually need to open this here yet, we just hoist | 458 // We don't actually need to open this here yet, we just hoist |
453 // it to the top for error reporting purposes | 459 // it to the top for error reporting purposes |
454 QFile file(transformFile); | 460 QFile file(transformFile); |
455 if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { | 461 if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { |
456 // Error case 1. File does not exist or cannot be opened | 462 // Error case 1. File does not exist or cannot be opened |
457 cerr << "ERROR: Failed to open transform file \"" << transformFile | 463 SVCERR << "ERROR: Failed to open transform file \"" << transformFile |
458 << "\" for reading" << endl; | 464 << "\" for reading" << endl; |
459 return false; | 465 return false; |
460 } | 466 } |
461 } | 467 } |
462 | 468 |
482 | 488 |
483 RDFTransformFactory factory | 489 RDFTransformFactory factory |
484 (QUrl::fromLocalFile(QFileInfo(transformFile).absoluteFilePath()) | 490 (QUrl::fromLocalFile(QFileInfo(transformFile).absoluteFilePath()) |
485 .toString()); | 491 .toString()); |
486 ProgressPrinter printer("Parsing transforms RDF file"); | 492 ProgressPrinter printer("Parsing transforms RDF file"); |
487 std::vector<Transform> transforms = factory.getTransforms(&printer); | 493 std::vector<Transform> transforms = factory.getTransforms |
494 (m_verbose ? &printer : 0); | |
488 | 495 |
489 if (factory.isOK()) { | 496 if (factory.isOK()) { |
490 if (transforms.empty()) { | 497 if (transforms.empty()) { |
491 cerr << "ERROR: Transform file \"" << transformFile | 498 SVCERR << "ERROR: Transform file \"" << transformFile |
492 << "\" is valid RDF but defines no transforms" << endl; | 499 << "\" is valid RDF but defines no transforms" << endl; |
493 return false; | 500 return false; |
494 } else { | 501 } else { |
495 bool success = true; | 502 bool success = true; |
496 for (int i = 0; i < (int)transforms.size(); ++i) { | 503 for (int i = 0; i < (int)transforms.size(); ++i) { |
500 } | 507 } |
501 return success; | 508 return success; |
502 } | 509 } |
503 } else { // !factory.isOK() | 510 } else { // !factory.isOK() |
504 if (factory.isRDF()) { | 511 if (factory.isRDF()) { |
505 cerr << "ERROR: Invalid transform RDF file \"" << transformFile | 512 SVCERR << "ERROR: Invalid transform RDF file \"" << transformFile |
506 << "\": " << factory.getErrorString() << endl; | 513 << "\": " << factory.getErrorString() << endl; |
507 return false; | 514 return false; |
508 } | 515 } |
509 | 516 |
510 // the not-RDF case: fall through without reporting an | 517 // the not-RDF case: fall through without reporting an |
516 | 523 |
517 if (tryXml) { | 524 if (tryXml) { |
518 | 525 |
519 QFile file(transformFile); | 526 QFile file(transformFile); |
520 if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { | 527 if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { |
521 cerr << "ERROR: Failed to open transform file \"" | 528 SVCERR << "ERROR: Failed to open transform file \"" |
522 << transformFile.toStdString() << "\" for reading" << endl; | 529 << transformFile.toStdString() << "\" for reading" << endl; |
523 return false; | 530 return false; |
524 } | 531 } |
525 | 532 |
526 QTextStream *qts = new QTextStream(&file); | 533 QTextStream *qts = new QTextStream(&file); |
532 xmlError = transform.getErrorString(); | 539 xmlError = transform.getErrorString(); |
533 | 540 |
534 if (xmlError == "") { | 541 if (xmlError == "") { |
535 | 542 |
536 if (transform.getIdentifier() == "") { | 543 if (transform.getIdentifier() == "") { |
537 cerr << "ERROR: Transform file \"" << transformFile | 544 SVCERR << "ERROR: Transform file \"" << transformFile |
538 << "\" is valid XML but defines no transform" << endl; | 545 << "\" is valid XML but defines no transform" << endl; |
539 return false; | 546 return false; |
540 } | 547 } |
541 | 548 |
542 return addFeatureExtractor(transform, writers); | 549 return addFeatureExtractor(transform, writers); |
543 } | 550 } |
544 } | 551 } |
545 | 552 |
546 cerr << "ERROR: Transform file \"" << transformFile | 553 SVCERR << "ERROR: Transform file \"" << transformFile |
547 << "\" could not be parsed" << endl; | 554 << "\" could not be parsed" << endl; |
548 if (rdfError != "") { | 555 if (rdfError != "") { |
549 cerr << "ERROR: RDF parser reported: " << rdfError << endl; | 556 SVCERR << "ERROR: RDF parser reported: " << rdfError << endl; |
550 } | 557 } |
551 if (xmlError != "") { | 558 if (xmlError != "") { |
552 cerr << "ERROR: XML parser reported: " << xmlError << endl; | 559 SVCERR << "ERROR: XML parser reported: " << xmlError << endl; |
553 } | 560 } |
554 | 561 |
555 return false; | 562 return false; |
556 } | 563 } |
557 | 564 |
558 void FeatureExtractionManager::addSource(QString audioSource, bool willMultiplex) | 565 void FeatureExtractionManager::addSource(QString audioSource, bool willMultiplex) |
559 { | 566 { |
560 std::cerr << "Have audio source: \"" << audioSource.toStdString() << "\"" << std::endl; | 567 SVCERR << "Have audio source: \"" << audioSource.toStdString() << "\"" << endl; |
561 | 568 |
562 // We don't actually do anything with it here, unless it's the | 569 // We don't actually do anything with it here, unless it's the |
563 // first audio source and we need it to establish default channel | 570 // first audio source and we need it to establish default channel |
564 // count and sample rate | 571 // count and sample rate |
565 | 572 |
566 if (m_channels == 0 || m_defaultSampleRate == 0) { | 573 if (m_channels == 0 || m_defaultSampleRate == 0) { |
567 | 574 |
568 ProgressPrinter retrievalProgress("Retrieving first input file to determine default rate and channel count..."); | 575 ProgressPrinter retrievalProgress("Retrieving first input file to determine default rate and channel count..."); |
569 | 576 |
570 FileSource source(audioSource, &retrievalProgress); | 577 FileSource source(audioSource, m_verbose ? &retrievalProgress : 0); |
571 if (!source.isAvailable()) { | 578 if (!source.isAvailable()) { |
572 cerr << "ERROR: File or URL \"" << audioSource.toStdString() | 579 SVCERR << "ERROR: File or URL \"" << audioSource.toStdString() |
573 << "\" could not be located"; | 580 << "\" could not be located"; |
574 if (source.getErrorString() != "") { | 581 if (source.getErrorString() != "") { |
575 cerr << ": " << source.getErrorString(); | 582 SVCERR << ": " << source.getErrorString(); |
576 } | 583 } |
577 cerr << endl; | 584 SVCERR << endl; |
578 throw FileNotFound(audioSource); | 585 throw FileNotFound(audioSource); |
579 } | 586 } |
580 | 587 |
581 source.waitForData(); | 588 source.waitForData(); |
582 | 589 |
583 // Open to determine validity, channel count, sample rate only | 590 // Open to determine validity, channel count, sample rate only |
584 // (then close, and open again later with actual desired rate &c) | 591 // (then close, and open again later with actual desired rate &c) |
585 | 592 |
586 AudioFileReader *reader = | 593 AudioFileReader *reader = |
587 AudioFileReaderFactory::createReader(source, 0, | 594 AudioFileReaderFactory::createReader |
588 m_normalise, | 595 (source, 0, m_normalise, m_verbose ? &retrievalProgress : 0); |
589 &retrievalProgress); | |
590 | 596 |
591 if (!reader) { | 597 if (!reader) { |
592 throw FailedToOpenFile(audioSource); | 598 throw FailedToOpenFile(audioSource); |
593 } | 599 } |
594 | 600 |
595 retrievalProgress.done(); | 601 if (m_verbose) retrievalProgress.done(); |
596 | 602 |
597 cerr << "File or URL \"" << audioSource.toStdString() << "\" opened successfully" << endl; | 603 SVCERR << "File or URL \"" << audioSource.toStdString() << "\" opened successfully" << endl; |
598 | 604 |
599 if (!willMultiplex) { | 605 if (!willMultiplex) { |
600 if (m_channels == 0) { | 606 if (m_channels == 0) { |
601 m_channels = reader->getChannelCount(); | 607 m_channels = reader->getChannelCount(); |
602 cerr << "Taking default channel count of " | 608 SVCERR << "Taking default channel count of " |
603 << reader->getChannelCount() << " from audio file" << endl; | 609 << reader->getChannelCount() << " from audio file" << endl; |
604 } | 610 } |
605 } | 611 } |
606 | 612 |
607 if (m_defaultSampleRate == 0) { | 613 if (m_defaultSampleRate == 0) { |
608 m_defaultSampleRate = reader->getNativeRate(); | 614 m_defaultSampleRate = reader->getNativeRate(); |
609 cerr << "Taking default sample rate of " | 615 SVCERR << "Taking default sample rate of " |
610 << reader->getNativeRate() << "Hz from audio file" << endl; | 616 << reader->getNativeRate() << "Hz from audio file" << endl; |
611 cerr << "(Note: Default may be overridden by transforms)" << endl; | 617 SVCERR << "(Note: Default may be overridden by transforms)" << endl; |
612 } | 618 } |
613 | 619 |
614 m_readyReaders[audioSource] = reader; | 620 m_readyReaders[audioSource] = reader; |
615 } | 621 } |
616 | 622 |
617 if (willMultiplex) { | 623 if (willMultiplex) { |
618 ++m_channels; // channel count is simply number of sources | 624 ++m_channels; // channel count is simply number of sources |
619 cerr << "Multiplexing, incremented target channel count to " | 625 SVCERR << "Multiplexing, incremented target channel count to " |
620 << m_channels << endl; | 626 << m_channels << endl; |
621 } | 627 } |
622 } | 628 } |
623 | 629 |
624 void FeatureExtractionManager::extractFeatures(QString audioSource) | 630 void FeatureExtractionManager::extractFeatures(QString audioSource) |
680 reader = 0; | 686 reader = 0; |
681 } | 687 } |
682 } | 688 } |
683 if (!reader) { | 689 if (!reader) { |
684 ProgressPrinter retrievalProgress("Retrieving audio data..."); | 690 ProgressPrinter retrievalProgress("Retrieving audio data..."); |
685 FileSource fs(source, &retrievalProgress); | 691 FileSource fs(source, m_verbose ? &retrievalProgress : 0); |
686 fs.waitForData(); | 692 fs.waitForData(); |
687 reader = AudioFileReaderFactory::createReader(fs, m_sampleRate, | 693 reader = AudioFileReaderFactory::createReader |
688 m_normalise, | 694 (fs, m_sampleRate, m_normalise, m_verbose ? &retrievalProgress : 0); |
689 &retrievalProgress); | 695 if (m_verbose) retrievalProgress.done(); |
690 retrievalProgress.done(); | |
691 } | 696 } |
692 if (!reader) { | 697 if (!reader) { |
693 throw FailedToOpenFile(source); | 698 throw FailedToOpenFile(source); |
694 } | 699 } |
695 if (reader->getChannelCount() != m_channels || | 700 if (reader->getChannelCount() != m_channels || |
696 reader->getNativeRate() != m_sampleRate) { | 701 reader->getNativeRate() != m_sampleRate) { |
697 cerr << "NOTE: File will be mixed or resampled for processing, to: " | 702 SVCERR << "NOTE: File will be mixed or resampled for processing, to: " |
698 << m_channels << "ch at " | 703 << m_channels << "ch at " |
699 << m_sampleRate << "Hz" << endl; | 704 << m_sampleRate << "Hz" << endl; |
700 } | 705 } |
701 return reader; | 706 return reader; |
702 } | 707 } |
705 FeatureExtractionManager::extractFeaturesFor(AudioFileReader *reader, | 710 FeatureExtractionManager::extractFeaturesFor(AudioFileReader *reader, |
706 QString audioSource) | 711 QString audioSource) |
707 { | 712 { |
708 // Note: This also deletes reader | 713 // Note: This also deletes reader |
709 | 714 |
710 cerr << "Audio file \"" << audioSource.toStdString() << "\": " | 715 SVCERR << "Audio file \"" << audioSource.toStdString() << "\": " |
711 << reader->getChannelCount() << "ch at " | 716 << reader->getChannelCount() << "ch at " |
712 << reader->getNativeRate() << "Hz" << endl; | 717 << reader->getNativeRate() << "Hz" << endl; |
713 | 718 |
714 // allocate audio buffers | 719 // allocate audio buffers |
715 float **data = new float *[m_channels]; | 720 float **data = new float *[m_channels]; |
735 }; | 740 }; |
736 LifespanMgr lifemgr(reader, m_channels, data); | 741 LifespanMgr lifemgr(reader, m_channels, data); |
737 | 742 |
738 size_t frameCount = reader->getFrameCount(); | 743 size_t frameCount = reader->getFrameCount(); |
739 | 744 |
740 // cerr << "file has " << frameCount << " frames" << endl; | 745 SVDEBUG << "FeatureExtractionManager: file has " << frameCount << " frames" << endl; |
741 | 746 |
742 int earliestStartFrame = 0; | 747 int earliestStartFrame = 0; |
743 int latestEndFrame = frameCount; | 748 int latestEndFrame = frameCount; |
744 bool haveExtents = false; | 749 bool haveExtents = false; |
745 | 750 |
746 foreach (Plugin *plugin, m_orderedPlugins) { | 751 foreach (Plugin *plugin, m_orderedPlugins) { |
747 | 752 |
748 PluginMap::iterator pi = m_plugins.find(plugin); | 753 PluginMap::iterator pi = m_plugins.find(plugin); |
749 | 754 |
750 // std::cerr << "Calling reset on " << plugin << std::endl; | 755 SVDEBUG << "FeatureExtractionManager: Calling reset on " << plugin << endl; |
751 plugin->reset(); | 756 plugin->reset(); |
752 | 757 |
753 for (TransformWriterMap::iterator ti = pi->second.begin(); | 758 for (TransformWriterMap::iterator ti = pi->second.begin(); |
754 ti != pi->second.end(); ++ti) { | 759 ti != pi->second.end(); ++ti) { |
755 | 760 |
767 earliestStartFrame = startFrame; | 772 earliestStartFrame = startFrame; |
768 } | 773 } |
769 if (!haveExtents || startFrame + duration > latestEndFrame) { | 774 if (!haveExtents || startFrame + duration > latestEndFrame) { |
770 latestEndFrame = startFrame + duration; | 775 latestEndFrame = startFrame + duration; |
771 } | 776 } |
777 | |
772 /* | 778 /* |
773 cerr << "startFrame for transform " << startFrame << endl; | 779 SVDEBUG << "startFrame for transform " << startFrame << endl; |
774 cerr << "duration for transform " << duration << endl; | 780 SVDEBUG << "duration for transform " << duration << endl; |
775 cerr << "earliestStartFrame becomes " << earliestStartFrame << endl; | 781 SVDEBUG << "earliestStartFrame becomes " << earliestStartFrame << endl; |
776 cerr << "latestEndFrame becomes " << latestEndFrame << endl; | 782 SVDEBUG << "latestEndFrame becomes " << latestEndFrame << endl; |
777 */ | 783 */ |
778 haveExtents = true; | 784 haveExtents = true; |
779 | 785 |
780 string outputId = transform.getOutput().toStdString(); | 786 string outputId = transform.getOutput().toStdString(); |
781 if (m_pluginOutputs[plugin].find(outputId) == | 787 if (m_pluginOutputs[plugin].find(outputId) == |
782 m_pluginOutputs[plugin].end()) { | 788 m_pluginOutputs[plugin].end()) { |
783 // We shouldn't actually reach this point: | 789 // We shouldn't actually reach this point: |
784 // addFeatureExtractor tests whether the output exists | 790 // addFeatureExtractor tests whether the output exists |
785 cerr << "ERROR: Nonexistent plugin output \"" << outputId << "\" requested for transform \"" | 791 SVCERR << "ERROR: Nonexistent plugin output \"" << outputId << "\" requested for transform \"" |
786 << transform.getIdentifier().toStdString() << "\", ignoring this transform" | 792 << transform.getIdentifier().toStdString() << "\", ignoring this transform" |
787 << endl; | 793 << endl; |
788 /* | 794 |
789 cerr << "Known outputs for all plugins are as follows:" << endl; | 795 SVDEBUG << "Known outputs for all plugins are as follows:" << endl; |
790 for (PluginOutputMap::const_iterator k = m_pluginOutputs.begin(); | 796 for (PluginOutputMap::const_iterator k = m_pluginOutputs.begin(); |
791 k != m_pluginOutputs.end(); ++k) { | 797 k != m_pluginOutputs.end(); ++k) { |
792 cerr << "Plugin " << k->first << ": "; | 798 SVDEBUG << "Plugin " << k->first << ": "; |
793 if (k->second.empty()) { | 799 if (k->second.empty()) { |
794 cerr << "(none)"; | 800 SVDEBUG << "(none)"; |
795 } | 801 } |
796 for (OutputMap::const_iterator i = k->second.begin(); | 802 for (OutputMap::const_iterator i = k->second.begin(); |
797 i != k->second.end(); ++i) { | 803 i != k->second.end(); ++i) { |
798 cerr << "\"" << i->first << "\" "; | 804 SVDEBUG << "\"" << i->first << "\" "; |
799 } | 805 } |
800 cerr << endl; | 806 SVDEBUG << endl; |
801 } | 807 } |
802 */ | |
803 } | 808 } |
804 } | 809 } |
805 } | 810 } |
806 | 811 |
807 int startFrame = earliestStartFrame; | 812 int startFrame = earliestStartFrame; |
909 } | 914 } |
910 } | 915 } |
911 | 916 |
912 int pp = progress; | 917 int pp = progress; |
913 progress = int(((i - startFrame) * 100.0) / (endFrame - startFrame) + 0.1); | 918 progress = int(((i - startFrame) * 100.0) / (endFrame - startFrame) + 0.1); |
914 if (progress > pp) extractionProgress.setProgress(progress); | 919 if (progress > pp && m_verbose) extractionProgress.setProgress(progress); |
915 } | 920 } |
916 | 921 |
917 // std::cerr << "FeatureExtractionManager: deleting audio file reader" << std::endl; | 922 SVDEBUG << "FeatureExtractionManager: deleting audio file reader" << endl; |
918 | 923 |
919 lifemgr.destroy(); // deletes reader, data | 924 lifemgr.destroy(); // deletes reader, data |
920 | 925 |
921 foreach (Plugin *plugin, m_orderedPlugins) { | 926 foreach (Plugin *plugin, m_orderedPlugins) { |
922 | 927 |
930 if (!m_summaries.empty()) { | 935 if (!m_summaries.empty()) { |
931 // Summaries requested on the command line, for all transforms | 936 // Summaries requested on the command line, for all transforms |
932 PluginSummarisingAdapter *adapter = | 937 PluginSummarisingAdapter *adapter = |
933 dynamic_cast<PluginSummarisingAdapter *>(plugin); | 938 dynamic_cast<PluginSummarisingAdapter *>(plugin); |
934 if (!adapter) { | 939 if (!adapter) { |
935 cerr << "WARNING: Summaries requested, but plugin is not a summarising adapter" << endl; | 940 SVCERR << "WARNING: Summaries requested, but plugin is not a summarising adapter" << endl; |
936 } else { | 941 } else { |
937 for (SummaryNameSet::const_iterator sni = m_summaries.begin(); | 942 for (SummaryNameSet::const_iterator sni = m_summaries.begin(); |
938 sni != m_summaries.end(); ++sni) { | 943 sni != m_summaries.end(); ++sni) { |
939 featureSet.clear(); | 944 featureSet.clear(); |
940 //!!! problem here -- we are requesting summaries | 945 //!!! problem here -- we are requesting summaries |
953 | 958 |
954 // Summaries specified in transform definitions themselves | 959 // Summaries specified in transform definitions themselves |
955 writeSummaries(audioSource, plugin); | 960 writeSummaries(audioSource, plugin); |
956 } | 961 } |
957 | 962 |
958 extractionProgress.done(); | 963 if (m_verbose) extractionProgress.done(); |
959 | 964 |
960 finish(); | 965 finish(); |
961 | 966 |
962 TempDirectory::getInstance()->cleanup(); | 967 TempDirectory::getInstance()->cleanup(); |
963 } | 968 } |
971 for (TransformWriterMap::const_iterator ti = pi->second.begin(); | 976 for (TransformWriterMap::const_iterator ti = pi->second.begin(); |
972 ti != pi->second.end(); ++ti) { | 977 ti != pi->second.end(); ++ti) { |
973 | 978 |
974 const Transform &transform = ti->first; | 979 const Transform &transform = ti->first; |
975 | 980 |
976 // cerr << "FeatureExtractionManager::writeSummaries: plugin is " << plugin | 981 SVDEBUG << "FeatureExtractionManager::writeSummaries: plugin is " << plugin |
977 // << ", found transform: " << transform.toXmlString() << endl; | 982 << ", found transform: " << transform.toXmlString() << endl; |
978 | 983 |
979 Transform::SummaryType summaryType = transform.getSummaryType(); | 984 Transform::SummaryType summaryType = transform.getSummaryType(); |
980 PluginSummarisingAdapter::SummaryType pType = | 985 PluginSummarisingAdapter::SummaryType pType = |
981 (PluginSummarisingAdapter::SummaryType)summaryType; | 986 (PluginSummarisingAdapter::SummaryType)summaryType; |
982 | 987 |
983 if (transform.getSummaryType() == Transform::NoSummary) { | 988 if (transform.getSummaryType() == Transform::NoSummary) { |
984 // cerr << "(no summary, continuing)" << endl; | 989 SVDEBUG << "FeatureExtractionManager::writeSummaries: no summary for this transform" << endl; |
985 continue; | 990 continue; |
986 } | 991 } |
987 | 992 |
988 PluginSummarisingAdapter *adapter = | 993 PluginSummarisingAdapter *adapter = |
989 dynamic_cast<PluginSummarisingAdapter *>(plugin); | 994 dynamic_cast<PluginSummarisingAdapter *>(plugin); |
990 if (!adapter) { | 995 if (!adapter) { |
991 cerr << "FeatureExtractionManager::writeSummaries: INTERNAL ERROR: Summary requested for transform, but plugin is not a summarising adapter" << endl; | 996 SVCERR << "FeatureExtractionManager::writeSummaries: INTERNAL ERROR: Summary requested for transform, but plugin is not a summarising adapter" << endl; |
992 continue; | 997 continue; |
993 } | 998 } |
994 | 999 |
995 Plugin::FeatureSet featureSet = adapter->getSummaryForAllOutputs | 1000 Plugin::FeatureSet featureSet = adapter->getSummaryForAllOutputs |
996 (pType, PluginSummarisingAdapter::ContinuousTimeAverage); | 1001 (pType, PluginSummarisingAdapter::ContinuousTimeAverage); |
997 | 1002 |
998 // cerr << "summary type " << int(pType) << " for transform:" << endl << transform.toXmlString().toStdString()<< endl << "... feature set with " << featureSet.size() << " elts" << endl; | 1003 SVDEBUG << "summary type " << int(pType) << " for transform:" << endl << transform.toXmlString().toStdString()<< endl << "... feature set with " << featureSet.size() << " elts" << endl; |
999 | 1004 |
1000 writeFeatures(audioSource, plugin, featureSet, summaryType); | 1005 writeFeatures(audioSource, plugin, featureSet, summaryType); |
1001 } | 1006 } |
1002 } | 1007 } |
1003 | 1008 |
1016 ti != pi->second.end(); ++ti) { | 1021 ti != pi->second.end(); ++ti) { |
1017 | 1022 |
1018 const Transform &transform = ti->first; | 1023 const Transform &transform = ti->first; |
1019 const vector<FeatureWriter *> &writers = ti->second; | 1024 const vector<FeatureWriter *> &writers = ti->second; |
1020 | 1025 |
1021 // cerr << "writeFeatures: plugin " << plugin << " has transform: " << transform.toXmlString() << endl; | 1026 // SVDEBUG << "writeFeatures: plugin " << plugin << " has transform: " << transform.toXmlString() << endl; |
1022 | 1027 |
1023 if (transform.getSummaryType() == Transform::NoSummary && | 1028 if (transform.getSummaryType() == Transform::NoSummary && |
1024 !m_summaries.empty()) { | 1029 !m_summaries.empty()) { |
1025 // cerr << "transform has no summary, but summaries requested on command line, so going for it anyway" << endl; | 1030 SVDEBUG << "transform has no summary, but summaries requested on command line, so going for it anyway" << endl; |
1026 } else if (transform.getSummaryType() != summaryType) { | 1031 } else if (transform.getSummaryType() != summaryType) { |
1027 // Either we're not writing a summary and the transform | 1032 // Either we're not writing a summary and the transform |
1028 // has one, or we're writing a summary but the transform | 1033 // has one, or we're writing a summary but the transform |
1029 // has none or a different one; either way, skip it | 1034 // has none or a different one; either way, skip it |
1030 // cerr << "summary type differs from passed-in one " << summaryType << endl; | 1035 SVDEBUG << "summary type differs from passed-in one " << summaryType << endl; |
1031 continue; | 1036 continue; |
1032 } | 1037 } |
1033 | 1038 |
1034 string outputId = transform.getOutput().toStdString(); | 1039 string outputId = transform.getOutput().toStdString(); |
1035 | 1040 |
1043 | 1048 |
1044 int outputIndex = m_pluginOutputIndices[outputId]; | 1049 int outputIndex = m_pluginOutputIndices[outputId]; |
1045 Plugin::FeatureSet::const_iterator fsi = features.find(outputIndex); | 1050 Plugin::FeatureSet::const_iterator fsi = features.find(outputIndex); |
1046 if (fsi == features.end()) continue; | 1051 if (fsi == features.end()) continue; |
1047 | 1052 |
1048 // cerr << "this transform has " << writers.size() << " writer(s)" << endl; | 1053 // SVDEBUG << "this transform has " << writers.size() << " writer(s)" << endl; |
1049 | 1054 |
1050 for (int j = 0; j < (int)writers.size(); ++j) { | 1055 for (int j = 0; j < (int)writers.size(); ++j) { |
1051 writers[j]->write | 1056 writers[j]->write |
1052 (audioSource, transform, desc, fsi->second, | 1057 (audioSource, transform, desc, fsi->second, |
1053 Transform::summaryTypeToString(summaryType).toStdString()); | 1058 Transform::summaryTypeToString(summaryType).toStdString()); |