NikTalk
Hi!大家好,我是Nik。一名在人工智能+物联网行业混迹多年的AIOT架构工程师兼产品经理。欢迎您来到我的博客!这里记录了我的AIOT职业生涯,从最开始的一名普通嵌入式软件工程师->到嵌入式系统工程师->再到AIOT架构师兼产品经理一路上的所学所感所得。希望这些知识,经验,技术以及感悟对后来的你,在技术学习以及职业发展的道路上有所帮助。记得关注我,我将不定期分享一些AIOT相关的技术和行业信息。唯一微信号:aiotnik

Mic麦克风和spk喇叭-08

AIOTNIK-ONE开发板,为了让开发者可以开发录音和播放等音频媒体功能。配置了一个AMIC麦克风和一个SPK扩音器接口,可以接一个模拟麦克风和一个扩音器,实物图如下。

录音和播放测试

这里给出一个录音和播放录音的功能测试用例,测试用例代码所在SDK路径/sdk/samples/libimp-samples/sample-ai-ref.c 以下是具体代码。

/*
 * sample-ai-ref.c
 *
 */
 
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/prctl.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <stdint.h>
#include <errno.h>
#include <pthread.h>
#include <semaphore.h>
#include <fcntl.h>
#include <sys/time.h>
 
#include <imp/imp_audio.h>
#include <imp/imp_log.h>
 
#define TAG "Sample-Ai-Ref"
 
#define AEC_SAMPLE_RATE 16000
#define AEC_SAMPLE_TIME 20
 
#define AUDIO_BUF_SIZE (AEC_SAMPLE_RATE * sizeof(short) * AEC_SAMPLE_TIME / 1000)
#define AUDIO_RECORD_NUM 400
 
#define AUDIO_RECORD_FILE "./test_aec_record.pcm"
 
