ReSpeaker 6-Mic Circular Array Pi HAT for Raspberry pi 4b . Use alsa API record voice error . I need help

Hi:

We recorded use ReSpeaker 6-Mic Circular Array Pi HAT . Raspberry pi 4b .

we use alsa api Play and record at the same time. but record voice error!

We play pcm use plughw:1,0 , one channel pcm ;

We record pcm use hw:1,0 , eight channel pcm;

I need technical support.

I use ALSA API record voice error.

hw:1,0 record 8 channel pcm.

plughw:1,0 play 1 channel pcm.

program run error .

The record proc error info .

FILE: rec.c, LINE: 186: short read, read 13 _frames

ret:-3

FILE: rec.c, LINE: 180: error from read: Input/output error

the record voice code:
#ifndef GLOBAL_DEF_H
#define GLOBAL_DEF_H

#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>

#define MicChannels 4 //Number of array elements
#define SAMPLERATE 16000
#define IN_CHANNELS 8
#define OUT_CHANNELS 1
#define OUT_8CHANNELS 8
#define SAMPLEBYTES 2
#define SAMPLENUM 160 //20ms @ 16kHz

#if ONE_AEC
#define NEAR_IN_CH 1
#else
#define NEAR_IN_CH 4
#endif

#define AEC_OUT_CH NEAR_IN_CH
#define REF_CH_NUM 6
#define PRIORITY_URGENT_AUDIO -19
#define SP_FOREGROUND 1

#define OUTPUT_GAIN_TO_INT16 (32768.0f)
#define SAT32(a) ((a) > 32767 ? 32767 : ((a) < -32768 ? -32768 : (a)))

#endif

#ifndef RECORD_LOCAL_MICARRAY_H
#define RECORD_LOCAL_MICARRAY_H

#include <alsa/asoundlib.h>
#include <sys/time.h>
#include <stdio.h>
#include <stdlib.h>

#ifdef __cplusplus
extern “C” {
#endif /* C++ */

int Record_mic_array_init(int *bytes_num);
int Record_mic_array_deinit();
int Record_mic_array_read(void * buffer, int bytes);

#ifdef __cplusplus
} /* extern “C” /
#endif /
C++ */

#endif //RECORD_LOCAL_MICARRAY_H

#include “record.h”
#include “globaldef.h”

#define LOG 1

#if LOG
#define LOG(format,…) printf("FILE: " FILE ", LINE: %d: " format “\n”, LINE, ##VA_ARGS)
#else
#define LOG(format,…)
#endif

typedef struct Record_mic_array{
int _rc;
int _nm;
int _dir;
int _all_channebuf_size;
int _bytes_num;

unsigned _channels;
unsigned _samplerate;
snd_pcm_uframes_t _sampleNumPerCh;
FILE * outputfile;
char* _record_8_bufferr;

snd_pcm_t* _handle;
snd_pcm_hw_params_t *_params;
snd_pcm_uframes_t _frames;
snd_pcm_uframes_t _period_size;
snd_pcm_uframes_t _buffer_size;

} Record_mic_array;

static Record_mic_array recmod = {
._rc=0,
._nm = 0,
._dir=0,
._all_channebuf_size = 0,
._bytes_num = SAMPLEBYTES*2,
._channels = IN_CHANNELS,
._samplerate = SAMPLERATE,
._sampleNumPerCh = SAMPLENUM, //10ms @ 16kHz
.outputfile = NULL
};

int32_t * pcm_int32buf = NULL;

