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