mirror of
https://github.com/gnif/LookingGlass.git
synced 2024-11-22 05:27:20 +00:00
[client] audio: add latency tuning parameter
This adds a new `audio:bufferLatency` option which allows the user to adjust the amount of buffering LG does over the absolute bare minimum. By default, this is set large enough to absorb typical timing jitter from Spice. Users may reduce this if they care more about latency than audio quality.
This commit is contained in:
parent
9908b737b0
commit
7c2d493bb5
@ -517,16 +517,26 @@ void audio_playbackData(uint8_t * data, size_t size)
|
|||||||
spiceData->devNextPosition = deviceTick.nextPosition;
|
spiceData->devNextPosition = deviceTick.nextPosition;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determine the target latency. Ideally, this would be precisely equal to
|
// Determine the target latency. This is made up of three components:
|
||||||
// the maximum device period size. However, we need to allow for some timing
|
// 1. Half the Spice period. This is necessary due to the way qemu handles
|
||||||
// jitter to avoid underruns. Packets from Spice in particular can sometimes
|
// audio. Data is not sent as soon as it is produced by the virtual sound
|
||||||
// be delayed by an entire period or more, so include a fixed amount of
|
// card; instead, qemu polls for new data every ~10ms. This results in a
|
||||||
// latency to absorb these gaps. For device jitter use a multiplier, so timing
|
// sawtooth pattern in the packet timing as it drifts in and out of phase
|
||||||
// requirements get progressively stricter as the period size is reduced
|
// with the virtual device. LG measures the average progression of the
|
||||||
int spiceJitterMs = 13;
|
// 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.
|
||||||
|
int configLatencyMs = max(g_params.audioBufferLatency, 0);
|
||||||
double targetLatencyFrames =
|
double targetLatencyFrames =
|
||||||
spiceJitterMs * audio.playback.sampleRate / 1000.0 +
|
spiceData->periodFrames / 2.0 +
|
||||||
audio.playback.deviceMaxPeriodFrames * 1.1;
|
audio.playback.deviceMaxPeriodFrames * 1.1 +
|
||||||
|
configLatencyMs * audio.playback.sampleRate / 1000.0;
|
||||||
|
|
||||||
// If the device is currently at a lower period size than its maximum (which
|
// If the device is currently at a lower period size than its maximum (which
|
||||||
// can happen, for example, if another application has requested a lower
|
// can happen, for example, if another application has requested a lower
|
||||||
|
@ -473,6 +473,13 @@ static struct Option options[] =
|
|||||||
.type = OPTION_TYPE_INT,
|
.type = OPTION_TYPE_INT,
|
||||||
.value.x_int = 2048
|
.value.x_int = 2048
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.module = "audio",
|
||||||
|
.name = "bufferLatency",
|
||||||
|
.description = "Additional buffer latency in milliseconds",
|
||||||
|
.type = OPTION_TYPE_INT,
|
||||||
|
.value.x_int = 8
|
||||||
|
},
|
||||||
{0}
|
{0}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -646,6 +653,7 @@ bool config_load(int argc, char * argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
g_params.audioPeriodSize = option_get_int("audio", "periodSize");
|
g_params.audioPeriodSize = option_get_int("audio", "periodSize");
|
||||||
|
g_params.audioBufferLatency = option_get_int("audio", "bufferLatency");
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -201,6 +201,7 @@ struct AppParams
|
|||||||
bool showCursorDot;
|
bool showCursorDot;
|
||||||
|
|
||||||
int audioPeriodSize;
|
int audioPeriodSize;
|
||||||
|
int audioBufferLatency;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CBRequest
|
struct CBRequest
|
||||||
|
Loading…
Reference in New Issue
Block a user