int Record_mic_array_init( int32_t *bytes_num )
{
LOG("%s: Record_8mic_Respeaker Init Begin!\n", func);

//liyanan add
recmod.outputfile = fopen("rec_output.pcm", "wb+");
if(NULL == recmod.outputfile)
{
	printf("open librec.so output file failed \n");
    return -1;
}
else
	printf("open librec.so output file successfully \n");
//liyanan add 

//printf("_bytes_num:%d _samplerate:%d _sampleNumPerCh:%d\n", _bytes_num, _samplerate, _sampleNumPerCh);
recmod._rc = snd_pcm_open(&recmod._handle, "hw:1,0", SND_PCM_STREAM_CAPTURE, 0);
if (recmod._rc < 0)
{
	LOG("unable to open pcm device: %s \n",  snd_strerror(recmod._rc));
	return -1;
}

LOG("%s: Device Successfully Initialized!\n", __func__);
snd_pcm_hw_params_malloc(&recmod._params);
snd_pcm_hw_params_any(recmod._handle, recmod._params);

recmod._rc = snd_pcm_hw_params_set_access(recmod._handle, recmod._params, SND_PCM_ACCESS_RW_INTERLEAVED);//access mode set
if (recmod._rc < 0) {
	LOG("%s: INTERLEAVED non available\n", __func__);
	return -1;
}

recmod._rc = snd_pcm_hw_params_set_format(recmod._handle, recmod._params, SND_PCM_FORMAT_S32_LE);//16bit Signed int Little Endian  SND_PCM_FORMAT_S16_LE:_bytes_num=2  SND_PCM_FORMAT_S32_LE:_bytes_num=4
if (recmod._rc < 0) {
	LOG("%s: S32_LE non available\n", __func__);
	return -1;
}

recmod._rc = snd_pcm_hw_params_set_channels(recmod._handle, recmod._params, recmod._channels);//6 _channels
if (recmod._rc < 0) {
	LOG("%s: Channels count non available\n", __func__);
	return -1;
}
	
recmod._rc = snd_pcm_hw_params_set_rate_near(recmod._handle, recmod._params, &recmod._samplerate, &recmod._dir);//16kHz Sample rate
if (recmod._rc < 0) {
	LOG("%s: samplerate: %d count non available\n", __func__, recmod._samplerate);
	return -1;
}

recmod._rc = snd_pcm_hw_params_set_period_size_near(recmod._handle, recmod._params, &recmod._sampleNumPerCh, &recmod._dir);//Period Size 320
if (recmod._rc < 0) {
	LOG("%s: Period Size: %ld count non available\n", __func__, recmod._sampleNumPerCh);
	return -1;
}

recmod._rc = snd_pcm_hw_params(recmod._handle, recmod._params);
if(recmod._rc < 0)
{
	LOG("%s: unable to set hardware parameters: %s\n",  __func__, snd_strerror(recmod._rc));
	return -1;
}

snd_pcm_hw_params_get_channels(recmod._params, &recmod._channels);
snd_pcm_hw_params_get_rate(recmod._params, &recmod._samplerate, &recmod._dir);
snd_pcm_get_params(recmod._handle, &recmod._buffer_size, &recmod._period_size);
snd_pcm_hw_params_get_period_size(recmod._params, &recmod._frames, &recmod._dir);
LOG("_frames: %d===_buffer_size: %d===_period_size:%d===_samplerate:%d===_channels:%d\n", 
				(int)recmod._frames, (int)recmod._buffer_size, (int)recmod._period_size, recmod._samplerate, recmod._channels);

recmod._all_channebuf_size = recmod._frames * recmod._bytes_num * recmod._channels;
LOG("_frames * _bytes_num * _channels = %d\n", recmod._all_channebuf_size);

//we only support 16bit, so the buffer size should be 1/2
*bytes_num = recmod._all_channebuf_size/2;

pcm_int32buf = (int32_t *)malloc(recmod._all_channebuf_size);
if(pcm_int32buf == NULL)
{
    printf("malloc pcm_int32 buf failed\n");
    return -2;
}

recmod._rc = snd_pcm_start(recmod._handle);
if(recmod._rc < 0)
{
    LOG("fail to start a pcm device: %s\n", snd_strerror(recmod._rc));
    return -1;
}

LOG("%s: Record_8mic_Respeaker Init End\n", __func__); 
return 0;

}

int Record_mic_array_deinit()
{
LOG("%s: Record_8mic_Respeaker Free Begin!\n", func);
snd_pcm_drain(recmod._handle);
snd_pcm_close(recmod._handle);
if(pcm_int32buf)
{
free(pcm_int32buf);
pcm_int32buf = NULL;
}

if(recmod.outputfile)
{
	fclose(recmod.outputfile);
}

LOG("%s: Record_8mic_Respeaker Free End!\n", __func__);
return 0;

}

