aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--audio/paaudio.c44
-rw-r--r--qapi/audio.json6
2 files changed, 39 insertions, 11 deletions
diff --git a/audio/paaudio.c b/audio/paaudio.c
index 5d410ed73f..45295b4e5e 100644
--- a/audio/paaudio.c
+++ b/audio/paaudio.c
@@ -549,12 +549,8 @@ static int qpa_init_out(HWVoiceOut *hw, struct audsettings *as,
ss.channels = as->nchannels;
ss.rate = as->freq;
- /*
- * qemu audio tick runs at 100 Hz (by default), so processing
- * data chunks worth 10 ms of sound should be a good fit.
- */
- ba.tlength = pa_usec_to_bytes (10 * 1000, &ss);
- ba.minreq = pa_usec_to_bytes (5 * 1000, &ss);
+ ba.tlength = pa_usec_to_bytes(ppdo->latency, &ss);
+ ba.minreq = -1;
ba.maxlength = -1;
ba.prebuf = -1;
@@ -577,7 +573,8 @@ static int qpa_init_out(HWVoiceOut *hw, struct audsettings *as,
audio_pcm_init_info (&hw->info, &obt_as);
hw->samples = pa->samples = audio_buffer_samples(
- qapi_AudiodevPaPerDirectionOptions_base(ppdo), &obt_as, 46440);
+ qapi_AudiodevPaPerDirectionOptions_base(ppdo),
+ &obt_as, ppdo->buffer_length);
pa->pcm_buf = audio_calloc(__func__, hw->samples, 1 << hw->info.shift);
pa->rpos = hw->rpos;
if (!pa->pcm_buf) {
@@ -608,6 +605,7 @@ static int qpa_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque)
{
int error;
pa_sample_spec ss;
+ pa_buffer_attr ba;
struct audsettings obt_as = *as;
PAVoiceIn *pa = (PAVoiceIn *) hw;
paaudio *g = pa->g = drv_opaque;
@@ -618,6 +616,11 @@ static int qpa_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque)
ss.channels = as->nchannels;
ss.rate = as->freq;
+ ba.fragsize = pa_usec_to_bytes(ppdo->latency, &ss);
+ ba.maxlength = -1;
+ ba.minreq = -1;
+ ba.prebuf = -1;
+
obt_as.fmt = pa_to_audfmt (ss.format, &obt_as.endianness);
pa->stream = qpa_simple_new (
@@ -627,7 +630,7 @@ static int qpa_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque)
ppdo->has_name ? ppdo->name : NULL,
&ss,
NULL, /* channel map */
- NULL, /* buffering attributes */
+ &ba, /* buffering attributes */
&error
);
if (!pa->stream) {
@@ -637,7 +640,8 @@ static int qpa_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque)
audio_pcm_init_info (&hw->info, &obt_as);
hw->samples = pa->samples = audio_buffer_samples(
- qapi_AudiodevPaPerDirectionOptions_base(ppdo), &obt_as, 46440);
+ qapi_AudiodevPaPerDirectionOptions_base(ppdo),
+ &obt_as, ppdo->buffer_length);
pa->pcm_buf = audio_calloc(__func__, hw->samples, 1 << hw->info.shift);
pa->wpos = hw->wpos;
if (!pa->pcm_buf) {
@@ -809,7 +813,20 @@ static int qpa_ctl_in (HWVoiceIn *hw, int cmd, ...)
return 0;
}
-/* common */
+static int qpa_validate_per_direction_opts(Audiodev *dev,
+ AudiodevPaPerDirectionOptions *pdo)
+{
+ if (!pdo->has_buffer_length) {
+ pdo->has_buffer_length = true;
+ pdo->buffer_length = 46440;
+ }
+ if (!pdo->has_latency) {
+ pdo->has_latency = true;
+ pdo->latency = 15000;
+ }
+ return 1;
+}
+
static void *qpa_audio_init(Audiodev *dev)
{
paaudio *g;
@@ -836,6 +853,13 @@ static void *qpa_audio_init(Audiodev *dev)
g = g_malloc(sizeof(paaudio));
server = popts->has_server ? popts->server : NULL;
+ if (!qpa_validate_per_direction_opts(dev, popts->in)) {
+ goto fail;
+ }
+ if (!qpa_validate_per_direction_opts(dev, popts->out)) {
+ goto fail;
+ }
+
g->dev = dev;
g->mainloop = NULL;
g->context = NULL;
diff --git a/qapi/audio.json b/qapi/audio.json
index 97aee37288..9fefdf5186 100644
--- a/qapi/audio.json
+++ b/qapi/audio.json
@@ -206,12 +206,16 @@
#
# @name: name of the sink/source to use
#
+# @latency: latency you want PulseAudio to achieve in microseconds
+# (default 15000)
+#
# Since: 4.0
##
{ 'struct': 'AudiodevPaPerDirectionOptions',
'base': 'AudiodevPerDirectionOptions',
'data': {
- '*name': 'str' } }
+ '*name': 'str',
+ '*latency': 'uint32' } }
##
# @AudiodevPaOptions: