[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