Mercurial > hg > svapp
changeset 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 | dd6d0bc05030 |
files | audioio/AudioCallbackPlaySource.cpp audioio/AudioCallbackPlaySource.h |
diffstat | 2 files changed, 48 insertions(+), 1 deletions(-) [+] |
line wrap: on
line diff
--- a/audioio/AudioCallbackPlaySource.cpp Mon Feb 11 12:46:39 2008 +0000 +++ b/audioio/AudioCallbackPlaySource.cpp Mon Feb 11 17:08:59 2008 +0000 @@ -64,6 +64,8 @@ m_outputRight(0.0), m_auditioningPlugin(0), m_auditioningPluginBypassed(false), + m_playStartFrame(0), + m_playStartFramePassed(false), m_timeStretcher(0), m_stretchRatio(1.0), m_stretcherInputCount(0), @@ -355,8 +357,12 @@ if (m_viewManager->getPlaySelectionMode() && !m_viewManager->getSelections().empty()) { + std::cerr << "AudioCallbackPlaySource::play: constraining frame " << startFrame << " to selection = "; + startFrame = m_viewManager->constrainFrameToSelection(startFrame); + std::cerr << startFrame << std::endl; + } else { if (startFrame >= m_lastModelEndFrame) { startFrame = 0; @@ -398,6 +404,13 @@ m_audioGenerator->reset(); + m_playStartFrame = startFrame; + m_playStartFramePassed = false; + m_playStartedAt = RealTime::zeroTime; + if (m_target) { + m_playStartedAt = RealTime::fromSeconds(m_target->getCurrentTime()); + } + bool changed = !m_playing; m_lastRetrievalTimestamp = 0; m_playing = true; @@ -631,11 +644,42 @@ if (inRange >= m_rangeStarts.size()) inRange = m_rangeStarts.size()-1; - RealTime playing_t = bufferedto_t - m_rangeStarts[inRange]; + RealTime playing_t = bufferedto_t; playing_t = playing_t - latency_t - stretchlat_t - lastretrieved_t - inbuffer_t + sincerequest_t; + + // This rather gross little hack is used to ensure that latency + // compensation doesn't result in the playback pointer appearing + // to start earlier than the actual playback does. It doesn't + // work properly (hence the bail-out in the middle) because if we + // are playing a relatively short looped region, the playing time + // estimated from the buffer fill frame may have wrapped around + // the region boundary and end up being much smaller than the + // theoretical play start frame, perhaps even for the entire + // duration of playback! + + if (!m_playStartFramePassed) { + RealTime playstart_t = RealTime::frame2RealTime(m_playStartFrame, + sourceRate); + if (playing_t < playstart_t) { +// std::cerr << "playing_t " << playing_t << " < playstart_t " +// << playstart_t << std::endl; + if (sincerequest_t > RealTime::zeroTime && + m_playStartedAt + latency_t + stretchlat_t < + RealTime::fromSeconds(currentTime)) { +// 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; + m_playStartFramePassed = true; + } else { + playing_t = playstart_t; + } + } else { + m_playStartFramePassed = true; + } + } + + playing_t = playing_t - m_rangeStarts[inRange]; #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING std::cerr << "playing_t as offset into range " << inRange << " (with start = " << m_rangeStarts[inRange] << ") = " << playing_t << std::endl;
--- a/audioio/AudioCallbackPlaySource.h Mon Feb 11 12:46:39 2008 +0000 +++ b/audioio/AudioCallbackPlaySource.h Mon Feb 11 17:08:59 2008 +0000 @@ -297,6 +297,9 @@ RealTimePluginInstance *m_auditioningPlugin; bool m_auditioningPluginBypassed; Scavenger<RealTimePluginInstance> m_pluginScavenger; + size_t m_playStartFrame; + bool m_playStartFramePassed; + RealTime m_playStartedAt; RingBuffer<float> *getWriteRingBuffer(size_t c) { if (m_writeBuffers && c < m_writeBuffers->size()) {