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