]> Repos - portaudio/commitdiff
wmme limit host buffer size to 32k. try to make host buffer size a factor of over...
authorrossb <rossb@0f58301d-fd10-0410-b4af-bbb618454e57>
Thu, 25 Aug 2011 07:15:31 +0000 (07:15 +0000)
committerrossb <rossb@0f58301d-fd10-0410-b4af-bbb618454e57>
Thu, 25 Aug 2011 07:15:31 +0000 (07:15 +0000)
src/hostapi/wmme/pa_win_wmme.c

index 4264d3c85be80c34119ec456b4a6a595277487fa..ec990857b49de5f84c0fb0322968bbd6bd390eab 100644 (file)
@@ -1368,6 +1368,48 @@ static unsigned long ComputeHostBufferCountForFixedBufferSizeFrames(
 }
 
 
+static unsigned long ComputeHostBufferSizeGivenHardUpperLimit( 
+        unsigned long userFramesPerBuffer,
+        unsigned long absoluteMaximumBufferSizeFrames )
+{
+    static unsigned long primes_[] = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 
+            29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 0 }; /* zero terminated */
+
+    unsigned long result = userFramesPerBuffer;
+    int i;
+
+    assert( absoluteMaximumBufferSizeFrames > 67 ); /* assume maximum is large and we're only factoring by small primes */
+
+    /* search for the largest integer factor of userFramesPerBuffer less 
+       than or equal to absoluteMaximumBufferSizeFrames */
+
+    /* repeatedly divide by smallest prime factors until a buffer size 
+       smaller than absoluteMaximumBufferSizeFrames is found */
+    while( result > absoluteMaximumBufferSizeFrames ){
+
+        /* search for the smallest prime factor of result */
+        for( i=0; primes_[i] != 0; ++i ) 
+        {
+            unsigned long p = primes_[i];
+            unsigned long divided = result / p;
+            if( divided*p == result )
+            {
+                result = divided;
+                break; /* continue with outer while loop */
+            }
+        }
+        if( primes_[i] == 0 )
+        { /* loop failed to find a prime factor, return an approximate result */
+            unsigned long d = (userFramesPerBuffer + (absoluteMaximumBufferSizeFrames-1))
+                    / absoluteMaximumBufferSizeFrames;
+            return userFramesPerBuffer / d;
+        }
+    }
+
+    return result;
+}
+
+
 static PaError SelectHostBufferSizeFramesAndHostBufferCount(
         unsigned long suggestedLatencyFrames,
         unsigned long userFramesPerBuffer,
@@ -1387,16 +1429,26 @@ static PaError SelectHostBufferSizeFramesAndHostBufferCount(
 
     }else{
 
-        effectiveUserFramesPerBuffer = userFramesPerBuffer;
+        if( userFramesPerBuffer > absoluteMaximumBufferSizeFrames ){
 
-        if( effectiveUserFramesPerBuffer > absoluteMaximumBufferSizeFrames ){
-            /* user has requested a user buffer that's larger than absoluteMaximumBufferSizeFrames */
-            
-            /* @todo FIXME/REVIEW right now we allow the user to request an oversize host buffer,
-                even though elsewhere in the code there are suggestions that oversize buffers
-                can cause crashes with some drivers. see http://www.portaudio.com/trac/ticket/189
-                */
-            /* return paBufferTooBig; */
+            /* user has requested a user buffer that's larger than absoluteMaximumBufferSizeFrames.
+               try to choose a buffer size that is equal or smaller than absoluteMaximumBufferSizeFrames
+               but is also an integer factor of userFramesPerBuffer, so as to distribute computation evenly.
+               the buffer processor will handle the block adaption between host and user buffer sizes.
+               see http://www.portaudio.com/trac/ticket/189 for discussion.
+            */
+
+            effectiveUserFramesPerBuffer = ComputeHostBufferSizeGivenHardUpperLimit( userFramesPerBuffer, absoluteMaximumBufferSizeFrames );
+            assert( effectiveUserFramesPerBuffer <= absoluteMaximumBufferSizeFrames );
+
+            /* try to ensure that duration of host buffering is at least as 
+                large as duration of user buffer. */
+            if( suggestedLatencyFrames < userFramesPerBuffer )
+                suggestedLatencyFrames = userFramesPerBuffer; 
+
+        }else{
+
+            effectiveUserFramesPerBuffer = userFramesPerBuffer;
         }
     }
                         
@@ -1407,39 +1459,42 @@ static PaError SelectHostBufferSizeFramesAndHostBufferCount(
     *hostBufferCount = ComputeHostBufferCountForFixedBufferSizeFrames(
             suggestedLatencyFrames, *hostBufferSizeFrames, minimumBufferCount );
 
-    /*
-        If there are too many host buffers we would like to coalesce 
-        them by packing an integer number of user buffers into each host buffer.
-        We try to coalesce such that hostBufferCount will lie between 
-        PA_MME_TARGET_HOST_BUFFER_COUNT_ and (PA_MME_TARGET_HOST_BUFFER_COUNT_*2)-1.
-        We limit coalescing to avoid exceeding either absoluteMaximumBufferSizeFrames and
-        preferredMaximumBufferSizeFrames. 
-
-        First, compute a coalescing factor: the number of user buffers per host buffer.
-        The goal is to achieve PA_MME_TARGET_HOST_BUFFER_COUNT_ total buffer count.
-        Since our latency is computed based on (*hostBufferCount - 1) we compute a
-        coalescing factor based on (*hostBufferCount - 1) and (PA_MME_TARGET_HOST_BUFFER_COUNT_-1).
-
-        The + (PA_MME_TARGET_HOST_BUFFER_COUNT_-2) term below is intended to round up.
-    */
-    numberOfUserBuffersPerHostBuffer = ((*hostBufferCount - 1) + (PA_MME_TARGET_HOST_BUFFER_COUNT_-2)) / (PA_MME_TARGET_HOST_BUFFER_COUNT_ - 1);
-    
-    if( numberOfUserBuffersPerHostBuffer > 1 )
+    if( *hostBufferSizeFrames >= userFramesPerBuffer )
     {
-        unsigned long maxCoalescedBufferSizeFrames = (absoluteMaximumBufferSizeFrames < preferredMaximumBufferSizeFrames) /* minimum of our limits */
-                        ? absoluteMaximumBufferSizeFrames
-                        : preferredMaximumBufferSizeFrames;
+        /*
+            If there are too many host buffers we would like to coalesce 
+            them by packing an integer number of user buffers into each host buffer.
+            We try to coalesce such that hostBufferCount will lie between 
+            PA_MME_TARGET_HOST_BUFFER_COUNT_ and (PA_MME_TARGET_HOST_BUFFER_COUNT_*2)-1.
+            We limit coalescing to avoid exceeding either absoluteMaximumBufferSizeFrames and
+            preferredMaximumBufferSizeFrames. 
+
+            First, compute a coalescing factor: the number of user buffers per host buffer.
+            The goal is to achieve PA_MME_TARGET_HOST_BUFFER_COUNT_ total buffer count.
+            Since our latency is computed based on (*hostBufferCount - 1) we compute a
+            coalescing factor based on (*hostBufferCount - 1) and (PA_MME_TARGET_HOST_BUFFER_COUNT_-1).
+
+            The + (PA_MME_TARGET_HOST_BUFFER_COUNT_-2) term below is intended to round up.
+        */
+        numberOfUserBuffersPerHostBuffer = ((*hostBufferCount - 1) + (PA_MME_TARGET_HOST_BUFFER_COUNT_-2)) / (PA_MME_TARGET_HOST_BUFFER_COUNT_ - 1);
+        
+        if( numberOfUserBuffersPerHostBuffer > 1 )
+        {
+            unsigned long maxCoalescedBufferSizeFrames = (absoluteMaximumBufferSizeFrames < preferredMaximumBufferSizeFrames) /* minimum of our limits */
+                            ? absoluteMaximumBufferSizeFrames
+                            : preferredMaximumBufferSizeFrames;
 
-        unsigned long maxUserBuffersPerHostBuffer = maxCoalescedBufferSizeFrames / effectiveUserFramesPerBuffer; /* don't coalesce more than this */
+            unsigned long maxUserBuffersPerHostBuffer = maxCoalescedBufferSizeFrames / effectiveUserFramesPerBuffer; /* don't coalesce more than this */
 
-        if( numberOfUserBuffersPerHostBuffer > maxUserBuffersPerHostBuffer )
-            numberOfUserBuffersPerHostBuffer = maxUserBuffersPerHostBuffer;
+            if( numberOfUserBuffersPerHostBuffer > maxUserBuffersPerHostBuffer )
+                numberOfUserBuffersPerHostBuffer = maxUserBuffersPerHostBuffer;
 
-        *hostBufferSizeFrames = effectiveUserFramesPerBuffer * numberOfUserBuffersPerHostBuffer;
+            *hostBufferSizeFrames = effectiveUserFramesPerBuffer * numberOfUserBuffersPerHostBuffer;
 
-        /* recompute hostBufferCount to approximate suggestedLatencyFrames now that hostBufferSizeFrames is larger */
-        *hostBufferCount = ComputeHostBufferCountForFixedBufferSizeFrames(
-                suggestedLatencyFrames, *hostBufferSizeFrames, minimumBufferCount );
+            /* recompute hostBufferCount to approximate suggestedLatencyFrames now that hostBufferSizeFrames is larger */
+            *hostBufferCount = ComputeHostBufferCountForFixedBufferSizeFrames(
+                    suggestedLatencyFrames, *hostBufferSizeFrames, minimumBufferCount );
+        }
     }
 
     return paNoError;