diff mbox series

[3/5] ALSA: pcm: fix playback silence - correct the incremental silencing

Message ID 20230505073813.1219175-4-perex@perex.cz
State New
Headers show
Series rewrite snd_pcm_playback_silence() again | expand

Commit Message

Jaroslav Kysela May 5, 2023, 7:38 a.m. UTC
The incremental silencing was broken with the threshold mode. The silenced
area was smaller than expected in some cases. The updated area starts
at runtime->silence_start + runtime->silence_filled position not
only at runtime->silence_start in this mode.

Unify the runtime->silence_start use for all cases (threshold and top-up).

Suggested-by: Oswald Buddenhagen <oswald.buddenhagen@gmx.de>
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
 sound/core/pcm_lib.c | 24 +++++++++++-------------
 1 file changed, 11 insertions(+), 13 deletions(-)
diff mbox series

Patch

diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index 8a01aeda2213..cfdb4aa5f6fa 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -78,26 +78,24 @@  void snd_pcm_playback_silence(struct snd_pcm_substream *substream, snd_pcm_ufram
 		if (frames > runtime->silence_size)
 			frames = runtime->silence_size;
 	} else {
-		if (new_hw_ptr == ULONG_MAX) {	/* initialization */
+		if (new_hw_ptr == ULONG_MAX) {
+			/* initialization, fill silence to whole unused buffer */
 			snd_pcm_sframes_t avail = snd_pcm_playback_hw_avail(runtime);
 			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;
+			/* top-up mode (appl_ptr is not required) */
+			/* silence the played area immediately */
+			frames = new_hw_ptr - runtime->status->hw_ptr;
 			if ((snd_pcm_sframes_t)frames < 0)
 				frames += runtime->boundary;
-			runtime->silence_filled -= frames;
-			if ((snd_pcm_sframes_t)runtime->silence_filled < 0) {
+			if ((snd_pcm_uframes_t)frames < runtime->silence_filled)
+				runtime->silence_filled -= frames;
+			else
 				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;
 	}
@@ -105,7 +103,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);