FaceAccess/Record/rkmedia_audio_test.c

412 lines
12 KiB
C
Raw Normal View History

2024-06-18 14:27:48 +08:00
// Copyright 2020 Fuzhou Rockchip Electronics Co., Ltd. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <assert.h>
#include <fcntl.h>
#include <signal.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <rkmedia_api.h>
#define MP3_NB_SAMPLES 1024
#define MP2_NB_SAMPLES 1152
//#define ALSA_PATH "default:CARD=rockchiprk809co" // get from "arecord -L"
#define ALSA_PATH "hw:0,0" // get from "arecord -L"
#define VQEFILE "/sdcard/RKAP_3A_Para.bin"
static bool quit = false;
static void sigterm_handler(int sig) {
fprintf(stderr, "signal %d\n", sig);
quit = true;
}
FILE *fp = NULL;
static RK_U32 g_enWorkSampleRate = 16000;
static RK_U32 g_s32VqeFrameSample = 256; // 20ms;
static RK_U32 g_s32AiLayout = AI_LAYOUT_MIC_REF;
static void audio_packet_cb(MEDIA_BUFFER mb) {
printf("Get Audio Encoded packet:ptr:%p, fd:%d, size:%zu, mode:%d\n",
RK_MPI_MB_GetPtr(mb), RK_MPI_MB_GetFD(mb), RK_MPI_MB_GetSize(mb),
RK_MPI_MB_GetModeID(mb));
fwrite(RK_MPI_MB_GetPtr(mb), 1, RK_MPI_MB_GetSize(mb), fp);
RK_MPI_MB_ReleaseBuffer(mb);
}
static RK_VOID AI_AO() {
RK_MPI_SYS_Init();
MPP_CHN_S mpp_chn_ai, mpp_chn_ao;
mpp_chn_ai.enModId = RK_ID_AI;
mpp_chn_ai.s32ChnId = 0;
mpp_chn_ao.enModId = RK_ID_AO;
mpp_chn_ao.s32ChnId = 0;
AI_CHN_ATTR_S ai_attr;
ai_attr.pcAudioNode = ALSA_PATH;
ai_attr.enSampleFormat = RK_SAMPLE_FMT_S16;
ai_attr.u32NbSamples = 1152;
ai_attr.u32SampleRate = g_enWorkSampleRate;
ai_attr.u32Channels = 1;
ai_attr.enAiLayout = g_s32AiLayout; // chanel layout: [ref:mic]; remove
// ref, output mic mono
AO_CHN_ATTR_S ao_attr;
ao_attr.pcAudioNode = ALSA_PATH;
ao_attr.enSampleFormat = RK_SAMPLE_FMT_S16;
ao_attr.u32NbSamples = 1152;
ao_attr.u32SampleRate = g_enWorkSampleRate;
ao_attr.u32Channels = 1;
// 1. create AI
RK_MPI_AI_SetChnAttr(mpp_chn_ai.s32ChnId, &ai_attr);
RK_MPI_AI_EnableChn(mpp_chn_ai.s32ChnId);
RK_MPI_AI_SetVolume(mpp_chn_ai.s32ChnId, 100);
// 2. create AO
RK_MPI_AO_SetChnAttr(mpp_chn_ao.s32ChnId, &ao_attr);
RK_MPI_AO_EnableChn(mpp_chn_ao.s32ChnId);
RK_MPI_AO_SetVolume(mpp_chn_ao.s32ChnId, 100);
// 3. bind AI-AO
RK_MPI_SYS_Bind(&mpp_chn_ai, &mpp_chn_ao);
printf("%s initial finish\n", __func__);
signal(SIGINT, sigterm_handler);
while (!quit) {
usleep(500000);
}
printf("%s exit!\n", __func__);
RK_MPI_SYS_UnBind(&mpp_chn_ai, &mpp_chn_ao);
RK_MPI_AI_DisableChn(mpp_chn_ai.s32ChnId);
RK_MPI_AO_DisableChn(mpp_chn_ao.s32ChnId);
}
static RK_VOID AI_AENC_FILE(char *file_path) {
fp = fopen(file_path, "w+");
RK_MPI_SYS_Init();
MPP_CHN_S mpp_chn_ai, mpp_chn_aenc;
mpp_chn_ai.enModId = RK_ID_AI;
mpp_chn_ai.s32ChnId = 0;
mpp_chn_aenc.enModId = RK_ID_AENC;
mpp_chn_aenc.s32ChnId = 0;
AI_CHN_ATTR_S ai_attr;
ai_attr.pcAudioNode = ALSA_PATH;
ai_attr.enSampleFormat = RK_SAMPLE_FMT_S16;
ai_attr.u32NbSamples = MP3_NB_SAMPLES;
ai_attr.u32SampleRate = g_enWorkSampleRate;
ai_attr.u32Channels = 1;
ai_attr.enAiLayout = g_s32AiLayout; // chanel layout: [ref:mic]; remove
// ref, output mic mono
AENC_CHN_ATTR_S aenc_attr;
aenc_attr.enCodecType = RK_CODEC_TYPE_MP3;
aenc_attr.u32Bitrate = 64000;
aenc_attr.u32Quality = 1;
aenc_attr.stAencMP3.u32Channels = 1;
aenc_attr.stAencMP3.u32SampleRate = g_enWorkSampleRate;
// 1. create AI
RK_MPI_AI_SetChnAttr(mpp_chn_ai.s32ChnId, &ai_attr);
RK_MPI_AI_EnableChn(mpp_chn_ai.s32ChnId);
// 2. create AENC
RK_MPI_AENC_CreateChn(mpp_chn_aenc.s32ChnId, &aenc_attr);
RK_U32 ret = RK_MPI_SYS_RegisterOutCb(&mpp_chn_aenc, audio_packet_cb);
printf("ret = %d.\n", ret);
// 3. bind AI-AENC
RK_MPI_SYS_Bind(&mpp_chn_ai, &mpp_chn_aenc);
printf("%s initial finish\n", __func__);
signal(SIGINT, sigterm_handler);
while (!quit) {
usleep(500000);
}
RK_MPI_SYS_UnBind(&mpp_chn_ai, &mpp_chn_aenc);
RK_MPI_AI_DisableChn(mpp_chn_ai.s32ChnId);
RK_MPI_AENC_DestroyChn(mpp_chn_aenc.s32ChnId);
fclose(fp);
}
static RK_VOID FILE_ADEC_AO(char *file_path) {
CODEC_TYPE_E codec_type = RK_CODEC_TYPE_MP3;
RK_U32 channels = 2;
RK_U32 sample_rate = g_enWorkSampleRate;
ADEC_CHN_ATTR_S stAdecAttr;
AO_CHN_ATTR_S stAoAttr;
stAdecAttr.enCodecType = codec_type;
MPP_CHN_S mpp_chn_ao, mpp_chn_adec;
mpp_chn_ao.enModId = RK_ID_AO;
mpp_chn_ao.s32ChnId = 0;
mpp_chn_adec.enModId = RK_ID_ADEC;
mpp_chn_adec.s32ChnId = 0;
stAoAttr.u32Channels = channels;
stAoAttr.u32SampleRate = sample_rate;
stAoAttr.u32NbSamples = 1024;
stAoAttr.pcAudioNode = ALSA_PATH;
switch (codec_type) {
case RK_CODEC_TYPE_MP3:
stAoAttr.enSampleFormat = RK_SAMPLE_FMT_S16;
stAoAttr.u32NbSamples = 1024;
break;
case RK_CODEC_TYPE_MP2:
stAoAttr.enSampleFormat = RK_SAMPLE_FMT_S16;
stAoAttr.u32NbSamples = 1152;
break;
case RK_CODEC_TYPE_G711A:
stAdecAttr.stAdecG711A.u32Channels = channels;
stAdecAttr.stAdecG711A.u32SampleRate = sample_rate;
stAoAttr.enSampleFormat = RK_SAMPLE_FMT_S16;
break;
case RK_CODEC_TYPE_G711U:
stAdecAttr.stAdecG711U.u32Channels = channels;
stAdecAttr.stAdecG711U.u32SampleRate = sample_rate;
stAoAttr.enSampleFormat = RK_SAMPLE_FMT_S16;
break;
case RK_CODEC_TYPE_G726:
stAoAttr.enSampleFormat = RK_SAMPLE_FMT_S16;
break;
default:
printf("audio codec type error.\n");
return;
}
// init MPI
RK_MPI_SYS_Init();
// create ADEC
RK_MPI_ADEC_CreateChn(mpp_chn_adec.s32ChnId, &stAdecAttr);
// create AO
RK_MPI_AO_SetChnAttr(mpp_chn_ao.s32ChnId, &stAoAttr);
RK_MPI_AO_EnableChn(mpp_chn_ao.s32ChnId);
RK_MPI_SYS_Bind(&mpp_chn_adec, &mpp_chn_ao);
RK_S32 buffer_size = 20480;
FILE *read_file = fopen(file_path, "r");
if (!read_file) {
printf("ERROR: open %s failed!\n", file_path);
exit(0);
}
quit = true;
while (quit) {
MEDIA_BUFFER mb = RK_MPI_MB_CreateAudioBuffer(buffer_size, RK_FALSE);
if (!mb) {
printf("ERROR: no space left!\n");
break;
}
RK_S32 s32ReadSize = fread(RK_MPI_MB_GetPtr(mb), 1, buffer_size, read_file);
RK_MPI_MB_SetSize(mb, s32ReadSize);
RK_MPI_SYS_SendMediaBuffer(RK_ID_ADEC, mpp_chn_adec.s32ChnId, mb);
RK_MPI_MB_ReleaseBuffer(mb);
if (s32ReadSize != buffer_size) {
printf("Get end of file!\n");
break;
}
}
sleep(2);
{
// flush decoder
printf("start flush decoder.\n");
MEDIA_BUFFER mb = RK_MPI_MB_CreateAudioBuffer(buffer_size, RK_FALSE);
RK_MPI_MB_SetSize(mb, 0);
RK_MPI_SYS_SendMediaBuffer(RK_ID_ADEC, mpp_chn_adec.s32ChnId, mb);
RK_MPI_MB_ReleaseBuffer(mb);
printf("end flush decoder.\n");
}
sleep(10);
}
/* 0: close, 1: talk, 2: record */
static RK_U32 u32AiVqeType = 1;
/* 0: close, 1: open */
static RK_U32 u32AoVqeType = 1;
/******************************************************************************
* function : Ai ->VqeProcess-> Ao
******************************************************************************/
RK_S32 AI_VqeProcess_AO(RK_VOID) {
AI_TALKVQE_CONFIG_S stAiVqeTalkAttr;
AI_RECORDVQE_CONFIG_S stAiVqeRecordAttr;
AO_VQE_CONFIG_S stAoVqeAttr;
MPP_CHN_S mpp_chn_ai, mpp_chn_ao;
if (1 == u32AiVqeType) {
memset(&stAiVqeTalkAttr, 0, sizeof(AI_TALKVQE_CONFIG_S));
stAiVqeTalkAttr.s32WorkSampleRate = g_enWorkSampleRate;
stAiVqeTalkAttr.s32FrameSample = g_s32VqeFrameSample;
strcpy(stAiVqeTalkAttr.aParamFilePath, VQEFILE);
stAiVqeTalkAttr.u32OpenMask =
AI_TALKVQE_MASK_AEC | AI_TALKVQE_MASK_ANR | AI_TALKVQE_MASK_AGC;
} else if (2 == u32AiVqeType) {
memset(&stAiVqeRecordAttr, 0, sizeof(AI_RECORDVQE_CONFIG_S));
stAiVqeRecordAttr.s32WorkSampleRate = g_enWorkSampleRate;
stAiVqeRecordAttr.s32FrameSample = g_s32VqeFrameSample;
stAiVqeRecordAttr.stAnrConfig.fPostAddGain = 0;
stAiVqeRecordAttr.stAnrConfig.fGmin = -30;
stAiVqeRecordAttr.stAnrConfig.fNoiseFactor = 0.98;
stAiVqeRecordAttr.u32OpenMask = AI_RECORDVQE_MASK_ANR;
}
if (1 == u32AoVqeType) {
memset(&stAoVqeAttr, 0, sizeof(AO_VQE_CONFIG_S));
stAoVqeAttr.s32WorkSampleRate = g_enWorkSampleRate;
stAoVqeAttr.s32FrameSample = g_s32VqeFrameSample;
strcpy(stAoVqeAttr.aParamFilePath, VQEFILE);
stAoVqeAttr.u32OpenMask = AO_VQE_MASK_ANR | AO_VQE_MASK_AGC;
}
RK_MPI_SYS_Init();
mpp_chn_ai.enModId = RK_ID_AI;
mpp_chn_ai.s32ChnId = 0;
mpp_chn_ao.enModId = RK_ID_AO;
mpp_chn_ao.s32ChnId = 0;
AI_CHN_ATTR_S ai_attr;
ai_attr.pcAudioNode = ALSA_PATH;
ai_attr.enSampleFormat = RK_SAMPLE_FMT_S16;
ai_attr.u32NbSamples = 1024;
ai_attr.u32SampleRate = g_enWorkSampleRate;
ai_attr.u32Channels = 2;
ai_attr.enAiLayout = g_s32AiLayout; // remove ref channel, and output mic mono
AO_CHN_ATTR_S ao_attr;
ao_attr.pcAudioNode = ALSA_PATH;
ao_attr.enSampleFormat = RK_SAMPLE_FMT_S16;
ao_attr.u32NbSamples = 1024;
ao_attr.u32SampleRate = g_enWorkSampleRate;
ao_attr.u32Channels = 2;
// 1. create AI
RK_MPI_AI_SetChnAttr(mpp_chn_ai.s32ChnId, &ai_attr);
RK_MPI_AI_EnableChn(mpp_chn_ai.s32ChnId);
//RK_MPI_AI_SetVolume(mpp_chn_ai.s32ChnId, 100);
if (1 == u32AiVqeType) {
RK_MPI_AI_SetTalkVqeAttr(mpp_chn_ai.s32ChnId, &stAiVqeTalkAttr);
RK_MPI_AI_EnableVqe(mpp_chn_ai.s32ChnId);
} else if (2 == u32AiVqeType) {
RK_MPI_AI_SetRecordVqeAttr(mpp_chn_ai.s32ChnId, &stAiVqeRecordAttr);
RK_MPI_AI_EnableVqe(mpp_chn_ai.s32ChnId);
}
// 2. create AO
RK_MPI_AO_SetChnAttr(mpp_chn_ao.s32ChnId, &ao_attr);
RK_MPI_AO_EnableChn(mpp_chn_ao.s32ChnId);
//RK_MPI_AO_SetVolume(mpp_chn_ao.s32ChnId, 100);
if (1 == u32AoVqeType) {
RK_MPI_AO_SetVqeAttr(mpp_chn_ao.s32ChnId, &stAoVqeAttr);
RK_MPI_AO_EnableVqe(mpp_chn_ao.s32ChnId);
}
// 3. bind AI-AO
RK_MPI_SYS_Bind(&mpp_chn_ai, &mpp_chn_ao);
printf("%s initial finish\n", __func__);
signal(SIGINT, sigterm_handler);
while (!quit) {
usleep(500000);
}
printf("%s exit!\n", __func__);
RK_MPI_SYS_UnBind(&mpp_chn_ai, &mpp_chn_ao);
RK_MPI_AI_DisableChn(mpp_chn_ai.s32ChnId);
RK_MPI_AO_DisableChn(mpp_chn_ao.s32ChnId);
return RK_SUCCESS;
}
static RK_VOID RKMEDIA_AUDIO_Usage() {
printf("\n\n/Usage:./rkmdia_audio <index> <sampleRate> [filePath]/ "
"[nbsamples] [ailayout]\n");
printf("\tindex and its function list below\n");
printf("\t0: start AI to AO loop\n");
printf("\t1: send audio frame to AENC channel from AI, save them\n");
printf("\t2: read audio stream from file, decode and send AO\n");
printf("\t3: start AI(VQE process), then send to AO\n");
// printf("\t4: start AI to Extern Resampler\n");
printf("\n");
printf("\tsampleRate list:\n");
printf("\t0 16000 22050 24000 32000 44100 48000\n");
printf("\n");
printf("\tfilePath represents the path of audio file to be decoded, only for "
"sample 2.\n");
printf("\tdefault filePath: /userdata/out.mp2\n");
printf("\n");
printf("\tnbsamples, for example: 160 is 10ms at 16kHz\n");
printf("\n");
printf("\tailayout:\n");
printf("\t0: AI_LAYOUT_NORMAL\n");
printf("\t1: AI_LAYOUT_MIC_REF\n");
printf("\t2: AI_LAYOUT_REF_MIC\n");
printf("\t3: AI_LAYOUT_2MIC_REF_NONE\n");
printf("\t4: AI_LAYOUT_2MIC_NONE_REF\n");
printf("\t5: AI_LAYOUT_2MIC_2REF\n");
printf("\t6: AI_LAYOUT_BUTT\n");
printf("\n");
printf("\texample: ./rkmdia_audio 0 48000 480 1 /tmp/out_aiao.mp2\n");
}
int main(int argc, char *argv[]) {
RK_U32 u32Index;
RK_CHAR *pFilePath = RK_NULL;
if (!(argc >= 3 && argc <= 6)) {
RKMEDIA_AUDIO_Usage();
return -1;
}
if (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "-?") == 0) {
RKMEDIA_AUDIO_Usage();
return -1;
}
u32Index = atoi(argv[1]);
g_enWorkSampleRate = atoi(argv[2]);
switch (argc) {
case 6:
pFilePath = argv[5];
g_s32AiLayout = atoi(argv[4]);
g_s32VqeFrameSample = atoi(argv[3]);
break;
case 5:
g_s32AiLayout = atoi(argv[4]);
g_s32VqeFrameSample = atoi(argv[3]);
break;
case 4:
g_s32VqeFrameSample = atoi(argv[3]);
break;
default:
pFilePath = (char *)"/tmp/out.mp2";
break;
}
switch (u32Index) {
case 0:
AI_AO();
break;
case 1:
AI_AENC_FILE(pFilePath);
break;
case 2:
FILE_ADEC_AO(pFilePath);
break;
case 3:
AI_VqeProcess_AO();
default:
break;
}
return 0;
}