[alsa-devel] Buffer size/periods (Layla3G)

Mark Hills mark at pogo.org.uk
Sun Mar 16 13:02:58 CET 2008


I am investigating problems I'm having with recording over long periods. 
I'm using a Layla3G and tested various ALSA versions including 1.0.14 and 
1.0.16 on different machines.

I've noticed that when I open the first pair of subdevices, my request for 
1000ms buffer size is handled differently to other devices:

   $ ./test_buffers "hw:Layla3G,0,0" 1000
   buffer_size=16384 period_size=128

   $ ./test_buffers "hw:Layla3G,0,2" 1000
   buffer_size=32768 period_size=256

   $ ./test_buffers "hw:Layla3G,0,4" 1000
   buffer_size=32768 period_size=256

   $ ./test_buffers "hw:Layla3G,0,6" 1000
   buffer_size=32768 period_size=256

If I try other buffer sizes, I can see is a limit to buffer size of 16384 
samples on the ,0 subdevice, which is also affecting the chosen period 
size. But only on the first subdevice. Is there a reason, or is this a 

Also, there seem to be failures at certain buffer sizes:

   $ ./test_buffers "hw:Layla3G,0,2" 429
   buffer_size=18912 period_size=96

   $ ./test_buffers "hw:Layla3G,0,2" 430
   set_buffer_time_near: Invalid argument

   $ ./test_buffers "hw:Layla3G,0,2" 431
   buffer_size=19008 period_size=96

Can anyone explain to me what's going on here, or is this also a bug?

The overall problem I'm investigating is snd_pcm_readi() returning 
incomplete buffers after running for long periods until another 
snd_pcm_prepare(). It seems possible that this is related.

Any help is greatly appreciated.


-------------- next part --------------
#include <stdio.h>
#include <alsa/asoundlib.h>

#define RATE 44100
#define CHANNELS 2

#define CHK(msg, r) \
{ \
	if ((r) < 0) { \
		fprintf(stderr, "%s: %s\n", msg, snd_strerror(r)); \
		return -1; \
	} \

int main(int argc, char *argv[])
	int r, dir;
	unsigned int p;
	snd_pcm_t *pcm;
	snd_pcm_hw_params_t *hw_params;
	snd_pcm_uframes_t buffer_size, period_size;

	r = snd_pcm_open(&pcm, argv[1], SND_PCM_STREAM_CAPTURE, 0);
	CHK("open", r);

	r = snd_pcm_hw_params_malloc(&hw_params);
	CHK("params_malloc", r);

	r = snd_pcm_hw_params_any(pcm, hw_params);
	CHK("params_any", r);

	r = snd_pcm_hw_params_set_access(pcm, hw_params,
	CHK("params_set_access", r);

	r = snd_pcm_hw_params_set_format(pcm, hw_params, SND_PCM_FORMAT_S32);
	CHK("set_format", r);

	r = snd_pcm_hw_params_set_rate(pcm, hw_params, RATE, 0);
	CHK("set_rate", r);

	r = snd_pcm_hw_params_set_channels(pcm, hw_params, CHANNELS);

	if (argc > 2) {
	        p = atoi(argv[2]) * 1000;
		r = snd_pcm_hw_params_set_buffer_time_near(pcm, hw_params,
							   &p, &dir);
		CHK("set_buffer_time_near", r);

	if (argc > 3) {
		p = atoi(argv[3]) * 1000;
		r = snd_pcm_hw_params_set_period_time_near(pcm, hw_params,
							   &p, &dir);
		CHK("set_period_time_near", r);

	r = snd_pcm_hw_params(pcm, hw_params);
	CHK("hw_params", r);

	r = snd_pcm_hw_params_get_buffer_size(hw_params, &buffer_size);
	CHK("get_buffer_size", r);

	r = snd_pcm_hw_params_get_period_size(hw_params, &period_size, &dir);
	CHK("get_period_size", r);

	printf("buffer_size=%d period_size=%d\n",
	       (int)buffer_size, (int)period_size);

	r = snd_pcm_close(pcm);
	CHK("pcm_close", r);

	return 0;

More information about the Alsa-devel mailing list