Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

snd_pcm_readn hangs at record & playback on same device #368

Closed
nodemand opened this issue Nov 20, 2023 · 27 comments
Closed

snd_pcm_readn hangs at record & playback on same device #368

nodemand opened this issue Nov 20, 2023 · 27 comments

Comments

@nodemand
Copy link

nodemand commented Nov 20, 2023

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;
}
@aditpape
Copy link
Contributor

some remarks:
a) unsigned int rate, pcm, tmp; --> 'pcm' should be signed as used to check return values <0
b) you configure and start capture device before even having opened the playback device.
opening + configuring playback device can take quite long time and leading to capture device already going into overrun
-> first configure both devices before starting capture device
c) playback device gets started w/o having written data to it -> may immediately enter underrun
d) I see no explicit configuration of buffer / period size. The read request 'buffer_frames' may be even bigger than overall buffer size
e) use snd_pcm_dump() to check the finally accepted configuration

@nodemand
Copy link
Author

nodemand commented Nov 20, 2023

Hi @aditpape, thanks for you feedback! I corrected most things:
a) done
b) done
c) I'm not sure what you mean by this
d) I reserve the correct amount of memory with malloc. is this not enough?
e) I'm getting the following error: pcm.c:2378: snd_pcm_dump: Assertion `out' failed.

