alsaloop: Fix the silence generation in xrun_sync

The silence frames generation in xrun_sync() seems to be currently
a bit off as snd_pcm_format_set_silence() uses a wrong buffer address
and size for zero-ing out the data. Consequently instead of clearing
out the last frame(s), snd_pcm_format_set_silence() ends up silencing
samples somewhere else in the buffer. This is partilarly more obvious
for higher frame sizes (e.g. more than 2 channels).

This patch fixes this issue by correcting the parameters passed to
snd_pcm_format_set_silence().

BugLink: https://github.com/alsa-project/alsa-utils/pull/58
Signed-off-by: Dragos Tarcatu <dragos_tarcatu@mentor.com>
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
This commit is contained in:
Dragos Tarcatu 2020-09-24 06:01:09 +00:00 committed by Jaroslav Kysela
parent 15539cd0e6
commit 8572c0c427

View file

@ -969,13 +969,14 @@ static int xrun_sync(struct loopback *loop)
"sync: playback silence added %li samples\n", (long)diff); "sync: playback silence added %li samples\n", (long)diff);
play->buf_pos -= diff; play->buf_pos -= diff;
play->buf_pos %= play->buf_size; play->buf_pos %= play->buf_size;
if ((err = snd_pcm_format_set_silence(play->format, play->buf + play->buf_pos * play->channels, diff)) < 0) err = snd_pcm_format_set_silence(play->format, play->buf + play->buf_pos * play->frame_size,
diff * play->channels);
if (err < 0)
return err; return err;
play->buf_count += diff; play->buf_count += diff;
} }
if ((err = snd_pcm_prepare(play->handle)) < 0) { if ((err = snd_pcm_prepare(play->handle)) < 0) {
logit(LOG_CRIT, "%s prepare failed: %s\n", play->id, snd_strerror(err)); logit(LOG_CRIT, "%s prepare failed: %s\n", play->id, snd_strerror(err));
return err; return err;
} }
delay1 = writeit(play); delay1 = writeit(play);
@ -1001,7 +1002,9 @@ static int xrun_sync(struct loopback *loop)
"sync: playback short, silence filling %li / buf_count=%li\n", (long)delay1, play->buf_count); "sync: playback short, silence filling %li / buf_count=%li\n", (long)delay1, play->buf_count);
if (delay1 > diff) if (delay1 > diff)
delay1 = diff; delay1 = diff;
if ((err = snd_pcm_format_set_silence(play->format, play->buf + play->buf_pos * play->channels, delay1)) < 0) err = snd_pcm_format_set_silence(play->format, play->buf + play->buf_pos * play->frame_size,
delay1 * play->channels);
if (err < 0)
return err; return err;
play->buf_pos += delay1; play->buf_pos += delay1;
play->buf_pos %= play->buf_size; play->buf_pos %= play->buf_size;