changeset 5:2edc0757ca75

* Fixes to playback of short looped files, of synthesised content within looped sections, and a few other fixes
author Chris Cannam
date Thu, 26 Jan 2006 11:56:09 +0000
parents 5865094175ea
children f3d777b693f7
files audioio/AudioCallbackPlaySource.cpp audioio/AudioGenerator.cpp
diffstat 2 files changed, 56 insertions(+), 29 deletions(-) [+]
line wrap: on
line diff
--- a/audioio/AudioCallbackPlaySource.cpp	Wed Jan 25 17:46:28 2006 +0000
+++ b/audioio/AudioCallbackPlaySource.cpp	Thu Jan 26 11:56:09 2006 +0000
@@ -204,7 +204,8 @@
 void
 AudioCallbackPlaySource::play(size_t startFrame)
 {
-    if (m_viewManager->getPlaySelectionMode()) {
+    if (m_viewManager->getPlaySelectionMode() &&
+	!m_viewManager->getSelections().empty()) {
 	ViewManager::SelectionList selections = m_viewManager->getSelections();
 	ViewManager::SelectionList::iterator i = selections.begin();
 	if (i != selections.end()) {
@@ -218,6 +219,10 @@
 		}
 	    }
 	}
+    } else {
+	if (startFrame >= m_lastModelEndFrame) {
+	    startFrame = 0;
+	}
     }
 
     // The fill thread will automatically empty its buffers before
@@ -343,27 +348,28 @@
     latency += readSpace;
     size_t bufferedFrame = m_bufferedToFrame;
 
+    bool looping = m_viewManager->getPlayLoopMode();
+    bool constrained = (m_viewManager->getPlaySelectionMode() &&
+			!m_viewManager->getSelections().empty());
+
     size_t framePlaying = bufferedFrame;