int Record_mic_array_read(void * buffer, int bytes)
{
int16_t * pcm16buf = (int16_t )buffer;
recmod._rc = snd_pcm_readi(recmod._handle, pcm_int32buf, recmod._frames);
if(recmod._rc == -EPIPE)
{
/
EPIPE means overrun */
LOG(“Record_Local_respeaker_data:overrun occurred, %s\n”, snd_strerror(recmod._rc));
snd_pcm_prepare(recmod._handle);
return -1;
}
else if(recmod._rc < 0)
{
LOG(“error from read: %s\n”, snd_strerror(recmod._rc));
snd_pcm_prepare(recmod._handle);
return -2;
}
else if(recmod._rc != (int)recmod._frames)
{
LOG(“short read, read %d _frames\n”, recmod._rc);
snd_pcm_prepare(recmod._handle);
return -3;
}

if( (recmod._rc * recmod._bytes_num * recmod._channels) != bytes*2 )
	LOG("read count number: %d does not equal with bytes \n", recmod._rc);

for (size_t i = 0; i < recmod._sampleNumPerCh*recmod._channels; i++)
{
    pcm16buf[i] = pcm_int32buf[i] >> 16;
}

fwrite(pcm16buf, bytes, 1, recmod.outputfile);

return 0;

}

error info:

FILE: rec.c, LINE: 186: short read, read 13 _frames

ret:-3
FILE: rec.c, LINE: 180: error from read: Input/output error

Here is the play code:

typedef struct snd_pcm_info_stru

{

snd_pcm_t *_play_handle = NULL; //PCI设备句柄

snd_pcm_hw_params_t *_playback_params = NULL; //硬件信息和PCM流配置

snd_pcm_uframes_t _playback_frames = 648;

int _datablock = 2;

int _playback_dir = 0;

int _playback_buf_size = 0;

unsigned int _play_channels = 0;

unsigned int _frequency = 16000;

char * _play_buffer = NULL;

}SND_PCM_INFO_STRU;

int Play_Audio_Data::play_snd_pcm_init()

{

int rec = snd_pcm_open(&playback_info_stru.snd_pcm_stru._play_handle, “plughw:1,0”, SND_PCM_STREAM_PLAYBACK, 0);

if (rec < 0)

{

printf("%s:%d:%s: ERROR [unable to open pcm device: %s]\n", FILE, LINE, func, snd_strerror(rec));

return -1;

}

snd_pcm_hw_params_alloca(&playback_info_stru.snd_pcm_stru._playback_params);

snd_pcm_hw_params_any(playback_info_stru.snd_pcm_stru._play_handle, playback_info_stru.snd_pcm_stru._playback_params);

rec = snd_pcm_hw_params_set_access(playback_info_stru.snd_pcm_stru._play_handle, playback_info_stru.snd_pcm_stru._playback_params, SND_PCM_ACCESS_RW_INTERLEAVED);

if (rec < 0)

{

printf("%s:%d:%s: ERROR [unable to open pcm device: %s]\n", FILE, LINE, func, snd_strerror(rec));

return -1;

}

snd_pcm_hw_params_set_format(playback_info_stru.snd_pcm_stru._play_handle, playback_info_stru.snd_pcm_stru._playback_params, SND_PCM_FORMAT_S16_LE);

snd_pcm_hw_params_set_channels(playback_info_stru.snd_pcm_stru._play_handle, playback_info_stru.snd_pcm_stru._playback_params, 1);

int rc = snd_pcm_hw_params_set_rate_near(playback_info_stru.snd_pcm_stru._play_handle, playback_info_stru.snd_pcm_stru._playback_params, &playback_info_stru.snd_pcm_stru._frequency, &playback_info_stru.snd_pcm_stru._playback_dir);

if (rc < 0)

{

printf("%s:%d:%s: ERROR [set rate failed: %s]\n", FILE, LINE, func, snd_strerror(rc));

return -1;

}

snd_pcm_hw_params_set_period_size_near(playback_info_stru.snd_pcm_stru._play_handle, playback_info_stru.snd_pcm_stru._playback_params, &playback_info_stru.snd_pcm_stru._playback_frames, &playback_info_stru.snd_pcm_stru._playback_dir);

rc = snd_pcm_hw_params(playback_info_stru.snd_pcm_stru._play_handle, playback_info_stru.snd_pcm_stru._playback_params);

if (rc < 0)

{

printf( “%s:%d:%s: ERROR [unable to set hw parameters: %s]\n”, FILE, LINE, func, snd_strerror(rc));

return -1;

}

snd_pcm_hw_params_get_period_size(playback_info_stru.snd_pcm_stru._playback_params, &playback_info_stru.snd_pcm_stru._playback_frames, &playback_info_stru.snd_pcm_stru._playback_dir);

snd_pcm_hw_params_get_channels(playback_info_stru.snd_pcm_stru._playback_params,&playback_info_stru.snd_pcm_stru._play_channels);

snd_pcm_hw_params_get_rate(playback_info_stru.snd_pcm_stru._playback_params, &playback_info_stru.snd_pcm_stru._frequency, &playback_info_stru.snd_pcm_stru._playback_dir);

playback_info_stru.snd_pcm_stru._playback_buf_size = playback_info_stru.snd_pcm_stru._playback_frames * playback_info_stru.snd_pcm_stru._datablock * playback_info_stru.snd_pcm_stru._play_channels;

playback_info_stru.snd_pcm_stru._play_buffer =(char*)malloc(playback_info_stru.snd_pcm_stru._playback_buf_size * sizeof(char) ) ;

if(NULL == playback_info_stru.snd_pcm_stru._play_buffer)

{

printf("%s:%d:%s: ERROR [malloc _play_buffer error!]\n", FILE, LINE, func );

return -1;

}

//bzero(playback_info_stru.snd_pcm_stru._play_buffer, playback_info_stru.snd_pcm_stru._playback_buf_size);

memset(playback_info_stru.snd_pcm_stru._play_buffer,0,playback_info_stru.snd_pcm_stru._playback_buf_size * sizeof(char));

printf("%s:%d:%s: play_snd_pcm_init success!\n", FILE, LINE, func);

return 0;

}

