diff audioio/AudioCallbackPlaySource.cpp @ 102:8591a0a3d57e

* Tolerable fixes to #1903062 and #1903046
author Chris Cannam
date Wed, 27 Feb 2008 18:04:10 +0000
parents cd5cbdecc82d
children 2485f822dc54
line wrap: on
line diff
--- a/audioio/AudioCallbackPlaySource.cpp	Mon Feb 18 10:14:58 2008 +0000
+++ b/audioio/AudioCallbackPlaySource.cpp	Wed Feb 27 18:04:10 2008 +0000
@@ -57,6 +57,8 @@
     m_target(0),
     m_lastRetrievalTimestamp(0.0),
     m_lastRetrievedBlockSize(0),
+    m_trustworthyTimestamps(true),
+    m_lastCurrentFrame(0),
     m_playing(false),
     m_exiting(false),
     m_lastModelEndFrame(0),
@@ -379,28 +381,25 @@
     // The fill thread will automatically empty its buffers before
     // starting again if we have not so far been playing, but not if
     // we're just re-seeking.
+    // NO -- we can end up playing some first -- always reset here
 
     m_mutex.lock();
+
     if (m_timeStretcher) {
         m_timeStretcher->reset();
     }
-    if (m_playing) {
-        std::cerr << "playing already, resetting" << std::endl;
-	m_readBufferFill = m_writeBufferFill = startFrame;
-	if (m_readBuffers) {
-	    for (size_t c = 0; c < getTargetChannelCount(); ++c) {
-		RingBuffer<float> *rb = getReadRingBuffer(c);
-                std::cerr << "reset ring buffer for channel " << c << std::endl;
-		if (rb) rb->reset();
-	    }
-	}
-	if (m_converter) src_reset(m_converter);
-        if (m_crapConverter) src_reset(m_crapConverter);
-    } else {
-	if (m_converter) src_reset(m_converter);
-        if (m_crapConverter) src_reset(m_crapConverter);
-	m_readBufferFill = m_writeBufferFill = startFrame;
+
+    m_readBufferFill = m_writeBufferFill = startFrame;
+    if (m_readBuffers) {
+        for (size_t c = 0; c < getTargetChannelCount(); ++c) {
+            RingBuffer<float> *rb = getReadRingBuffer(c);
+            std::cerr << "reset ring buffer for channel " << c << std::endl;
+            if (rb) rb->reset();
+        }
     }
+    if (m_converter) src_reset(m_converter);
+    if (m_crapConverter) src_reset(m_crapConverter);
+
     m_mutex.unlock();
 
     m_audioGenerator->reset();
@@ -414,6 +413,7 @@
 
     bool changed = !m_playing;
     m_lastRetrievalTimestamp = 0;
+    m_lastCurrentFrame = 0;
     m_playing = true;
     m_condition.wakeAll();
     if (changed) emit playStatusChanged(m_playing);
@@ -426,6 +426,7 @@
     m_playing = false;
     m_condition.wakeAll();
     m_lastRetrievalTimestamp = 0;
+    m_lastCurrentFrame = 0;
     if (changed) emit playStatusChanged(m_playing);
 }
 
@@ -555,6 +556,8 @@
     double currentTime = 0.0;
     if (m_target) currentTime = m_target->getCurrentTime();
 
+    bool looping = m_viewManager->getPlayLoopMode();
+
     RealTime inbuffer_t = RealTime::frame2RealTime(inbuffer, targetRate);
 
     size_t stretchlat = 0;
@@ -579,7 +582,9 @@
     RealTime sincerequest_t = RealTime::zeroTime;
     RealTime lastretrieved_t = RealTime::zeroTime;
 
-    if (m_target && lastRetrievalTimestamp != 0.0) {
+    if (m_target &&
+        m_trustworthyTimestamps &&
+        lastRetrievalTimestamp != 0.0) {
 
         lastretrieved_t = RealTime::frame2RealTime
             (lastRetrievedBlockSize, targetRate);
@@ -587,10 +592,14 @@
         // calculate number of frames at target rate that have elapsed
         // since the end of the last call to getSourceSamples
 
-        double elapsed = currentTime - lastRetrievalTimestamp;
+        if (m_trustworthyTimestamps && !looping) {
 
-        if (elapsed > 0.0) {
-            sincerequest_t = RealTime::fromSeconds(elapsed);
+            // this adjustment seems to cause more problems when looping
+            double elapsed = currentTime - lastRetrievalTimestamp;
+
+            if (elapsed > 0.0) {
+                sincerequest_t = RealTime::fromSeconds(elapsed);
+            }
         }
 
     } else {
@@ -606,8 +615,6 @@
         sincerequest_t = sincerequest_t / timeRatio;
     }
 
-    bool looping = m_viewManager->getPlayLoopMode();
-
 #ifdef DEBUG_AUDIO_PLAY_SOURCE_PLAYING
     std::cerr << "\nbuffered to: " << bufferedto_t << ", in buffer: " << inbuffer_t << ", time ratio " << timeRatio << "\n  stretcher latency: " << stretchlat_t << ", device latency: " << latency_t << "\n  since request: " << sincerequest_t << ", last retrieved: " << lastretrieved_t << std::endl;
 #endif
@@ -718,6 +725,15 @@
     if (playing_t < RealTime::zeroTime) playing_t = RealTime::zeroTime;
 
     size_t frame = RealTime::realTime2Frame(playing_t, sourceRate);
+
+    if (m_lastCurrentFrame > 0 && !looping) {
+        if (frame < m_lastCurrentFrame) {
+            frame = m_lastCurrentFrame;
+        }
+    }
+
+    m_lastCurrentFrame = frame;
+
     return m_viewManager->alignPlaybackFrameToReference(frame);
 }
 
@@ -1137,9 +1153,9 @@
 //                  << std::endl;
         return;
     }
-    if (plugin->getBufferSize() != count) {
+    if (plugin->getBufferSize() < count) {
 //        std::cerr << "plugin buffer size " << plugin->getBufferSize() 
-//                  << " != our block size " << count
+//                  << " < our block size " << count
 //                  << std::endl;
         return;
     }
@@ -1153,7 +1169,7 @@
         }
     }
 
-    plugin->run(Vamp::RealTime::zeroTime);
+    plugin->run(Vamp::RealTime::zeroTime, count);
     
     for (size_t c = 0; c < getTargetChannelCount(); ++c) {
         for (size_t i = 0; i < count; ++i) {