Mercurial > hg > svapp
comparison audioio/AudioCallbackPlaySource.cpp @ 94:9cc9862333bd sv1-v1.2pre4
* a hack to try to prevent playback pointer bouncing back when playback starts
author | Chris Cannam |
---|---|
date | Mon, 11 Feb 2008 17:08:59 +0000 |
parents | 737b373246b5 |
children | e177e6ee7c12 |
comparison
equal
deleted
inserted
replaced
93:737b373246b5 | 94:9cc9862333bd |
---|---|
62 m_lastModelEndFrame(0), | 62 m_lastModelEndFrame(0), |
63 m_outputLeft(0.0), | 63 m_outputLeft(0.0), |
64 m_outputRight(0.0), | 64 m_outputRight(0.0), |
65 m_auditioningPlugin(0), | 65 m_auditioningPlugin(0), |
66 m_auditioningPluginBypassed(false), | 66 m_auditioningPluginBypassed(false), |
67 m_playStartFrame(0), | |
68 m_playStartFramePassed(false), | |
67 m_timeStretcher(0), | 69 m_timeStretcher(0), |
68 m_stretchRatio(1.0), | 70 m_stretchRatio(1.0), |
69 m_stretcherInputCount(0), | 71 m_stretcherInputCount(0), |
70 m_stretcherInputs(0), | 72 m_stretcherInputs(0), |
71 m_stretcherInputSizes(0), | 73 m_stretcherInputSizes(0), |
353 AudioCallbackPlaySource::play(size_t startFrame) | 355 AudioCallbackPlaySource::play(size_t startFrame) |
354 { | 356 { |
355 if (m_viewManager->getPlaySelectionMode() && | 357 if (m_viewManager->getPlaySelectionMode() && |
356 !m_viewManager->getSelections().empty()) { | 358 !m_viewManager->getSelections().empty()) { |
357 | 359 |
360 std::cerr << "AudioCallbackPlaySource::play: constraining frame " << startFrame << " to selection = "; | |
361 | |
358 startFrame = m_viewManager->constrainFrameToSelection(startFrame); | 362 startFrame = m_viewManager->constrainFrameToSelection(startFrame); |
363 | |
364 std::cerr << startFrame << std::endl; | |
359 | 365 |
360 } else { | 366 } else { |
361 if (startFrame >= m_lastModelEndFrame) { | 367 if (startFrame >= m_lastModelEndFrame) { |
362 startFrame = 0; | 368 startFrame = 0; |
363 } | 369 } |
396 } | 402 } |
397 m_mutex.unlock(); | 403 m_mutex.unlock(); |
398 | 404 |
399 m_audioGenerator->reset(); | 405 m_audioGenerator->reset(); |
400 | 406 |
407 m_playStartFrame = startFrame; | |
408 m_playStartFramePassed = false; | |
409 m_playStartedAt = RealTime::zeroTime; | |
410 if (m_target) { | |
411 m_playStartedAt = RealTime::fromSeconds(m_target->getCurrentTime()); | |
412 } | |
413 | |
401 bool changed = !m_playing; | 414 bool changed = !m_playing; |
402 m_lastRetrievalTimestamp = 0; | 415 m_lastRetrievalTimestamp = 0; |
403 m_playing = true; | 416 m_playing = true; |
404 m_condition.wakeAll(); | 417 m_condition.wakeAll(); |
405 if (changed) emit playStatusChanged(m_playing); | 418 if (changed) emit playStatusChanged(m_playing); |
629 ++index; | 642 ++index; |
630 } | 643 } |
631 | 644 |
632 if (inRange >= m_rangeStarts.size()) inRange = m_rangeStarts.size()-1; | 645 if (inRange >= m_rangeStarts.size()) inRange = m_rangeStarts.size()-1; |
633 | 646 |
634 RealTime playing_t = bufferedto_t - m_rangeStarts[inRange]; | 647 RealTime playing_t = bufferedto_t; |
635 | 648 |
636 playing_t = playing_t | 649 playing_t = playing_t |
637 - latency_t - stretchlat_t - lastretrieved_t - inbuffer_t | 650 - latency_t - stretchlat_t - lastretrieved_t - inbuffer_t |
638 + sincerequest_t; | 651 + sincerequest_t; |
652 | |
653 // This rather gross little hack is used to ensure that latency | |
654 // compensation doesn't result in the playback pointer appearing | |
655 // to start earlier than the actual playback does. It doesn't | |
656 // work properly (hence the bail-out in the middle) because if we | |
657 // are playing a relatively short looped region, the playing time | |
658 // estimated from the buffer fill frame may have wrapped around | |
659 // the region boundary and end up being much smaller than the | |
660 // theoretical play start frame, perhaps even for the entire | |
661 // duration of playback! | |
662 | |
663 if (!m_playStartFramePassed) { | |
664 RealTime playstart_t = RealTime::frame2RealTime(m_playStartFrame, | |
665 sourceRate); | |
666 if (playing_t < playstart_t) { | |
667 // std::cerr << "playing_t " << playing_t << " < playstart_t " | |
668 // << playstart_t << std::endl; | |
669 if (sincerequest_t > RealTime::zeroTime && | |
670 m_playStartedAt + latency_t + stretchlat_t < | |
671 RealTime::fromSeconds(currentTime)) { | |
672 // std::cerr << "but we've been playing for long enough that I think we should disregard it (it probably results from loop wrapping)" << std::endl; | |
673 m_playStartFramePassed = true; | |
674 } else { | |
675 playing_t = playstart_t; | |
676 } | |
677 } else { | |
678 m_playStartFramePassed = true; | |
679 } | |
680 } | |
681 | |
682 playing_t = playing_t - m_rangeStarts[inRange]; | |
639 | 683 |
640 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING | 684 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING |
641 std::cerr << "playing_t as offset into range " << inRange << " (with start = " << m_rangeStarts[inRange] << ") = " << playing_t << std::endl; | 685 std::cerr << "playing_t as offset into range " << inRange << " (with start = " << m_rangeStarts[inRange] << ") = " << playing_t << std::endl; |
642 #endif | 686 #endif |
643 | 687 |