diff audioio/AudioGenerator.cpp @ 80:448ff6e34b99

* Add wave file model method for reading more than one channel at once, avoiding ludicrously expensive backward seeks and double-reads when playing multi-channel files or using them as inputs to feature extraction plugins
author Chris Cannam
date Thu, 24 Jan 2008 14:35:43 +0000
parents 215b8b1b0308
children e25e8f5d785b
line wrap: on
line diff
--- a/audioio/AudioGenerator.cpp	Thu Jan 24 11:03:59 2008 +0000
+++ b/audioio/AudioGenerator.cpp	Thu Jan 24 14:35:43 2008 +0000
@@ -434,23 +434,60 @@
 				       float **buffer, float gain, float pan,
 				       size_t fadeIn, size_t fadeOut)
 {
-    static float *channelBuffer = 0;
-    static size_t channelBufSiz = 0;
+    static float **channelBuffer = 0;
+    static size_t  channelBufSiz = 0;
+    static size_t  channelBufCount = 0;
 
     size_t totalFrames = frames + fadeIn/2 + fadeOut/2;
 
-    if (channelBufSiz < totalFrames) {
+    size_t modelChannels = dtvm->getChannelCount();
+
+    if (channelBufSiz < totalFrames || channelBufCount < modelChannels) {
+
+        for (size_t c = 0; c < channelBufCount; ++c) {
+            delete[] channelBuffer[c];
+        }
+
 	delete[] channelBuffer;
-	channelBuffer = new float[totalFrames];
+        channelBuffer = new float *[modelChannels];
+
+        for (size_t c = 0; c < modelChannels; ++c) {
+            channelBuffer[c] = new float[totalFrames];
+        }
+
+        channelBufCount = modelChannels;
 	channelBufSiz = totalFrames;
     }
-    
+
     size_t got = 0;
-    size_t prevChannel = 999;
+
+    if (startFrame >= fadeIn/2) {
+        got = dtvm->getData(0, modelChannels - 1,
+                            startFrame - fadeIn/2,
+                            frames + fadeOut/2 + fadeIn/2,
+                            channelBuffer);
+    } else {
+        size_t missing = fadeIn/2 - startFrame;
+
+        for (size_t c = 0; c < modelChannels; ++c) {
+            channelBuffer[c] += missing;
+        }
+
+        got = dtvm->getData(0, modelChannels - 1,
+                            startFrame,
+                            frames + fadeOut/2,
+                            channelBuffer);
+
+        for (size_t c = 0; c < modelChannels; ++c) {
+            channelBuffer[c] -= missing;
+        }
+
+        got += missing;
+    }	    
 
     for (size_t c = 0; c < m_targetChannelCount; ++c) {
 
-	size_t sourceChannel = (c % dtvm->getChannelCount());
+	size_t sourceChannel = (c % modelChannels);
 
 //	std::cerr << "mixing channel " << c << " from source channel " << sourceChannel << std::endl;
 
@@ -463,28 +500,10 @@
 	    }
 	}
 
-	if (prevChannel != sourceChannel) {
-	    if (startFrame >= fadeIn/2) {
-		got = dtvm->getData
-		    (sourceChannel,
-		     startFrame - fadeIn/2,
-                     frames + fadeOut/2 + fadeIn/2,
-		     channelBuffer);
-	    } else {
-		size_t missing = fadeIn/2 - startFrame;
-		got = dtvm->getData
-		    (sourceChannel,
-		     startFrame,
-                     frames + fadeOut/2,
-		     channelBuffer + missing);
-	    }	    
-	}
-	prevChannel = sourceChannel;
-
 	for (size_t i = 0; i < fadeIn/2; ++i) {
 	    float *back = buffer[c];
 	    back -= fadeIn/2;
-	    back[i] += (channelGain * channelBuffer[i] * i) / fadeIn;
+	    back[i] += (channelGain * channelBuffer[sourceChannel][i] * i) / fadeIn;
 	}
 
 	for (size_t i = 0; i < frames + fadeOut/2; ++i) {
@@ -495,7 +514,9 @@
 	    if (i > frames - fadeOut/2) {
 		mult = (mult * ((frames + fadeOut/2) - i)) / fadeOut;
 	    }
-	    buffer[c][i] += mult * channelBuffer[i];
+            float val = channelBuffer[sourceChannel][i];
+            if (i >= got) val = 0.f;
+	    buffer[c][i] += mult * val;
 	}
     }