[Vm-dev] [PATCH 3/3] ALSA: be sensible with buffering thresholds

Daniel Drake dsd at laptop.org
Wed Mar 27 18:14:53 UTC 2013


At http://dev.laptop.org/ticket/12400 we find that Scratch cannot play
sound when the sound hardware buffer is small. The error
"snd_pcm_writei returned -11" is produced and there is no audible output.

This happens because the ALSA backend requests that the sound playback
does not start until 7/8 of the sound has been buffered in hardware.
That is quite a significant amount of buffering to ask for, and in this
case, buffer space ran out before that threshold had been hit.

Improve this code to be more realistic about these thresholds.
I copied the logic from aplay, which hopefully knows what it is doing.
I also made the same changes to the recording path, based on what arecord
does by default.

Index: Squeak-4.10.2.2614-src-no-mp3/unix/vm-sound-ALSA/sqUnixSoundALSA.c
===================================================================
--- Squeak-4.10.2.2614-src-no-mp3.orig/unix/vm-sound-ALSA/sqUnixSoundALSA.c
+++ Squeak-4.10.2.2614-src-no-mp3/unix/vm-sound-ALSA/sqUnixSoundALSA.c
@@ -65,9 +65,6 @@ static void sigio_restore(void);
 /* output */
 
 
-#define SQ_SND_PLAY_START_THRESHOLD	7/8
-#define SQ_SND_PLAY_AVAIL_MIN		4/8
-
 static snd_pcm_t		*output_handle= 0;
 static snd_async_handler_t	*output_handler= 0;
 static int			 output_semaphore= 0;
@@ -99,6 +96,7 @@ static sqInt sound_Start(sqInt frameCoun
   int			 err;
   snd_pcm_hw_params_t	*hwparams;
   snd_pcm_sw_params_t	*swparams;
+  snd_pcm_uframes_t	 period_size;
   unsigned int		 uval;
 
   if (output_handle) sound_Stop();
@@ -120,11 +118,13 @@ static sqInt sound_Start(sqInt frameCoun
 
   snd_pcm_sw_params_alloca(&swparams);
   snd(pcm_sw_params_current(output_handle, swparams), "sound_Start: snd_pcm_sw_params_current");
-  snd(pcm_sw_params_set_start_threshold(output_handle, swparams, frameCount * SQ_SND_PLAY_START_THRESHOLD), "sound_Start: snd_pcm_sw_params_set_start_threshold");
-  snd(pcm_sw_params_set_avail_min(output_handle, swparams, frameCount * SQ_SND_PLAY_AVAIL_MIN), "sound_Start: snd_pcm_sw_parama_set_avail_min");
   snd(pcm_sw_params_set_xfer_align(output_handle, swparams, 1), "sound_Start: snd_pcm_sw_params_set_xfer_align");
   snd(pcm_sw_params(output_handle, swparams), "sound_Start: snd_pcm_sw_params");
+
+  snd(pcm_hw_params_get_period_size(hwparams, &period_size, 0), "sound_Start: pcm_hw_params_get_period_size");
   snd(pcm_hw_params_get_buffer_size(hwparams, &output_buffer_size), "sound_Start: pcm_hw_params_get_buffer_size");
+  snd(pcm_sw_params_set_avail_min(output_handle, swparams, period_size), "sound_Start: snd_pcm_sw_parama_set_avail_min");
+  snd(pcm_sw_params_set_start_threshold(output_handle, swparams, output_buffer_size), "sound_Start: snd_pcm_sw_params_set_start_threshold");
   output_buffer_frames_available= 1;
   max_delay_frames= output_buffer_period_size * 2;	/* set initial delay frames */
 
@@ -246,9 +246,6 @@ static sqInt  sound_PlaySilence(void)
 /* input */
 
 
-#define SQ_SND_REC_START_THRESHOLD	4/8
-#define SQ_SND_REC_AVAIL_MIN		4/8
-
 static snd_pcm_t		*input_handle= 0;
 static snd_async_handler_t	*input_handler= 0;
 static int			 input_semaphore= 0;
@@ -277,6 +274,8 @@ static sqInt sound_StartRecording(sqInt
   snd_pcm_hw_params_t	*hwparams;
   snd_pcm_sw_params_t	*swparams;
   snd_pcm_uframes_t	 frames;
+  snd_pcm_uframes_t	 period_size;
+  snd_pcm_uframes_t	 buffer_size;
 
   if (input_handle) sound_StopRecording();
 
@@ -295,10 +294,13 @@ static sqInt sound_StartRecording(sqInt
   snd_pcm_hw_params_set_period_size_near(input_handle, hwparams, &frames, NULL);
   snd(pcm_hw_params(input_handle, hwparams), "sound_StartRecording: snd_pcm_hw_params");
 
+  snd(pcm_hw_params_get_period_size(hwparams, &period_size, 0), "sound_Start: pcm_hw_params_get_period_size");
+  snd(pcm_hw_params_get_buffer_size(hwparams, &buffer_size), "sound_Start: pcm_hw_params_get_buffer_size");
+
   snd_pcm_sw_params_alloca(&swparams);
   snd(pcm_sw_params_current(input_handle, swparams), "sound_StartRecording: snd_pcm_sw_params_current");
-  snd(pcm_sw_params_set_start_threshold(input_handle, swparams, frames * SQ_SND_REC_START_THRESHOLD), "sound_StartRecording: snd_pcm_sw_params_set_start_threshold");
-  snd(pcm_sw_params_set_avail_min(input_handle, swparams, frames * SQ_SND_REC_AVAIL_MIN), "sound_StartRecording: snd_pcm_sw_parama_set_avail_min");
+  snd(pcm_sw_params_set_start_threshold(input_handle, swparams, buffer_size), "sound_StartRecording: snd_pcm_sw_params_set_start_threshold");
+  snd(pcm_sw_params_set_avail_min(input_handle, swparams, period_size), "sound_StartRecording: snd_pcm_sw_parama_set_avail_min");
   snd(pcm_sw_params_set_xfer_align(input_handle, swparams, 1), "sound_StartRecording: snd_pcm_sw_params_set_xfer_align");
   snd(pcm_sw_params(input_handle, swparams), "sound_StartRecording: snd_pcm_sw_params");
 


More information about the Vm-dev mailing list