void Play_Audio_Data::play_snd_pcm_deinit()

{

//snd_pcm_hw_params_free(playback_info_stru.snd_pcm_stru._playback_params);

snd_pcm_close(playback_info_stru.snd_pcm_stru._play_handle);

if(playback_info_stru.snd_pcm_stru._play_buffer != NULL)

{

free(playback_info_stru.snd_pcm_stru._play_buffer);

playback_info_stru.snd_pcm_stru._play_buffer = NULL;

}

}

int Play_Audio_Data::play_awake_pcm(FILE * voice_file)

{

DEBUG(“INTO PLAY AWAKE PCM FILE!”,func);

snd_pcm_prepare(playback_info_stru.snd_pcm_stru._play_handle);

fseek(voice_file,0,SEEK_SET);

while(1)

{

int _ret = 0,read_len = 0;

bzero(playback_info_stru.snd_pcm_stru._play_buffer, playback_info_stru.snd_pcm_stru._playback_buf_size);

read_len = fread(playback_info_stru.snd_pcm_stru._play_buffer, 1, playback_info_stru.snd_pcm_stru._playback_buf_size, voice_file);

//if( read_len != playback_info_stru.snd_pcm_stru._playback_buf_size )

//{

// playback_info_stru.snd_pcm_stru._playback_frames = read_len/(playback_info_stru.snd_pcm_stru._datablock * playback_info_stru.snd_pcm_stru._play_channels);

//}

_ret = snd_pcm_writei(playback_info_stru.snd_pcm_stru._play_handle, playback_info_stru.snd_pcm_stru._play_buffer, playback_info_stru.snd_pcm_stru._playback_frames);

if(_ret == -EPIPE)

{

printf("%s:%d:%s: play_pcm overrun occurred\n", FILE, LINE, func);

snd_pcm_prepare(playback_info_stru.snd_pcm_stru._play_handle);

}

else if(_ret < 0)

{

printf("%s:%d:%s: play_pcm error from read: %s\n",FILE, LINE, func , snd_strerror(_ret));

snd_pcm_prepare(playback_info_stru.snd_pcm_stru._play_handle);

}

else if(_ret != (int)playback_info_stru.snd_pcm_stru._playback_frames)

{

printf("%s:%d:%s: play_pcm short read, read %d _playback_frames\n", FILE, LINE, func, _ret);

snd_pcm_prepare(playback_info_stru.snd_pcm_stru._play_handle);

}

if( feof(voice_file) )

{

//playback_info_stru.snd_pcm_stru._playback_frames = playback_info_stru.snd_pcm_stru._playback_buf_size/(playback_info_stru.snd_pcm_stru._datablock * playback_info_stru.snd_pcm_stru._play_channels);

break;

}

if(playthreadmod.play_thread_stop)

{

//playback_info_stru.snd_pcm_stru._playback_frames = playback_info_stru.snd_pcm_stru._playback_buf_size/(playback_info_stru.snd_pcm_stru._datablock * playback_info_stru.snd_pcm_stru._play_channels);

break;

}

}

fseek(voice_file,0,SEEK_SET);

DEBUG("%s:PLAY AWAKE PCM FILE END!",func);

return 0;

}

I want to know why did the program run for a while and the recording went wrong.
I hope to get help!

                                                               Thanks!