this is my new 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 pcm, err, result, loops, n, t;
unsigned int rate, 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;
static snd_output_t *info = NULL;
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));
		
	/* 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));
	
	/* 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);
	
	
	
	
	
	
	// allocate buffers
	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);
	
	
	
	// check accepted configuration
	err = snd_pcm_dump(play, info);
	err = snd_pcm_dump(record, info);
	
	
	
	
	// start both devices
	if ((pcm = snd_pcm_start(play)) < 0)
		printf("ERROR: Can't start soundcard for playback. %s\n", snd_strerror(pcm));
	
	if ((pcm = snd_pcm_start(record)) < 0)
		printf("ERROR: Can't start soundcard for recording. %s\n", snd_strerror(pcm));
	
	
	
	

	
	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;
}

output:

PCM name: 'plughw:Zero,0'
PCM state: PREPARED
channels: 2 (stereo)
sample rate: 48000 bps
PCM name: 'plughw:Zero,0'
PCM state: PREPARED
channels: 2 (stereo)
sample rate: 48000 bps
buffers allocated: 2048 bytes per channel
ps9: pcm.c:2378: snd_pcm_dump: Assertion `out' failed.
Aborted

Also, I have the same issue when I switch to PortAudio. Then my application hangs on Pa_ReadStream. And I'm using one of their examples as the basis of my application.

@aditpape
Copy link
Contributor

aditpape commented Nov 21, 2023

c) refer to 'start_threshold'. You should start the device once full or enough data got written to it.
Also relates to d)..
d) you implement a 'forwarding' which requires some alignment of chunk sized read from input and written to output.
In ideal case you configure same period size on input and output and forward period by period.

e) needs initialization like e.g.
snd_output_stdio_attach(&info, stderr, 0);

Also, I have the same issue when I switch to PortAudio.

Assume you refer to PulseAudio via pulse ALSA plugin?
EDIT: PortAudio is right (ref: Pa_ReadStream), was not aware that same prefix PA is used at API than for PulseAudio

@nodemand
Copy link
Author

ok, I have output!

PCM name: 'plughw:Zero,0'
PCM state: PREPARED
channels: 2 (stereo)
sample rate: 48000 bps
PCM name: 'plughw:Zero,0'
PCM state: PREPARED
channels: 2 (stereo)
sample rate: 48000 bps
buffers allocated: 2048 bytes per channel
Plug PCM: Copy conversion PCM
Its setup is:
  stream       : PLAYBACK
  access       : RW_NONINTERLEAVED
  format       : S16_LE
  subformat    : STD
  channels     : 2
  rate         : 48000
  exact rate   : 48000 (48000/1)
  msbits       : 16
  buffer_size  : 131072
  period_size  : 256
  period_time  : 5333
  tstamp_mode  : NONE
  tstamp_type  : MONOTONIC
  period_step  : 1
  avail_min    : 256
  period_event : 0
  start_threshold  : 1
  stop_threshold   : 131072
  silence_threshold: 0
  silence_size : 0
  boundary     : 4611686018427387904
Slave: Hardware PCM card 0 'RPi Codec Zero' device 0 subdevice 0
Its setup is:
  stream       : PLAYBACK
  access       : MMAP_INTERLEAVED
  format       : S16_LE
  subformat    : STD
  channels     : 2
  rate         : 48000
  exact rate   : 48000 (48000/1)
  msbits       : 16
  buffer_size  : 131072
  period_size  : 256
  period_time  : 5333
  tstamp_mode  : NONE
  tstamp_type  : MONOTONIC
  period_step  : 1
  avail_min    : 256
  period_event : 0
  start_threshold  : 1
  stop_threshold   : 131072
  silence_threshold: 0
  silence_size : 0
  boundary     : 4611686018427387904
  appl_ptr     : 0
  hw_ptr       : 0
Plug PCM: Copy conversion PCM
Its setup is:
  stream       : CAPTURE
  access       : RW_NONINTERLEAVED
  format       : S16_LE
  subformat    : STD
  channels     : 2
  rate         : 48000
  exact rate   : 48000 (48000/1)
  msbits       : 16
  buffer_size  : 131072
  period_size  : 256
  period_time  : 5333
  tstamp_mode  : NONE
  tstamp_type  : MONOTONIC
  period_step  : 1
  avail_min    : 256
  period_event : 0
  start_threshold  : 1
  stop_threshold   : 131072
  silence_threshold: 0
  silence_size : 0
  boundary     : 4611686018427387904
Slave: Hardware PCM card 0 'RPi Codec Zero' device 0 subdevice 0
Its setup is:
  stream       : CAPTURE
  access       : MMAP_INTERLEAVED
  format       : S16_LE
  subformat    : STD
  channels     : 2
  rate         : 48000
  exact rate   : 48000 (48000/1)
  msbits       : 16
  buffer_size  : 131072
  period_size  : 256
  period_time  : 5333
  tstamp_mode  : NONE
  tstamp_type  : MONOTONIC
  period_step  : 1
  avail_min    : 256
  period_event : 0
  start_threshold  : 1
  stop_threshold   : 131072
  silence_threshold: 0
  silence_size : 0
  boundary     : 4611686018427387904
  appl_ptr     : 0
  hw_ptr       : 0
ERROR: Can't start soundcard for playback. Broken pipe

@nodemand
Copy link
Author

nodemand commented Nov 21, 2023

I switched to buffer_frames = 256 instead of 1024 and I wrote some data into the playback device before starting it. Now the broken pipe error disappeared but my app still hangs.

PCM name: 'plughw:Zero,0'
PCM state: PREPARED
channels: 2 (stereo)
sample rate: 48000 bps
PCM name: 'plughw:Zero,0'
PCM state: PREPARED
channels: 2 (stereo)
sample rate: 48000 bps
buffers allocated: 512 bytes per channel
Plug PCM: Copy conversion PCM
Its setup is:
  stream       : PLAYBACK
  access       : RW_NONINTERLEAVED
  format       : S16_LE
  subformat    : STD
  channels     : 2
  rate         : 48000
  exact rate   : 48000 (48000/1)
  msbits       : 16
  buffer_size  : 131072
  period_size  : 256
  period_time  : 5333
  tstamp_mode  : NONE
  tstamp_type  : MONOTONIC
  period_step  : 1
  avail_min    : 256
  period_event : 0
  start_threshold  : 1
  stop_threshold   : 131072
  silence_threshold: 0
  silence_size : 0
  boundary     : 4611686018427387904
Slave: Hardware PCM card 0 'RPi Codec Zero' device 0 subdevice 0
Its setup is:
  stream       : PLAYBACK
  access       : MMAP_INTERLEAVED
  format       : S16_LE
  subformat    : STD
  channels     : 2
  rate         : 48000
  exact rate   : 48000 (48000/1)
  msbits       : 16
  buffer_size  : 131072
  period_size  : 256
  period_time  : 5333
  tstamp_mode  : NONE
  tstamp_type  : MONOTONIC
  period_step  : 1
  avail_min    : 256
  period_event : 0
  start_threshold  : 1
  stop_threshold   : 131072
  silence_threshold: 0
  silence_size : 0
  boundary     : 4611686018427387904
  appl_ptr     : 0
  hw_ptr       : 0
Plug PCM: Copy conversion PCM
Its setup is:
  stream       : CAPTURE
  access       : RW_NONINTERLEAVED
  format       : S16_LE
  subformat    : STD
  channels     : 2
  rate         : 48000
  exact rate   : 48000 (48000/1)
  msbits       : 16
  buffer_size  : 131072
  period_size  : 256
  period_time  : 5333
  tstamp_mode  : NONE
  tstamp_type  : MONOTONIC
  period_step  : 1
  avail_min    : 256
  period_event : 0
  start_threshold  : 1
  stop_threshold   : 131072
  silence_threshold: 0
  silence_size : 0
  boundary     : 4611686018427387904
Slave: Hardware PCM card 0 'RPi Codec Zero' device 0 subdevice 0
Its setup is:
  stream       : CAPTURE
  access       : MMAP_INTERLEAVED
  format       : S16_LE
  subformat    : STD
  channels     : 2
  rate         : 48000
  exact rate   : 48000 (48000/1)
  msbits       : 16
  buffer_size  : 131072
  period_size  : 256
  period_time  : 5333
  tstamp_mode  : NONE
  tstamp_type  : MONOTONIC
  period_step  : 1
  avail_min    : 256
  period_event : 0
  start_threshold  : 1
  stop_threshold   : 131072
  silence_threshold: 0
  silence_size : 0
  boundary     : 4611686018427387904
  appl_ptr     : 0
  hw_ptr       : 0

oh, and I just remembered, I also tried alsaloop and piping audio from arecord to aplay using some examples, but nowhere ever does there come audio out of the lineout of the same device I record from...

@aditpape
Copy link
Contributor

propose to verify the underlaying devices separately with aplay/arecord..

aplay -vvv -Dplughw:Zero,0 -fdat /dev/urandom
arecord -vvv -Dplughw:Zero,0 -fdat >/dev/null

once properly working separately you can form a forwarding via arecord | aplay

..and if that is working you can continue with your own app.

@nodemand
Copy link
Author

nodemand commented Nov 21, 2023

both arecord and aplay work as they did before, but forwarding is where it goes wrong. I tried that already as I said ...
output of aplay:

Playing raw data '/dev/urandom' : Signed 16 bit Little Endian, Rate 48000 Hz, Stereo
Plug PCM: Hardware PCM card 0 'RPi Codec Zero' device 0 subdevice 0
Its setup is:
  stream       : PLAYBACK
  access       : RW_INTERLEAVED
  format       : S16_LE
  subformat    : STD
  channels     : 2
  rate         : 48000
  exact rate   : 48000 (48000/1)
  msbits       : 16
  buffer_size  : 23552
  period_size  : 1024
  period_time  : 21333
  tstamp_mode  : NONE
  tstamp_type  : MONOTONIC
  period_step  : 1
  avail_min    : 1024
  period_event : 0
  start_threshold  : 23552
  stop_threshold   : 23552
  silence_threshold: 0
  silence_size : 0
  boundary     : 6629298651489370112
  appl_ptr     : 0
  hw_ptr       : 0
Max peak (2048 samples): 0x00007fee #################### 99%
Max peak (2048 samples): 0x00007fdf #################### 99%
Max peak (2048 samples): 0x00007ffb #################### 99%
Max peak (2048 samples): 0x00007ff1 #################### 99%
Max peak (2048 samples): 0x00007fe3 #################### 99%
Max peak (2048 samples): 0x00007fed #################### 99%
Max peak (2048 samples): 0x00007ffb #################### 99%
Max peak (2048 samples): 0x00007ff9 #################### 99%
Max peak (2048 samples): 0x00007ff7 #################### 99%
Max peak (2048 samples): 0x00007fff #################### 99%
Max peak (2048 samples): 0x00007fe2 #################### 99%
Max peak (2048 samples): 0x00007ffb #################### 99%
Max peak (2048 samples): 0x00007ffc #################### 99%
Max peak (2048 samples): 0x00007fe8 #################### 99%
Max peak (2048 samples): 0x00007ffc #################### 99%
Max peak (2048 samples): 0x00007ff5 #################### 99%
Max peak (2048 samples): 0x00007fed #################### 99%
Max peak (2048 samples): 0x00007fee #################### 99%
Max peak (2048 samples): 0x00007fee #################### 99%
Max peak (2048 samples): 0x00007ff4 #################### 99%
Max peak (2048 samples): 0x00007fdf #################### 99%
Max peak (2048 samples): 0x00007ff3 #################### 99%
Max peak (2048 samples): 0x00007ffb #################### 99%
Max peak (2048 samples): 0x00007fed #################### 99%
Max peak (2048 samples): 0x00007ff9 #################### 99%
Max peak (2048 samples): 0x00007fe4 #################### 99%

output of arecord:

Recording WAVE 'stdin' : Signed 16 bit Little Endian, Rate 48000 Hz, Stereo
Plug PCM: Hardware PCM card 0 'RPi Codec Zero' device 0 subdevice 0
Its setup is:
  stream       : CAPTURE
  access       : RW_INTERLEAVED
  format       : S16_LE
  subformat    : STD
  channels     : 2
  rate         : 48000
  exact rate   : 48000 (48000/1)
  msbits       : 16
  buffer_size  : 23552
  period_size  : 1024
  period_time  : 21333
  tstamp_mode  : NONE
  tstamp_type  : MONOTONIC
  period_step  : 1
  avail_min    : 1024
  period_event : 0
  start_threshold  : 1
  stop_threshold   : 23552
  silence_threshold: 0
  silence_size : 0
  boundary     : 6629298651489370112
  appl_ptr     : 0
  hw_ptr       : 0
Max peak (2048 samples): 0x00000e9c ###                  11%
Max peak (2048 samples): 0x00001025 ###                  12%
Max peak (2048 samples): 0x00000d8e ###                  10%
Max peak (2048 samples): 0x00001039 ###                  12%
Max peak (2048 samples): 0x000011c4 ###                  13%
Max peak (2048 samples): 0x00000eac ###                  11%
Max peak (2048 samples): 0x000014ac ####                 16%
Max peak (2048 samples): 0x0000167f ####                 17%
Max peak (2048 samples): 0x000016d0 ####                 17%
Max peak (2048 samples): 0x00001545 ####                 16%
Max peak (2048 samples): 0x000011c1 ###                  13%
Max peak (2048 samples): 0x00001158 ###                  13%
Max peak (2048 samples): 0x00001233 ###                  14%
Max peak (2048 samples): 0x000017ca ####                 18%
Max peak (2048 samples): 0x0000125b ###                  14%
Max peak (2048 samples): 0x000010b1 ###                  13%
Max peak (2048 samples): 0x00000e5d ###                  11%
Max peak (2048 samples): 0x00001047 ###                  12%
Max peak (2048 samples): 0x00000fa8 ###                  12%
Max peak (2048 samples): 0x000008bc ##                   6%
Max peak (2048 samples): 0x00001eb2 #####                23%

EDIT:

arecord -f S16_LE -r48000 -c2 -D plughw:Zero,0 -F0 --period-size=256 -B0 --buffer-size=4096 | aplay -D plughw:Zero,0 -

Recording WAVE 'stdin' : Signed 16 bit Little Endian, Rate 48000 Hz, Stereo
Playing WAVE 'stdin' : Signed 16 bit Little Endian, Rate 48000 Hz, Stereo
arecord: pcm_read:2221: read error: Input/output error

so how do I get the forwarding to work?

@aditpape
Copy link
Contributor

Seems devices do not accept duplex mode.. (using as playback and capture simultaneously)
-you can verify by issuing arecord + aplay in separate shells...

@nodemand
Copy link
Author

nodemand commented Nov 21, 2023

I opened two SSH connections to my RPi. One with:
arecord -f S16_LE -r48000 -c2 -D plughw:Zero,0 -F0 --period-size=256 -B0 --buffer-size=4096 test.wav
and one with:
aplay test.wav -f S16_LE -r48000 -c2 -D plughw:Zero,0

And I do actually hear music!
After awhile though I get "arecord: pcm_read:2221: read error: Input/output error", but that might be because of both shells reading and writing to the same file?

@aditpape
Copy link
Contributor

aditpape commented Nov 21, 2023

After awhile though I get "arecord: pcm_read:2221: read error: Input/output error",

That error is returned from the snd_pcm_readX()-API, thus cannot be related to the concurrent access to file.
-> any error seen in kernel log ? (dmesg)
-> error seen after 5 or 10s of 'blocking'? (there are timeout value in kernel which are 5 or 10s..)

Also, for verification, access hardware as direct as possible.. (remove plugins)
plughw -> hw

@nodemand
Copy link
Author

nodemand commented Nov 21, 2023

I'm not sure if this is what we are looking for but there are errors:

[   10.533134] brcmfmac mmc1:0001:1: firmware: failed to load brcm/brcmfmac43455-sdio.raspberrypi,5-model-b.bin (-2)
[   10.533142] firmware_class: See https://wiki.debian.org/Firmware for information about missing firmware
[   10.533146] brcmfmac mmc1:0001:1: Direct firmware load for brcm/brcmfmac43455-sdio.raspberrypi,5-model-b.bin failed with error -2
[   10.542402] Registered IR keymap rc-cec
[   10.548627] brcmfmac mmc1:0001:1: firmware: direct-loading firmware brcm/brcmfmac43455-sdio.bin
[   10.548690] brcmfmac mmc1:0001:1: firmware: failed to load brcm/brcmfmac43455-sdio.raspberrypi,5-model-b.txt (-2)
[   10.550827] brcmfmac mmc1:0001:1: firmware: direct-loading firmware brcm/brcmfmac43455-sdio.txt
[   10.551426] brcmfmac mmc1:0001:1: firmware: failed to load brcm/brcmfmac43455-sdio.raspberrypi,5-model-b.clm_blob (-2)

Going from plughw to hw makes no difference. Same error...

@aditpape
Copy link
Contributor

messages in kernel log are not audio related..
If EINVVAL is also seen when directly acting on hardware it is more pointing to issue in the kernel / sound driver.
-You may try to avoid the 'termination' of aplay / arecord by using nonblocking access via -N option.
-then monitor device status in procfs whether device's status is still 'running' and hw pointer is still moving.
cat /proc/asound/card ...

@nodemand
Copy link
Author

nodemand commented Nov 21, 2023

When I add the -N option to both commands the error does not show anymore, but playback with aplay stops prematurely. arecord just keeps on going without any errors...

status: RUNNING
Nope. HW pointer is NOT moving

@aditpape
Copy link
Contributor

aditpape commented Nov 21, 2023

'status' or 'info' should show the runtime..
doing cat multiple times should show hw_ptr moving
-do on both input and output stream: pcm0c= capture, pcm0p = playback

@aditpape
Copy link
Contributor

status: RUNNING
Nope. HW pointer is NOT moving

hw doesn't give any more interrupts...

@nodemand
Copy link
Author

nodemand commented Nov 21, 2023

btw this was on the record stream...

@nodemand
Copy link
Author

nodemand commented Nov 21, 2023

doing cat multiple times should show hw_ptr moving

it does, but as soon as I start aplay in another shell, it stops moving

@aditpape
Copy link
Contributor

Correct alsa state files 'loaded'?
https://github.com/raspberrypi/Pi-Codec/tree/master

For duplex operation AUXIN HPOUT seems a dedicated state file needed.
Codec_Zero_AUXIN_record_and_HP_playback.state

sudo alsactl restore -f

@nodemand
Copy link
Author

ahhh yes, I ran into a little problem there. But not with the HifiBerry with which I have the same issue. Anyway, this is the output of sudo alsactl restore -f:

alsa-lib main.c:1541:(snd_use_case_mgr_open) error: failed to import hw:0 use case configuration -2
No state is present for card Device
Found hardware: "USB-Audio" "USB Mixer" "USB040d:340a" "" ""
Hardware is initialized using a generic method
No state is present for card Device

@aditpape
Copy link
Contributor

command for your case should be:
sudo alsactl restore -f Codec_Zero_AUXIN_record_and_HP_playback.state

Topic seems to turn into pure 'Raspi codec related', thus 'Rapi forum' may help further.

@nodemand
Copy link
Author

I ran that command exactly. And no. Like I said it also happens with the HifiBerry!

@aditpape
Copy link
Contributor

Not that familiar with the alsactrl + involvement of the UCM (use case manager)
-as 'hw:0' and even 'USB' sound cards are mentioned in alsactrl output you could instruct alsactrl to only act on your Zero card.
sudo alsactl restore Zero -f Codec_Zero_AUXIN_record_and_HP_playback.state

If that also does not help, I am 'out'

@nodemand
Copy link
Author

Same error I'm afraid. Ok, well thank you very much for your input! I learned a lot! Thanx!

@nodemand
Copy link
Author

I double checked EVERYTHING with only the HifiBerry installed and exactly the same symptoms as with the IQAudio Codec Zero! In the end the HW pointer stops moving as soon as I start aplay in a different shell and arecord exits with a 2221 input/output error. Help!

@perexg
Copy link
Member

perexg commented Nov 25, 2023

It looks like an issue with the BCM I2S kernel driver for RPi 5. You should consult your issue in the RPi forums.

@nodemand
Copy link
Author

Ok! Thank you! Will investigate further in the RPi forums…

@nodemand
Copy link
Author

It's fixed!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants