comparison vamp-sdk/hostext/PluginBufferingAdapter.cpp @ 134:c1dce0b033cb

* Permit '-' as well as the other characters in identifiers (existing plugins were already using this character, it's really the documentation that was at fault) * Fix failure to return output descriptors properly from PluginBufferingAdapter * Fix incorrect sample rate in output descriptors for certain sample types from PluginBufferingAdapter * Fix incorrect timestamping on features returned from PluginBufferingAdapter (rounding error)
author cannam
date Thu, 24 Apr 2008 10:27:02 +0000
parents 92ca8e401044
children af8e59f43d1d
comparison
equal deleted inserted replaced
133:92ca8e401044 134:c1dce0b033cb
225 size_t m_blockSize; 225 size_t m_blockSize;
226 size_t m_channels; 226 size_t m_channels;
227 vector<RingBuffer *> m_queue; 227 vector<RingBuffer *> m_queue;
228 float **m_buffers; 228 float **m_buffers;
229 float m_inputSampleRate; 229 float m_inputSampleRate;
230 RealTime m_timestamp; 230 long m_frame;
231 bool m_unrun; 231 bool m_unrun;
232 mutable OutputList m_outputs; 232 mutable OutputList m_outputs;
233 mutable std::map<int, bool> m_rewriteOutputTimes; 233 mutable std::map<int, bool> m_rewriteOutputTimes;
234 234
235 void processBlock(FeatureSet& allFeatureSets, RealTime timestamp); 235 void processBlock(FeatureSet& allFeatureSets);
236 }; 236 };
237 237
238 PluginBufferingAdapter::PluginBufferingAdapter(Plugin *plugin) : 238 PluginBufferingAdapter::PluginBufferingAdapter(Plugin *plugin) :
239 PluginWrapper(plugin) 239 PluginWrapper(plugin)
240 { 240 {
285 m_blockSize(0), 285 m_blockSize(0),
286 m_channels(0), 286 m_channels(0),
287 m_queue(0), 287 m_queue(0),
288 m_buffers(0), 288 m_buffers(0),
289 m_inputSampleRate(inputSampleRate), 289 m_inputSampleRate(inputSampleRate),
290 m_timestamp(RealTime::zeroTime), 290 m_frame(0),
291 m_unrun(true) 291 m_unrun(true)
292 { 292 {
293 (void)getOutputDescriptors(); // set up m_outputs and m_rewriteOutputTimes 293 (void)getOutputDescriptors(); // set up m_outputs and m_rewriteOutputTimes
294 } 294 }
295 295
368 { 368 {
369 if (m_outputs.empty()) { 369 if (m_outputs.empty()) {
370 m_outputs = m_plugin->getOutputDescriptors(); 370 m_outputs = m_plugin->getOutputDescriptors();
371 } 371 }
372 372
373 PluginBufferingAdapter::OutputList outs; 373 PluginBufferingAdapter::OutputList outs = m_outputs;
374 374
375 for (size_t i = 0; i < outs.size(); ++i) { 375 for (size_t i = 0; i < outs.size(); ++i) {
376 376
377 switch (outs[i].sampleType) { 377 switch (outs[i].sampleType) {
378 378
379 case OutputDescriptor::OneSamplePerStep: 379 case OutputDescriptor::OneSamplePerStep:
380 outs[i].sampleType = OutputDescriptor::FixedSampleRate; 380 outs[i].sampleType = OutputDescriptor::FixedSampleRate;
381 outs[i].sampleRate = 1.f / m_stepSize; 381 outs[i].sampleRate = (1.f / m_inputSampleRate) * m_stepSize;
382 m_rewriteOutputTimes[i] = true; 382 m_rewriteOutputTimes[i] = true;
383 break; 383 break;
384 384
385 case OutputDescriptor::FixedSampleRate: 385 case OutputDescriptor::FixedSampleRate:
386 if (outs[i].sampleRate == 0.f) { 386 if (outs[i].sampleRate == 0.f) {
387 outs[i].sampleRate = 1.f / m_stepSize; 387 outs[i].sampleRate = (1.f / m_inputSampleRate) * m_stepSize;
388 } 388 }
389 // We actually only need to rewrite output times for 389 // We actually only need to rewrite output times for
390 // features that don't have timestamps already, but we 390 // features that don't have timestamps already, but we
391 // can't tell from here whether our features will have 391 // can't tell from here whether our features will have
392 // timestamps or not 392 // timestamps or not
403 } 403 }
404 404
405 void 405 void
406 PluginBufferingAdapter::Impl::reset() 406 PluginBufferingAdapter::Impl::reset()
407 { 407 {
408 m_timestamp = RealTime::zeroTime; 408 m_frame = 0;
409 m_unrun = true; 409 m_unrun = true;
410 410
411 for (size_t i = 0; i < m_queue.size(); ++i) { 411 for (size_t i = 0; i < m_queue.size(); ++i) {
412 m_queue[i]->reset(); 412 m_queue[i]->reset();
413 } 413 }
418 RealTime timestamp) 418 RealTime timestamp)
419 { 419 {
420 FeatureSet allFeatureSets; 420 FeatureSet allFeatureSets;
421 421
422 if (m_unrun) { 422 if (m_unrun) {
423 m_timestamp = timestamp; 423 m_frame = RealTime::realTime2Frame(timestamp,
424 int(m_inputSampleRate + 0.5));
424 m_unrun = false; 425 m_unrun = false;
425 } 426 }
426 427
427 // queue the new input 428 // queue the new input
428 429
439 } 440 }
440 441
441 // process as much as we can 442 // process as much as we can
442 443
443 while (m_queue[0]->getReadSpace() >= int(m_blockSize)) { 444 while (m_queue[0]->getReadSpace() >= int(m_blockSize)) {
444 processBlock(allFeatureSets, timestamp); 445 processBlock(allFeatureSets);
445 } 446 }
446 447
447 return allFeatureSets; 448 return allFeatureSets;
448 } 449 }
449 450
452 { 453 {
453 FeatureSet allFeatureSets; 454 FeatureSet allFeatureSets;
454 455
455 // process remaining samples in queue 456 // process remaining samples in queue
456 while (m_queue[0]->getReadSpace() >= int(m_blockSize)) { 457 while (m_queue[0]->getReadSpace() >= int(m_blockSize)) {
457 processBlock(allFeatureSets, m_timestamp); 458 processBlock(allFeatureSets);
458 } 459 }
459 460
460 // pad any last samples remaining and process 461 // pad any last samples remaining and process
461 if (m_queue[0]->getReadSpace() > 0) { 462 if (m_queue[0]->getReadSpace() > 0) {
462 for (size_t i = 0; i < m_channels; ++i) { 463 for (size_t i = 0; i < m_channels; ++i) {
463 m_queue[i]->zero(m_blockSize - m_queue[i]->getReadSpace()); 464 m_queue[i]->zero(m_blockSize - m_queue[i]->getReadSpace());
464 } 465 }
465 processBlock(allFeatureSets, m_timestamp); 466 processBlock(allFeatureSets);
466 } 467 }
467 468
468 // get remaining features 469 // get remaining features
469 470
470 FeatureSet featureSet = m_plugin->getRemainingFeatures(); 471 FeatureSet featureSet = m_plugin->getRemainingFeatures();
479 480
480 return allFeatureSets; 481 return allFeatureSets;
481 } 482 }
482 483
483 void 484 void
484 PluginBufferingAdapter::Impl::processBlock(FeatureSet& allFeatureSets, 485 PluginBufferingAdapter::Impl::processBlock(FeatureSet& allFeatureSets)
485 RealTime timestamp)
486 { 486 {
487 for (size_t i = 0; i < m_channels; ++i) { 487 for (size_t i = 0; i < m_channels; ++i) {
488 m_queue[i]->peek(m_buffers[i], m_blockSize); 488 m_queue[i]->peek(m_buffers[i], m_blockSize);
489 } 489 }
490 490
491 FeatureSet featureSet = m_plugin->process(m_buffers, m_timestamp); 491 long frame = m_frame;
492 RealTime timestamp = RealTime::frame2RealTime
493 (frame, int(m_inputSampleRate + 0.5));
494
495 FeatureSet featureSet = m_plugin->process(m_buffers, timestamp);
492 496
493 for (FeatureSet::iterator iter = featureSet.begin(); 497 for (FeatureSet::iterator iter = featureSet.begin();
494 iter != featureSet.end(); ++iter) { 498 iter != featureSet.end(); ++iter) {
495 499
496 int outputNo = iter->first; 500 int outputNo = iter->first;
497 501
498 if (m_rewriteOutputTimes[outputNo]) { 502 if (m_rewriteOutputTimes[outputNo]) {
499 503
500 // Make sure the timestamp is always set
501
502 FeatureList featureList = iter->second; 504 FeatureList featureList = iter->second;
503 505
504 for (size_t i = 0; i < featureList.size(); ++i) { 506 for (size_t i = 0; i < featureList.size(); ++i) {
505 507
506 switch (m_outputs[outputNo].sampleType) { 508 switch (m_outputs[outputNo].sampleType) {
507 509
508 case OutputDescriptor::OneSamplePerStep: 510 case OutputDescriptor::OneSamplePerStep:
509 // use our internal timestamp, always 511 // use our internal timestamp, always
510 featureList[i].timestamp = m_timestamp; 512 featureList[i].timestamp = timestamp;
511 featureList[i].hasTimestamp = true; 513 featureList[i].hasTimestamp = true;
512 break; 514 break;
513 515
514 case OutputDescriptor::FixedSampleRate: 516 case OutputDescriptor::FixedSampleRate:
515 // use our internal timestamp if feature lacks one 517 // use our internal timestamp if feature lacks one
516 if (!featureList[i].hasTimestamp) { 518 if (!featureList[i].hasTimestamp) {
517 featureList[i].timestamp = m_timestamp; 519 featureList[i].timestamp = timestamp;
518 featureList[i].hasTimestamp = true; 520 featureList[i].hasTimestamp = true;
519 } 521 }
520 break; 522 break;
521 523
522 case OutputDescriptor::VariableSampleRate: 524 case OutputDescriptor::VariableSampleRate:
539 541
540 for (size_t i = 0; i < m_channels; ++i) { 542 for (size_t i = 0; i < m_channels; ++i) {
541 m_queue[i]->skip(m_stepSize); 543 m_queue[i]->skip(m_stepSize);
542 } 544 }
543 545
544 // fake up the timestamp each time we step forward 546 // increment internal frame counter each time we step forward
545 547 m_frame += m_stepSize;
546 long frame = RealTime::realTime2Frame(m_timestamp,
547 int(m_inputSampleRate + 0.5));
548 m_timestamp = RealTime::frame2RealTime(frame + m_stepSize,
549 int(m_inputSampleRate + 0.5));
550 } 548 }
551 549
552 } 550 }
553 551
554 } 552 }