mirror of
https://github.com/xemu-project/xemu.git
synced 2024-11-23 11:39:53 +00:00
paaudio: avoid to clip samples multiple times
The pulseaudio backend currently converts, clips and copies audio playback samples in the mixing-engine sample buffer multiple times. In qpa_get_buffer_out() the function pa_stream_begin_write() returns a rather large buffer and this allows audio_pcm_hw_run_out() in audio/audio.c to copy all samples in the mixing-engine buffer to the pulse audio buffer. Immediately after copying, qpa_write() notices with a call to pa_stream_writable_size() that pulse audio only needs a smaller part of the copied samples and ignores the rest. This copy and ignore process happens several times for each audio sample. To fix this behaviour, call pa_stream_writable_size() in qpa_get_buffer_out() to limit the number of samples audio_pcm_hw_run_out() will convert. With this change the pulseaudio pcm_ops functions put_buffer_out and write are no longer identical and a separate qpa_put_buffer_out is needed. Signed-off-by: Volker Rümelin <vr_qemu@t-online.de> Message-id: 9315afe5-5958-c0b4-ea1e-14769511a9d5@t-online.de Message-Id: <20210110100239.27588-13-vr_qemu@t-online.de> Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
This commit is contained in:
parent
6fb0cd5054
commit
bea29e9f2e
@ -207,6 +207,7 @@ static void *qpa_get_buffer_out(HWVoiceOut *hw, size_t *size)
|
|||||||
PAVoiceOut *p = (PAVoiceOut *) hw;
|
PAVoiceOut *p = (PAVoiceOut *) hw;
|
||||||
PAConnection *c = p->g->conn;
|
PAConnection *c = p->g->conn;
|
||||||
void *ret;
|
void *ret;
|
||||||
|
size_t l;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
pa_threaded_mainloop_lock(c->mainloop);
|
pa_threaded_mainloop_lock(c->mainloop);
|
||||||
@ -214,12 +215,19 @@ static void *qpa_get_buffer_out(HWVoiceOut *hw, size_t *size)
|
|||||||
CHECK_DEAD_GOTO(c, p->stream, unlock_and_fail,
|
CHECK_DEAD_GOTO(c, p->stream, unlock_and_fail,
|
||||||
"pa_threaded_mainloop_lock failed\n");
|
"pa_threaded_mainloop_lock failed\n");
|
||||||
|
|
||||||
|
l = pa_stream_writable_size(p->stream);
|
||||||
|
CHECK_SUCCESS_GOTO(c, l != (size_t) -1, unlock_and_fail,
|
||||||
|
"pa_stream_writable_size failed\n");
|
||||||
|
|
||||||
*size = -1;
|
*size = -1;
|
||||||
r = pa_stream_begin_write(p->stream, &ret, size);
|
r = pa_stream_begin_write(p->stream, &ret, size);
|
||||||
CHECK_SUCCESS_GOTO(c, r >= 0, unlock_and_fail,
|
CHECK_SUCCESS_GOTO(c, r >= 0, unlock_and_fail,
|
||||||
"pa_stream_begin_write failed\n");
|
"pa_stream_begin_write failed\n");
|
||||||
|
|
||||||
pa_threaded_mainloop_unlock(c->mainloop);
|
pa_threaded_mainloop_unlock(c->mainloop);
|
||||||
|
if (*size > l) {
|
||||||
|
*size = l;
|
||||||
|
}
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
unlock_and_fail:
|
unlock_and_fail:
|
||||||
@ -228,6 +236,28 @@ unlock_and_fail:
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static size_t qpa_put_buffer_out(HWVoiceOut *hw, void *data, size_t length)
|
||||||
|
{
|
||||||
|
PAVoiceOut *p = (PAVoiceOut *)hw;
|
||||||
|
PAConnection *c = p->g->conn;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
pa_threaded_mainloop_lock(c->mainloop);
|
||||||
|
|
||||||
|
CHECK_DEAD_GOTO(c, p->stream, unlock_and_fail,
|
||||||
|
"pa_threaded_mainloop_lock failed\n");
|
||||||
|
|
||||||
|
r = pa_stream_write(p->stream, data, length, NULL, 0LL, PA_SEEK_RELATIVE);
|
||||||
|
CHECK_SUCCESS_GOTO(c, r >= 0, unlock_and_fail, "pa_stream_write failed\n");
|
||||||
|
|
||||||
|
pa_threaded_mainloop_unlock(c->mainloop);
|
||||||
|
return length;
|
||||||
|
|
||||||
|
unlock_and_fail:
|
||||||
|
pa_threaded_mainloop_unlock(c->mainloop);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static size_t qpa_write(HWVoiceOut *hw, void *data, size_t length)
|
static size_t qpa_write(HWVoiceOut *hw, void *data, size_t length)
|
||||||
{
|
{
|
||||||
PAVoiceOut *p = (PAVoiceOut *) hw;
|
PAVoiceOut *p = (PAVoiceOut *) hw;
|
||||||
@ -861,7 +891,7 @@ static struct audio_pcm_ops qpa_pcm_ops = {
|
|||||||
.fini_out = qpa_fini_out,
|
.fini_out = qpa_fini_out,
|
||||||
.write = qpa_write,
|
.write = qpa_write,
|
||||||
.get_buffer_out = qpa_get_buffer_out,
|
.get_buffer_out = qpa_get_buffer_out,
|
||||||
.put_buffer_out = qpa_write, /* pa handles it */
|
.put_buffer_out = qpa_put_buffer_out,
|
||||||
.volume_out = qpa_volume_out,
|
.volume_out = qpa_volume_out,
|
||||||
|
|
||||||
.init_in = qpa_init_in,
|
.init_in = qpa_init_in,
|
||||||
|
Loading…
Reference in New Issue
Block a user