//1、音频录制,录制400帧降噪后的pcm格式音频,并保存到AUDIO_RECORD_FILE文件
static void * IMP_Audio_Record_AEC_Thread(void *argv)
{
int ret = -1;
int record_num = 0;
 
if(argv == NULL) {
IMP_LOG_ERR(TAG, "Please input the record file name.\n");
return NULL;
}
 
FILE *record_file = fopen(argv, "wb");
if(record_file == NULL) {
IMP_LOG_ERR(TAG, "fopen %s failed\n", AUDIO_RECORD_FILE);
return NULL;
}
 
/* step 1. set public attribute of AI device. */
int devID = 1;
IMPAudioIOAttr attr;
attr.samplerate = AUDIO_SAMPLE_RATE_16000;
attr.bitwidth = AUDIO_BIT_WIDTH_16;
attr.soundmode = AUDIO_SOUND_MODE_MONO;
attr.frmNum = 40;
attr.numPerFrm = 640;
attr.chnCnt = 1;
ret = IMP_AI_SetPubAttr(devID, &attr);
if(ret != 0) {
IMP_LOG_ERR(TAG, "set ai %d attr err: %d\n", devID, ret);
return NULL;
}
 
memset(&attr, 0x0, sizeof(attr));
ret = IMP_AI_GetPubAttr(devID, &attr);
if(ret != 0) {
IMP_LOG_ERR(TAG, "get ai %d attr err: %d\n", devID, ret);
return NULL;
}
 
IMP_LOG_INFO(TAG, "Audio In GetPubAttr samplerate : %d\n", attr.samplerate);
IMP_LOG_INFO(TAG, "Audio In GetPubAttr   bitwidth : %d\n", attr.bitwidth);
IMP_LOG_INFO(TAG, "Audio In GetPubAttr  soundmode : %d\n", attr.soundmode);
IMP_LOG_INFO(TAG, "Audio In GetPubAttr     frmNum : %d\n", attr.frmNum);
IMP_LOG_INFO(TAG, "Audio In GetPubAttr  numPerFrm : %d\n", attr.numPerFrm);
IMP_LOG_INFO(TAG, "Audio In GetPubAttr     chnCnt : %d\n", attr.chnCnt);
 
/* step 2. enable AI device. */
ret = IMP_AI_Enable(devID);
if(ret != 0) {
IMP_LOG_ERR(TAG, "enable ai %d err\n", devID);
return NULL;
}
 
/* step 3. set audio channel attribute of AI device. */
int chnID = 0;
IMPAudioIChnParam chnParam;
chnParam.usrFrmDepth = 40;
chnParam.aecChn = AUDIO_AEC_CHANNEL_FIRST_LEFT;
ret = IMP_AI_SetChnParam(devID, chnID, &chnParam);
if(ret != 0) {
IMP_LOG_ERR(TAG, "set ai %d channel %d attr err: %d\n", devID, chnID, ret);
return NULL;
}
 
memset(&chnParam, 0x0, sizeof(chnParam));
ret = IMP_AI_GetChnParam(devID, chnID, &chnParam);
if(ret != 0) {
IMP_LOG_ERR(TAG, "get ai %d channel %d attr err: %d\n", devID, chnID, ret);
return NULL;
}
 
IMP_LOG_INFO(TAG, "Audio In GetChnParam usrFrmDepth : %d\n", chnParam.usrFrmDepth);
 
/* step 4. enable AI channel. */
ret = IMP_AI_EnableChn(devID, chnID);
if(ret != 0) {
IMP_LOG_ERR(TAG, "Audio Record enable channel failed\n");
return NULL;
}
 
ret = IMP_AI_EnableAec(devID, chnID, 0, 0);
if(ret != 0) {
IMP_LOG_ERR(TAG, "Audio Record enable channel failed\n");
return NULL;
}
 
/* step 5. Set audio channel volume. */
int chnVol = 60;
ret = IMP_AI_SetVol(devID, chnID, chnVol);
if(ret != 0) {
IMP_LOG_ERR(TAG, "Audio Record set volume failed\n");
return NULL;
}
 
ret = IMP_AI_GetVol(devID, chnID, &chnVol);
if(ret != 0) {
IMP_LOG_ERR(TAG, "Audio Record get volume failed\n");
return NULL;
}
 
IMP_LOG_INFO(TAG, "Audio In GetVol    vol : %d\n", chnVol);
 
int aigain = 31;
ret = IMP_AI_SetGain(devID, chnID, aigain);
if(ret != 0) {
IMP_LOG_ERR(TAG, "Audio Record Set Gain failed\n");
return NULL;
}
 
ret = IMP_AI_GetGain(devID, chnID, &aigain);
if(ret != 0) {
IMP_LOG_ERR(TAG, "Audio Record Get Gain failed\n");
return NULL;
}
IMP_LOG_INFO(TAG, "Audio In GetGain    gain : %d\n", aigain);
 
while(1) {
/* step 6. get audio record frame. */
 
ret = IMP_AI_PollingFrame(devID, chnID, 1000);
if (ret != 0 ) {
IMP_LOG_ERR(TAG, "Audio Polling Frame Data error\n");
}
IMPAudioFrame frm;
ret = IMP_AI_GetFrame(devID, chnID, &frm, BLOCK);
if(ret != 0) {
IMP_LOG_ERR(TAG, "Audio Get Frame Data error\n");
return NULL;
}
 
/* step 7. Save the recording data to a file. */
fwrite(frm.virAddr, 1, frm.len, record_file);
 
/* step 8. release the audio record frame. */
ret = IMP_AI_ReleaseFrame(devID, chnID, &frm);
if(ret != 0) {
IMP_LOG_ERR(TAG, "Audio release frame data error\n");
return NULL;
}
 
if(++record_num >= AUDIO_RECORD_NUM)
break;
}
 
ret = IMP_AI_DisableAec(devID, chnID);
if(ret != 0) {
IMP_LOG_ERR(TAG, "IMP_AI_DisableAecRefFrame\n");
return NULL;
}
sleep(3);
ret = IMP_AI_DisableChn(devID, chnID);
if(ret != 0) {
IMP_LOG_ERR(TAG, "Audio channel disable error\n");
return NULL;
}
 
/* step 9. disable the audio devices. */
ret = IMP_AI_Disable(devID);
if(ret != 0) {
IMP_LOG_ERR(TAG, "Audio device disable error\n");
return NULL;
}
 
fclose(record_file);
pthread_exit(0);
}
 
