wmme limit host buffer size to 32k. try to make host buffer size a factor of over-limit user buffer size. closes #189
This commit is contained in:
parent
6aa858c0f7
commit
16f40db4c8
1 changed files with 92 additions and 37 deletions
|
|
@ -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.
|
||||
|
||||
unsigned long maxUserBuffersPerHostBuffer = maxCoalescedBufferSizeFrames / effectiveUserFramesPerBuffer; /* don't coalesce more than this */
|
||||
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).
|
||||
|
||||
if( numberOfUserBuffersPerHostBuffer > maxUserBuffersPerHostBuffer )
|
||||
numberOfUserBuffersPerHostBuffer = maxUserBuffersPerHostBuffer;
|
||||
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;
|
||||
|
||||
*hostBufferSizeFrames = effectiveUserFramesPerBuffer * numberOfUserBuffersPerHostBuffer;
|
||||
unsigned long maxUserBuffersPerHostBuffer = maxCoalescedBufferSizeFrames / effectiveUserFramesPerBuffer; /* don't coalesce more than this */
|
||||
|
||||
/* recompute hostBufferCount to approximate suggestedLatencyFrames now that hostBufferSizeFrames is larger */
|
||||
*hostBufferCount = ComputeHostBufferCountForFixedBufferSizeFrames(
|
||||
suggestedLatencyFrames, *hostBufferSizeFrames, minimumBufferCount );
|
||||
if( numberOfUserBuffersPerHostBuffer > maxUserBuffersPerHostBuffer )
|
||||
numberOfUserBuffersPerHostBuffer = maxUserBuffersPerHostBuffer;
|
||||
|
||||
*hostBufferSizeFrames = effectiveUserFramesPerBuffer * numberOfUserBuffersPerHostBuffer;
|
||||
|
||||
/* recompute hostBufferCount to approximate suggestedLatencyFrames now that hostBufferSizeFrames is larger */
|
||||
*hostBufferCount = ComputeHostBufferCountForFixedBufferSizeFrames(
|
||||
suggestedLatencyFrames, *hostBufferSizeFrames, minimumBufferCount );
|
||||
}
|
||||
}
|
||||
|
||||
return paNoError;
|
||||
|
|
|
|||
Loading…
Reference in a new issue