-    if (framePlaying > latency) framePlaying -= latency;
-    else {
-	//!!! Not right
-	if (m_viewManager->getPlayLoopMode() &&
-	    !m_viewManager->getPlaySelectionMode()) {
-	    framePlaying += m_lastModelEndFrame;
-	    if (framePlaying > latency) framePlaying -= latency;
-	    else framePlaying = 0;
-	}
+
+    if (looping && !constrained) {
+	while (framePlaying < latency) framePlaying += m_lastModelEndFrame;
     }
 
-    if (!m_viewManager->getPlaySelectionMode()) {
+    if (framePlaying > latency) framePlaying -= latency;
+    else framePlaying = 0;
+
+    if (!constrained) {
+	if (!looping && framePlaying > m_lastModelEndFrame) {
+	    framePlaying = m_lastModelEndFrame;
+	    stop();
+	}
 	return framePlaying;
     }
 
     ViewManager::SelectionList selections = m_viewManager->getSelections();
-    if (selections.empty()) {
-	return framePlaying;
-    }
-
     ViewManager::SelectionList::const_iterator i;
 
     i = selections.begin();
@@ -386,7 +392,7 @@
 	if (i->getEndFrame() + latency < f) {
 //    std::cerr << "framePlaying = " << framePlaying << ", rangeEnd = " << rangeEnd << std::endl;
 
-	    if (!m_viewManager->getPlayLoopMode() && (framePlaying > rangeEnd)) {
+	    if (!looping && (framePlaying > rangeEnd)) {
 //		std::cerr << "STOPPING" << std::endl;
 		stop();
 		return rangeEnd;
@@ -413,7 +419,7 @@
 	    break;
 	} else {
 	    if (i == selections.begin()) {
-		if (m_viewManager->getPlayLoopMode()) {
+		if (looping) {
 		    i = selections.end();
 		}
 	    }
@@ -843,8 +849,9 @@
     size_t chunkSize = count;
     size_t nextChunkStart = chunkStart + chunkSize;
     
-    bool useSelection = (m_viewManager->getPlaySelectionMode() &&
-			 !m_viewManager->getSelections().empty());
+    bool looping = m_viewManager->getPlayLoopMode();
+    bool constrained = (m_viewManager->getPlaySelectionMode() &&
+			!m_viewManager->getSelections().empty());
 
     static float **chunkBufferPtrs = 0;
     static size_t chunkBufferPtrCount = 0;
@@ -871,13 +878,13 @@
 
 	size_t fadeIn = 0, fadeOut = 0;
 
-	if (useSelection) {
+	if (constrained) {
 	    
 	    Selection selection =
 		m_viewManager->getContainingSelection(chunkStart, true);
 	    
 	    if (selection.isEmpty()) {
-		if (m_viewManager->getPlayLoopMode()) {
+		if (looping) {
 		    selection = *m_viewManager->getSelections().begin();
 		    chunkStart = selection.getStartFrame();
 		    fadeIn = 50;
@@ -906,8 +913,7 @@
 		chunkSize = nextChunkStart - chunkStart;
 	    }
 	
-	} else if (m_viewManager->getPlayLoopMode() &&
-		   m_lastModelEndFrame > 0) {
+	} else if (looping && m_lastModelEndFrame > 0) {
 
 	    if (chunkStart >= m_lastModelEndFrame) {
 		chunkStart = 0;
--- a/audioio/AudioGenerator.cpp	Wed Jan 25 17:46:28 2006 +0000
+++ b/audioio/AudioGenerator.cpp	Thu Jan 26 11:56:09 2006 +0000
@@ -25,7 +25,7 @@
 const size_t
 AudioGenerator::m_pluginBlockSize = 2048;
 
-// #define DEBUG_AUDIO_GENERATOR 1
+//#define DEBUG_AUDIO_GENERATOR 1
 
 AudioGenerator::AudioGenerator(ViewManager *manager) :
     m_viewManager(manager),
@@ -190,7 +190,7 @@
 {
     static float *channelBuffer = 0;
     static size_t channelBufSiz = 0;
-    
+
     size_t totalFrames = frames + fadeIn/2 + fadeOut/2;
 
     if (channelBufSiz < totalFrames) {
@@ -203,9 +203,16 @@
 
     for (size_t c = 0; c < m_targetChannelCount && c < dtvm->getChannelCount(); ++c) {
 
-	got = dtvm->getValues
-	    (c, startFrame - fadeIn/2, startFrame + frames + fadeOut/2,
-	     channelBuffer);
+	if (startFrame >= fadeIn/2) {
+	    got = dtvm->getValues
+		(c, startFrame - fadeIn/2, startFrame + frames + fadeOut/2,
+		 channelBuffer);
+	} else {
+	    size_t missing = fadeIn/2 - startFrame;
+	    got = dtvm->getValues
+		(c, 0, startFrame + frames + fadeOut/2,
+		 channelBuffer + missing);
+	}	    
 
 	for (size_t i = 0; i < fadeIn/2; ++i) {
 	    float *back = buffer[c];
@@ -276,7 +283,7 @@
 	size_t reqStart = startFrame + i * m_pluginBlockSize;
 
 	SparseOneDimensionalModel::PointList points =
-	    sodm->getPoints(reqStart > 0 ? reqStart + latency : reqStart,
+	    sodm->getPoints(reqStart + latency,
 			    reqStart + latency + m_pluginBlockSize);
 
 	RealTime blockTime = RealTime::frame2RealTime
@@ -286,8 +293,12 @@
 		 points.begin(); pli != points.end(); ++pli) {
 
 	    size_t pliFrame = pli->frame;
+
 	    if (pliFrame >= latency) pliFrame -= latency;
 
+	    if (pliFrame < reqStart ||
+		pliFrame >= reqStart + m_pluginBlockSize) continue;
+
 	    while (noteOffs.begin() != noteOffs.end() &&
 		   noteOffs.begin()->frame <= pliFrame) {
 
@@ -295,6 +306,11 @@
 		    (noteOffs.begin()->frame, m_sourceSampleRate);
 
 		offEv.data.note.note = noteOffs.begin()->pitch;
+
+#ifdef DEBUG_AUDIO_GENERATOR
+		std::cerr << "mixModel [sparse]: sending note-off event at time " << eventTime << " frame " << noteOffs.begin()->frame << std::endl;
+#endif
+
 		plugin->sendEvent(eventTime, &offEv);
 		noteOffs.erase(noteOffs.begin());
 	    }
@@ -323,6 +339,11 @@
 		(noteOffs.begin()->frame, m_sourceSampleRate);
 
 	    offEv.data.note.note = noteOffs.begin()->pitch;
+
+#ifdef DEBUG_AUDIO_GENERATOR
+		std::cerr << "mixModel [sparse]: sending leftover note-off event at time " << eventTime << " frame " << noteOffs.begin()->frame << std::endl;
+#endif
+
 	    plugin->sendEvent(eventTime, &offEv);
 	    noteOffs.erase(noteOffs.begin());
 	}