//2、播放刚才录制的AUDIO_RECORD_FILE音频文件
static void *IMP_Audio_Play_Thread(void *argv)
{
unsigned char *buf = NULL;
int size = 0;
int ret = -1;
 
if(argv == NULL) {
IMP_LOG_ERR(TAG, "[ERROR] %s: Please input the play file name.\n", __func__);
return NULL;
}
 
buf = (unsigned char *)malloc(AUDIO_BUF_SIZE);
if(buf == NULL) {
IMP_LOG_ERR(TAG, "[ERROR] %s: malloc audio buf error\n", __func__);
return NULL;
}
 
FILE *play_file = fopen(argv, "rb");
if(play_file == NULL) {
IMP_LOG_ERR(TAG, "[ERROR] %s: fopen %s failed\n", __func__, argv);
return NULL;
}
 
/* Step 1: set public attribute of AO device. */
int devID = 0;
IMPAudioIOAttr attr;
attr.samplerate = AUDIO_SAMPLE_RATE_16000;
attr.bitwidth = AUDIO_BIT_WIDTH_16;
attr.soundmode = AUDIO_SOUND_MODE_MONO;
attr.frmNum = 20;
attr.numPerFrm = 640;
attr.chnCnt = 1;
ret = IMP_AO_SetPubAttr(devID, &attr);
if(ret != 0) {
IMP_LOG_ERR(TAG, "set ao %d attr err: %d\n", devID, ret);
return NULL;
}
 
memset(&attr, 0x0, sizeof(attr));
ret = IMP_AO_GetPubAttr(devID, &attr);
if(ret != 0) {
IMP_LOG_ERR(TAG, "get ao %d attr err: %d\n", devID, ret);
return NULL;
}
 
IMP_LOG_INFO(TAG, "Audio Out GetPubAttr samplerate:%d\n", attr.samplerate);
IMP_LOG_INFO(TAG, "Audio Out GetPubAttr   bitwidth:%d\n", attr.bitwidth);
IMP_LOG_INFO(TAG, "Audio Out GetPubAttr  soundmode:%d\n", attr.soundmode);
IMP_LOG_INFO(TAG, "Audio Out GetPubAttr     frmNum:%d\n", attr.frmNum);
IMP_LOG_INFO(TAG, "Audio Out GetPubAttr  numPerFrm:%d\n", attr.numPerFrm);
IMP_LOG_INFO(TAG, "Audio Out GetPubAttr     chnCnt:%d\n", attr.chnCnt);
 
/* Step 2: enable AO device. */
ret = IMP_AO_Enable(devID);
if(ret != 0) {
IMP_LOG_ERR(TAG, "enable ao %d err\n", devID);
return NULL;
}
 
/* Step 3: enable AI channel. */
int chnID = 0;
ret = IMP_AO_EnableChn(devID, chnID);
if(ret != 0) {
IMP_LOG_ERR(TAG, "Audio play enable channel failed\n");
return NULL;
}
 
/* Step 4: Set audio channel volume. */
int chnVol = 60;
ret = IMP_AO_SetVol(devID, chnID, chnVol);
if(ret != 0) {
IMP_LOG_ERR(TAG, "Audio Play set volume failed\n");
return NULL;
}
 
ret = IMP_AO_GetVol(devID, chnID, &chnVol);
if(ret != 0) {
IMP_LOG_ERR(TAG, "Audio Play get volume failed\n");
return NULL;
}
IMP_LOG_INFO(TAG, "Audio Out GetVol    vol:%d\n", chnVol);
 
int aogain = 31;
ret = IMP_AO_SetGain(devID, chnID, aogain);
if(ret != 0) {
IMP_LOG_ERR(TAG, "Audio Record Set Gain failed\n");
return NULL;
}
 
ret = IMP_AO_GetGain(devID, chnID, &aogain);
if(ret != 0) {
IMP_LOG_ERR(TAG, "Audio Record Get Gain failed\n");
return NULL;
}
IMP_LOG_INFO(TAG, "Audio Out GetGain    gain : %d\n", aogain);
/* Step 5: enable AO algorithm. */
ret = IMP_AO_EnableAlgo(devID, chnID);
if (ret != 0) {
IMP_LOG_ERR(TAG, "IMP_AO_EnableAlgo failed\n");
return NULL;
}
 
while(1) {
size = fread(buf, 1, AUDIO_BUF_SIZE, play_file);
if(size < AUDIO_BUF_SIZE)
break;
 
/* Step 6: send frame data. */
IMPAudioFrame frm;
frm.virAddr = (uint32_t *)buf;
frm.len = size;
ret = IMP_AO_SendFrame(devID, chnID, &frm, BLOCK);
if(ret != 0) {
IMP_LOG_ERR(TAG, "send Frame Data error\n");
return NULL;
}
 
IMPAudioOChnState play_status;
ret = IMP_AO_QueryChnStat(devID, chnID, &play_status);
if(ret != 0) {
IMP_LOG_ERR(TAG, "IMP_AO_QueryChnStat error\n");
return NULL;
}
 
IMP_LOG_INFO(TAG, "Play: TotalNum %d, FreeNum %d, BusyNum %d\n",
play_status.chnTotalNum, play_status.chnFreeNum, play_status.chnBusyNum);
}
ret = IMP_AO_FlushChnBuf(devID, chnID);
if (ret != 0) {
IMP_LOG_ERR(TAG, "IMP_AO_FlushChnBuf error\n");
return NULL;
}
/* Step 7: disable AO algorithm. */
ret = IMP_AO_DisableAlgo(devID, chnID);
if (ret != 0) {
IMP_LOG_ERR(TAG, "IMP_AO_DisableAlgo error\n");
return NULL;
}
/* Step 8: disable the audio channel. */
ret = IMP_AO_DisableChn(devID, chnID);
if(ret != 0) {
IMP_LOG_ERR(TAG, "Audio channel disable error\n");
return NULL;
}
 
/* Step 9: disable the audio devices. */
ret = IMP_AO_Disable(devID);
if(ret != 0) {
IMP_LOG_ERR(TAG, "Audio device disable error\n");
return NULL;
}
 
fclose(play_file);
free(buf);
pthread_exit(0);
}
 
