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());