[pulseaudio-discuss] [PATCH 10/13] loopback: Added a deadband to reduce rate hunting

Georg Chini georg at chini.tk
Sat Dec 12 04:24:40 PST 2015


On 08.12.2015 23:04, Tanu Kaskinen wrote:
> On Wed, 2015-02-25 at 19:43 +0100, Georg Chini wrote:
>> With USB or Bluetooth sources, the controller exhibited random
>> deviations of new_rate around the correct value, due to latency jitter.
>> Use the already-known latency error due to jitter, and assume that there
>> is no latency difference if the difference is below that error margin.
>> ---
>>   src/modules/module-loopback.c | 10 +++++++---
>>   1 file changed, 7 insertions(+), 3 deletions(-)
>>
>> diff --git a/src/modules/module-loopback.c b/src/modules/module-loopback.c
>> index b733663..6b48fc6 100644
>> --- a/src/modules/module-loopback.c
>> +++ b/src/modules/module-loopback.c
>> @@ -183,12 +183,12 @@ static void teardown(struct userdata *u) {
>>   /* rate controller
>>    * - maximum deviation from base rate is less than 1%
>>    * - can create audible artifacts by changing the rate too quickly
>> - * - exhibits hunting with USB or Bluetooth sources
>> + * - deadband to handle error of latency measurement
>>    */
>>   static uint32_t rate_controller(
>>                   uint32_t base_rate,
>>                   pa_usec_t adjust_time,
>> -                int32_t latency_difference_usec) {
>> +                int32_t latency_difference_usec, pa_usec_t latency_error_usec) {
>>   
>>       uint32_t new_rate;
>>       double min_cycles;
>> @@ -198,6 +198,10 @@ static uint32_t rate_controller(
>>       min_cycles = (double)abs(latency_difference_usec) / adjust_time / 0.0095 + 1;
>>       new_rate = base_rate * (1.0 + (double)latency_difference_usec / min_cycles / adjust_time);
>>   
>> +    /* Adjust as good as physics allows (with some safety margin) */
>> +    if (abs(latency_difference_usec) <= 2.5 * latency_error_usec + adjust_time / 2 / base_rate + 100)
>> +       new_rate = base_rate;
> There's that magic number 2.5 again...

That's where that number is coming from in the first place. The idea was 
that
I am tracking an average of the absolute errors, so the worst thing I should
be seeing is a jump from predicted_latency - error to predicted_latency 
+error.
That's 2 * latency_error_usec. Because I am tracking an average, the actual
jump might even be larger, so I changed the factor to 2.5 as a safety 
margin.

>
> What's that "adjust_time / 2 / base_rate"? The unit of that is seconds
> squared, doesn't make sense to me...

No, it isn't. I know it looks strange, but there is a second that you do 
not see.
The smallest amount of latency correction possible at a given base_rate and
adjust_time is one sample per second of adjust_time. And that is the second
you cannot see in the term above (because it is 1).
It does not make sense to try to correct the latency when you are less than
half of that distance away from the desired latency because then you end
up further away from the target.
It does not account for a large part of the deadband, but when I tested my
patch I went down to sample rates of 50 Hz and below where it is 
significant.

>
> Are you claiming that this results in adjustment that is as close to
> optimal as physics allows? If so, what's the basis for that claim?
>
Yes, within the restrictions of the used model. The deadband accounts
for

1) The error of the measurement (first term)
2) The minimum correctable latency amount (second term)
3) A general safety margin (third term)

So when I am within the bounds of the deadband it does not make sense to
try to correct the latency because I cannot be sure that I end up with a 
better
value.

But overall Alexander convinced me that the deadband is not necessary, so
it will vanish in the next version of the patch. It is replaced by a 
Kalman filter
to smooth down the measured latency.
Additionally the current patch set does not take the rate difference between
source and sink into account (it assumes that both are running exactly 
at the
same frequency) and will so lead to sawtooth changes of the latency if this
assumption is not met. This is fixed in my new version.
I sent you a few results for the new version earlier today.



More information about the pulseaudio-discuss mailing list