diff options
| author | Maarten Bosmans <mkbosmans@gmail.com> | 2011-01-07 01:25:55 +0100 | 
|---|---|---|
| committer | Colin Guthrie <cguthrie@mandriva.org> | 2011-02-25 10:34:37 +0000 | 
| commit | 90c5520e03bbccf6c1d9f87221d3742cc70b53ed (patch) | |
| tree | 46aed8205bdf1f1266739dd6ca885e36f6983a9d /src/modules/module-loopback.c | |
| parent | 09770e577991d49cf826bdf80b0f9559f1e67820 (diff) | |
Limit rate adjustments to small, inaudible jumps
The same logic is applied to the sample rate adjustments in module-rtp-recv,
module-loopback and module-combine:
 - Each time an adjustment is made, the new rate can differ at most 2‰ from the
   old rate.  Such a step is equal to 3.5 cents (a cent is 1/100th of a
   semitone) and as 5 cents is generally considered the smallest observable
   difference in pitch, this results in inaudible adjustments.
 - The sample rate of the stream can only differ from the rate of the
   corresponding sink by 25%.  As these adjustments are meant to account for
   very small clock drifts, any large deviation from the base rate suggests
   something is seriously wrong.
 - If the calculated rate is within 20Hz of the base rate, set it to the base
   rate.  This saves CPU because no resampling is necessary.
Diffstat (limited to 'src/modules/module-loopback.c')
| -rw-r--r-- | src/modules/module-loopback.c | 18 | 
1 files changed, 15 insertions, 3 deletions
| diff --git a/src/modules/module-loopback.c b/src/modules/module-loopback.c index ca06314d..e0277c17 100644 --- a/src/modules/module-loopback.c +++ b/src/modules/module-loopback.c @@ -167,13 +167,13 @@ static void adjust_rates(struct userdata *u) {      buffer_latency = pa_bytes_to_usec(buffer, &u->sink_input->sample_spec); -    pa_log_info("Loopback overall latency is %0.2f ms + %0.2f ms + %0.2f ms = %0.2f ms", +    pa_log_debug("Loopback overall latency is %0.2f ms + %0.2f ms + %0.2f ms = %0.2f ms",                  (double) u->latency_snapshot.sink_latency / PA_USEC_PER_MSEC,                  (double) buffer_latency / PA_USEC_PER_MSEC,                  (double) u->latency_snapshot.source_latency / PA_USEC_PER_MSEC,                  ((double) u->latency_snapshot.sink_latency + buffer_latency + u->latency_snapshot.source_latency) / PA_USEC_PER_MSEC); -    pa_log_info("Should buffer %zu bytes, buffered at minimum %zu bytes", +    pa_log_debug("Should buffer %zu bytes, buffered at minimum %zu bytes",                  u->latency_snapshot.max_request*2,                  u->latency_snapshot.min_memblockq_length); @@ -186,9 +186,21 @@ static void adjust_rates(struct userdata *u) {      else          new_rate = base_rate + (((u->latency_snapshot.min_memblockq_length - u->latency_snapshot.max_request*2) / fs) *PA_USEC_PER_SEC)/u->adjust_time; -    pa_log_info("Old rate %lu Hz, new rate %lu Hz", (unsigned long) old_rate, (unsigned long) new_rate); +    if (new_rate < (uint32_t) (base_rate*0.8) || new_rate > (uint32_t) (base_rate*1.25)) { +        pa_log_warn("Sample rates too different, not adjusting (%u vs. %u).", base_rate, new_rate); +        new_rate = base_rate; +    } else { +        if (base_rate < new_rate + 20 && new_rate < base_rate + 20) +          new_rate = base_rate; +        /* Do the adjustment in small steps; 2‰ can be considered inaudible */ +        if (new_rate < (uint32_t) (old_rate*0.998) || new_rate > (uint32_t) (old_rate*1.002)) { +            pa_log_info("New rate of %u Hz not within 2‰ of %u Hz, forcing smaller adjustment", new_rate, old_rate); +            new_rate = PA_CLAMP(new_rate, (uint32_t) (old_rate*0.998), (uint32_t) (old_rate*1.002)); +        } +    }      pa_sink_input_set_rate(u->sink_input, new_rate); +    pa_log_debug("[%s] Updated sampling rate to %lu Hz.", u->sink_input->sink->name, (unsigned long) new_rate);      pa_core_rttime_restart(u->core, u->time_event, pa_rtclock_now() + u->adjust_time);  } | 