int  main(int argc, char *argv[])
{
int ret;
 
pthread_t tid_play, tid_ref;
 
/*set aec profile path */
ret = IMP_AI_Set_WebrtcProfileIni_Path("/system/etc");
if(ret != 0) {
IMP_LOG_ERR(TAG, "Set AEC Path failed\n");
return -1;
} else {
IMP_LOG_INFO(TAG, "Set AEC Path Ok\n");
}
 
printf("[INFO] Start audio record ref test.\n");
printf("[INFO] Can create the %s file.\n", AUDIO_RECORD_FILE);
printf("[INFO] Please input any key to continue.\n");
//创建音频录制线程IMP_Audio_Record_AEC_Thread
ret = pthread_create(&tid_ref, NULL, IMP_Audio_Record_AEC_Thread, AUDIO_RECORD_FILE);
if(ret != 0) {
IMP_LOG_ERR(TAG, "[ERROR] %s: pthread_create Audio Record failed\n", __func__);
return -1;
}
pthread_join(tid_ref, NULL);
 
//创建音频播放线程IMP_Audio_Play_Thread
printf("[INFO]  Start audio play test.\n");
printf("[INFO]  Play the %s file.\n", AUDIO_RECORD_FILE);
printf("[INFO]  Please input any key to continue.\n");
ret = pthread_create(&tid_play, NULL, IMP_Audio_Play_Thread, AUDIO_RECORD_FILE);
if(ret != 0) {
IMP_LOG_ERR(TAG, "[ERROR] %s: pthread_create Audio Play failed\n", __func__);
return -1;
}
 
pthread_join(tid_play, NULL);
pthread_join(tid_ref, NULL);
 
return 0;
}

将以上音频录制和播放测试用例编译后拷贝到开发板上运行之后,对麦克讲话即可实时录制你的声音,然后通过扩音器将录制的声音播放出来。