ALSA: pcm: fix playback silence - correct incremental silencing
authorJaroslav Kysela <perex@perex.cz>
Fri, 5 May 2023 15:52:40 +0000 (17:52 +0200)
committerTakashi Iwai <tiwai@suse.de>
Fri, 5 May 2023 16:23:50 +0000 (18:23 +0200)
Commit 9a826ddba6e ("[ALSA] pcm core: fix silence_start calculations")
came with exactly the right commit message, but the patch just made
things broken in a different way: We'd fill at a too low address if the
area was already partially zeroed, so we'd under-fill. This affected
both thresholded mode (where it was somewhat less likely) and top-up
mode (where it would be the case consistently).

Co-developed-by: Oswald Buddenhagen <oswald.buddenhagen@gmx.de>
Signed-off-by: Oswald Buddenhagen <oswald.buddenhagen@gmx.de>
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
Link: https://lore.kernel.org/r/20230505155244.2312199-3-oswald.buddenhagen@gmx.de
Signed-off-by: Takashi Iwai <tiwai@suse.de>
sound/core/pcm_lib.c

index 6ad67e7..5ddb74a 100644 (file)
@@ -87,9 +87,7 @@ void snd_pcm_playback_silence(struct snd_pcm_substream *substream, snd_pcm_ufram
                        if (avail > runtime->buffer_size)
                                avail = runtime->buffer_size;
                        runtime->silence_filled = avail > 0 ? avail : 0;
-                       runtime->silence_start = (runtime->status->hw_ptr +
-                                                 runtime->silence_filled) %
-                                                runtime->boundary;
+                       runtime->silence_start = runtime->status->hw_ptr;
                } else {
                        ofs = runtime->status->hw_ptr;
                        frames = new_hw_ptr - ofs;
@@ -98,10 +96,8 @@ void snd_pcm_playback_silence(struct snd_pcm_substream *substream, snd_pcm_ufram
                        runtime->silence_filled -= frames;
                        if ((snd_pcm_sframes_t)runtime->silence_filled < 0) {
                                runtime->silence_filled = 0;
-                               runtime->silence_start = new_hw_ptr;
-                       } else {
-                               runtime->silence_start = ofs;
                        }
+                       runtime->silence_start = new_hw_ptr;
                }
                frames = runtime->buffer_size - runtime->silence_filled;
        }
@@ -109,7 +105,7 @@ void snd_pcm_playback_silence(struct snd_pcm_substream *substream, snd_pcm_ufram
                return;
        if (frames == 0)
                return;
-       ofs = runtime->silence_start % runtime->buffer_size;
+       ofs = (runtime->silence_start + runtime->silence_filled) % runtime->buffer_size;
        while (frames > 0) {
                transfer = ofs + frames > runtime->buffer_size ? runtime->buffer_size - ofs : frames;
                err = fill_silence_frames(substream, ofs, transfer);