snd_pcm_readn hangs at record & playback on same device

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



alsa-project/alsa-lib issue #368 was edited from nodemand:

I'm on a RPi5 4GB running Raspberry Pi OS 64bit Bookworm and my application hangs on snd_pcm_readn when I try to read and write to the same device. This occurs on an IQAudio Codec Zero sound card and on a HifiBerry DAC+ADC Pro as well. When I select a USB sound card as the output and one of the others described for input everything works like it should. 

Here is my code:

```
#include <alsa/asoundlib.h>
#include <alsa/control.h>
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <algorithm>
#include <iterator>

typedef   signed short	drwav_int16;
typedef   signed int	drwav_int32;

#define PCM_DEVICE_IN "plughw:Zero,0"
#define PCM_DEVICE_OUT "plughw:Zero,0" //"plughw:Device,0"

int err, result, loops, n, t;
unsigned int rate, pcm, tmp;

snd_pcm_t			*play;
snd_pcm_t			*record;
snd_pcm_hw_params_t *playparams;
snd_pcm_hw_params_t *recordparams;
snd_pcm_uframes_t	frames;
snd_pcm_sframes_t	recresult;
snd_pcm_format_t	format = SND_PCM_FORMAT_S16_LE;
int                 block = 0;//SND_PCM_NONBLOCK;

int buffer_frames 			= 	1024;
int bits_per_frame 			= 	16;
const int bits_per_byte		= 	8;
int channels				= 	2;

int bytesize_per_channel  	= 	buffer_frames 
								* bits_per_frame 
								/ bits_per_byte;

int main(int argc, char **argv) {
	if (argc < 3) {
		printf("Usage: %s <sample_rate> <frames>\n", argv[0]);
		return -1;
	}

	rate			= atoi(argv[1]);
	buffer_frames	= atoi(argv[2]);
	
	bytesize_per_channel  	= 	buffer_frames 
								* snd_pcm_format_width(format)  
								/ bits_per_byte;

	drwav_int16 *buffer_in[channels];
	
	/* Open the PCM device in record mode */
	if ((pcm = snd_pcm_open(&record, PCM_DEVICE_IN, SND_PCM_STREAM_CAPTURE, block)) < 0)
		printf("ERROR: Can't open \"%s\" PCM device. %s\n", PCM_DEVICE_IN, snd_strerror(pcm));

	/* Allocate parameters object and fill it with default values*/
	if ((pcm = snd_pcm_hw_params_malloc(&recordparams)) < 0)
		printf("ERROR: Can't allocate hardware parameter structure. %s\n", snd_strerror(pcm));

	if ((pcm = snd_pcm_hw_params_any(record, recordparams)) < 0)
		printf("ERROR: Can't initialize hardware parameter structure. %s\n", snd_strerror(pcm));

	/* Set parameters */
	if ((pcm = snd_pcm_hw_params_set_access(record, recordparams, SND_PCM_ACCESS_RW_NONINTERLEAVED )) < 0) 
		printf("ERROR: Can't set interleaved mode. %s\n", snd_strerror(pcm));

	if ((pcm = snd_pcm_hw_params_set_format(record, recordparams, format)) < 0)
		printf("ERROR: Can't set format. %s\n", snd_strerror(pcm));

	if ((pcm = snd_pcm_hw_params_set_channels(record, recordparams, channels)) < 0) 
		printf("ERROR: Can't set channels number. %s\n", snd_strerror(pcm));

	if ((pcm = snd_pcm_hw_params_set_rate_near(record, recordparams, &rate, 0)) < 0) 
		printf("ERROR: Can't set sample rate. %s\n", snd_strerror(pcm));

	/* Write parameters */
	if ((pcm = snd_pcm_hw_params(record, recordparams)) < 0)
		printf("ERROR: Can't set hardware parameters. %s\n", snd_strerror(pcm));
		
	if ((pcm = snd_pcm_prepare(record)) < 0)
   	 	printf("ERROR: Can't prepare audio interface for use. %s\n", snd_strerror(pcm));
	
    if ((pcm = snd_pcm_start(record)) < 0)
		printf("ERROR: Can't start hardware soundcard. %s\n", snd_strerror(pcm));
		
	/* Resume information */
	printf("PCM name: '%s'\n", snd_pcm_name(record));

	printf("PCM state: %s\n", snd_pcm_state_name(snd_pcm_state(record)));

	snd_pcm_hw_params_get_channels(recordparams, &tmp);
	printf("channels: %i ", tmp);

	if (tmp == 1)
		printf("(mono)\n");
	else if (tmp == 2)
		printf("(stereo)\n");

	snd_pcm_hw_params_get_rate(recordparams, &tmp, 0);
	printf("sample rate: %d bps\n", tmp);
	
	
	
	/* Open the PCM device in playback mode */
	if ((pcm = snd_pcm_open(&play, PCM_DEVICE_OUT, SND_PCM_STREAM_PLAYBACK, block)) < 0)
		printf("ERROR: Can't open \"%s\" PCM device. %s\n", PCM_DEVICE_OUT, snd_strerror(pcm));
		
	if ((pcm = snd_pcm_hw_params_malloc(&playparams)) < 0)
		printf("ERROR: Can't allocate hardware parameter structure. %s\n", snd_strerror(pcm));

	if ((pcm = snd_pcm_hw_params_any(play, playparams)) < 0)
		printf("ERROR: Can't initialize hardware parameter structure. %s\n", snd_strerror(pcm));

	/* Set parameters */
	if ((pcm = snd_pcm_hw_params_set_access(play, playparams, SND_PCM_ACCESS_RW_NONINTERLEAVED )) < 0) 
		printf("ERROR: Can't set interleaved mode. %s\n", snd_strerror(pcm));
		
	if ((pcm = snd_pcm_hw_params_set_format(play, playparams, format)) < 0)
		printf("ERROR: Can't set format. %s\n", snd_strerror(pcm));

	if ((pcm = snd_pcm_hw_params_set_channels(play, playparams, channels)) < 0) 
		printf("ERROR: Can't set channels number. %s\n", snd_strerror(pcm));

	if ((pcm = snd_pcm_hw_params_set_rate_near(play, playparams, &rate, 0)) < 0) 
		printf("ERROR: Can't set sample rate. %s\n", snd_strerror(pcm));

	/* Write parameters */
	if ((pcm = snd_pcm_hw_params(play, playparams)) < 0)
		printf("ERROR: Can't set hardware parameters. %s\n", snd_strerror(pcm));
		
	if ((pcm = snd_pcm_prepare(play)) < 0)
   	 	printf("ERROR: Can't prepare audio interface for use. %s\n", snd_strerror(pcm));
	
    if ((pcm = snd_pcm_start(play)) < 0)
		printf("ERROR: Can't start hardware soundcard. %s\n", snd_strerror(pcm));
	
	/* Resume information */
	printf("PCM name: '%s'\n", snd_pcm_name(play));

	printf("PCM state: %s\n", snd_pcm_state_name(snd_pcm_state(play)));

	snd_pcm_hw_params_get_channels(playparams, &tmp);
	printf("channels: %i ", tmp);

	if (tmp == 1)
		printf("(mono)\n");
	else if (tmp == 2)
		printf("(stereo)\n");

	snd_pcm_hw_params_get_rate(playparams, &tmp, 0);
	printf("sample rate: %d bps\n", tmp);
	
	buffer_in[0]	= (drwav_int16*) malloc(bytesize_per_channel);
	buffer_in[1] 	= (drwav_int16*) malloc(bytesize_per_channel);
	
	printf("buffers allocated: %d bytes per channel\n", bytesize_per_channel);
	
	for (loops = 0; loops < 25000; loops++)
	{

        if ((recresult = snd_pcm_readn(record, (void**) buffer_in, buffer_frames)) < 0) {
             printf ("ERROR. Read from audio interface failed. (%s)\n", snd_strerror(recresult));
            exit(1);
        }
        n = (int) recresult;
        printf("read %d done, %d frames\n", loops, n);
		
		if ((result = snd_pcm_writen(play, (void**) buffer_in, recresult)) == -EPIPE) {
			printf("XRUN.\n");
			snd_pcm_prepare(play);
		} else if (result < 0) {
			printf("ERROR. Can't write to playback device. %s\n", snd_strerror(result));
			exit(1);
		}
		printf("write %d done\n", loops);
	}

	snd_pcm_hw_params_free(playparams);
	snd_pcm_hw_params_free(recordparams);
	printf("params freed\n");
	
	snd_pcm_drain(play);
	snd_pcm_close(play);
	snd_pcm_drain(record);
	snd_pcm_close(record);
	printf("audio interface closed\n");
	
	free(buffer_in[0]);
	free(buffer_in[1]);
	printf("buffers freed\n");

	return 0;
}
```

Issue URL     : https://github.com/alsa-project/alsa-lib/issues/368
Repository URL: https://github.com/alsa-project/alsa-lib



[Index of Archives]     [ALSA User]     [Linux Audio Users]     [Pulse Audio]     [Kernel Archive]     [Asterisk PBX]     [Photo Sharing]     [Linux Sound]     [Video 4 Linux]     [Gimp]     [Yosemite News]

  Powered by Linux