alsa-sink: reduce the amount of smoother updates

Exponentially increase the amount of time between smoother updates. We start
with a 2ms interval and increase up to 200ms intervals.
Smoother updates and the resulting linear regression take a fair amount of CPU
so we want to reduce the amount of updates.
This commit is contained in:
Wim Taymans 2009-08-20 13:40:27 +02:00
parent f8ffe0dabc
commit c1b6a87b27

View file

@ -68,6 +68,9 @@
#define TSCHED_MIN_SLEEP_USEC (10*PA_USEC_PER_MSEC) /* 10ms -- Sleep at least 10ms on each iteration */ #define TSCHED_MIN_SLEEP_USEC (10*PA_USEC_PER_MSEC) /* 10ms -- Sleep at least 10ms on each iteration */
#define TSCHED_MIN_WAKEUP_USEC (4*PA_USEC_PER_MSEC) /* 4ms -- Wakeup at least this long before the buffer runs empty*/ #define TSCHED_MIN_WAKEUP_USEC (4*PA_USEC_PER_MSEC) /* 4ms -- Wakeup at least this long before the buffer runs empty*/
#define SMOOTHER_MIN_INTERVAL (2*PA_USEC_PER_MSEC) /* 2ms -- min smoother update interval */
#define SMOOTHER_MAX_INTERVAL (200*PA_USEC_PER_MSEC) /* 200ms -- max smoother update inteval */
#define VOLUME_ACCURACY (PA_VOLUME_NORM/100) /* don't require volume adjustments to be perfectly correct. don't necessarily extend granularity in software unless the differences get greater than this level */ #define VOLUME_ACCURACY (PA_VOLUME_NORM/100) /* don't require volume adjustments to be perfectly correct. don't necessarily extend granularity in software unless the differences get greater than this level */
struct userdata { struct userdata {
@ -115,6 +118,8 @@ struct userdata {
pa_smoother *smoother; pa_smoother *smoother;
uint64_t write_count; uint64_t write_count;
uint64_t since_start; uint64_t since_start;
pa_usec_t smoother_interval;
pa_usec_t last_smoother_update;
pa_reserve_wrapper *reserve; pa_reserve_wrapper *reserve;
pa_hook_slot *reserve_slot; pa_hook_slot *reserve_slot;
@ -723,17 +728,27 @@ static void update_smoother(struct userdata *u) {
now1 = pa_timespec_load(&htstamp); now1 = pa_timespec_load(&htstamp);
} }
/* Hmm, if the timestamp is 0, then it wasn't set and we take the current time */
if (now1 <= 0)
now1 = pa_rtclock_now();
/* check if the time since the last update is bigger than the interval */
if (u->last_smoother_update > 0) {
if (u->last_smoother_update + u->smoother_interval > now1)
return;
}
position = (int64_t) u->write_count - ((int64_t) delay * (int64_t) u->frame_size); position = (int64_t) u->write_count - ((int64_t) delay * (int64_t) u->frame_size);
if (PA_UNLIKELY(position < 0)) if (PA_UNLIKELY(position < 0))
position = 0; position = 0;
/* Hmm, if the timestamp is 0, then it wasn't set and we take the current time */
if (now1 <= 0)
now1 = pa_rtclock_now();
now2 = pa_bytes_to_usec((uint64_t) position, &u->sink->sample_spec); now2 = pa_bytes_to_usec((uint64_t) position, &u->sink->sample_spec);
u->last_smoother_update = now1;
/* exponentially increase the update interval up to the MAX limit */
u->smoother_interval = PA_MIN (u->smoother_interval * 2, SMOOTHER_MAX_INTERVAL);
pa_smoother_put(u->smoother, now1, now2); pa_smoother_put(u->smoother, now1, now2);
} }
@ -906,6 +921,8 @@ static int unsuspend(struct userdata *u) {
u->write_count = 0; u->write_count = 0;
pa_smoother_reset(u->smoother, pa_rtclock_now(), TRUE); pa_smoother_reset(u->smoother, pa_rtclock_now(), TRUE);
u->smoother_interval = SMOOTHER_MIN_INTERVAL;
u->last_smoother_update = 0;
u->first = TRUE; u->first = TRUE;
u->since_start = 0; u->since_start = 0;
@ -1622,6 +1639,7 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
5, 5,
pa_rtclock_now(), pa_rtclock_now(),
TRUE); TRUE);
u->smoother_interval = SMOOTHER_MIN_INTERVAL;
dev_id = pa_modargs_get_value( dev_id = pa_modargs_get_value(
ma, "device_id", ma, "device_id",