[client] audio: reduce hardcoded minimum latency

The current minimum target latency is partially based upon the default qemu
behaviour whereby audio packets are delivered in a sawtooth pattern, with
packet timestamps drifting between 5ms above and below the measured clock.
This 5ms error is baked into the minimum target latency to avoid
underrunning.

This sawtooth pattern can be reduced by specifying a lower timer period in
the qemu configuration, so remove it from the hardcoded minimum latency and
add it to the default configurable buffer latency instead. This allows
users that have configured their VM appropriately to reduce the overall
latency.
This commit is contained in:
Chris Spencer 2022-02-27 17:09:58 +00:00 committed by Geoffrey McRae
parent c2523be4b4
commit 72033f3822
2 changed files with 5 additions and 17 deletions

View file

@ -516,24 +516,12 @@ void audio_playbackData(uint8_t * data, size_t size)
spiceData->devNextPosition = deviceTick.nextPosition;
}
/* Determine the target latency. This is made up of three components:
* 1. Half the Spice period. This is necessary due to the way qemu handles
* audio. Data is not sent as soon as it is produced by the virtual sound
* card; instead, qemu polls for new data every ~10ms. This results in a
* sawtooth pattern in the packet timing as it drifts in and out of phase
* with the virtual device. LG measures the average progression of the
* Spice clock, so sees the packet timing error drift by half a period
* above and below the measured clock. We need to account for this in the
* target latency to avoid underrunning.
* 2. The maximum audio device period, plus a little extra to absorb timing
* jitter.
* 3. A configurable additional buffer period. The default value is set high
* enough to absorb typical timing jitter from Spice, which can be quite
* significant. Users may reduce this if they care more about latency than
* audio quality. */
/* Determine the target latency. This is made up of the maximum audio device
* period (plus a little extra to absorb timing jitter) and a configurable
* additional buffer period. The default is set high enough to absorb typical
* timing jitter from qemu. */
int configLatencyMs = max(g_params.audioBufferLatency, 0);
double targetLatencyFrames =
spiceData->periodFrames / 2.0 +
audio.playback.deviceMaxPeriodFrames * 1.1 +
configLatencyMs * audio.playback.sampleRate / 1000.0;

View file

@ -478,7 +478,7 @@ static struct Option options[] =
.name = "bufferLatency",
.description = "Additional buffer latency in milliseconds",
.type = OPTION_TYPE_INT,
.value.x_int = 8
.value.x_int = 13
},
{0}
};