linuxOS_AP06/app/lvgl_demo/rk_demo/rockit/audio_out.c
2025-06-03 12:28:32 +08:00

315 lines
7.1 KiB
C

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/poll.h>
#include <unistd.h>
#include "rk_defines.h"
#include "rk_debug.h"
#include "rk_mpi_adec.h"
#include "rk_mpi_ao.h"
#include "rk_mpi_mb.h"
#include "rk_mpi_sys.h"
#define ADEC_EN 1
#define AUDIO_RATE AUDIO_SAMPLE_RATE_16000
#define AUDIO_BITS AUDIO_BIT_WIDTH_16
#define AUDIO_CH 2
#define AUDIO_CH_IN 1
#define AUDIO_PERIOD_SZ 256
#define AUDIO_PERIOD_CNT 4
static AUDIO_DEV aoDevId = 0;
static AIO_ATTR_S aoAttr;
static AO_CHN aoChn = 0;
static ADEC_CHN_ATTR_S adAttr;
static ADEC_CHN adChn = 0;
static MPP_CHN_S aoBindAttr, adecBindAttr;
static AUDIO_SOUND_MODE_E sound_mode(int ch)
{
switch (ch)
{
case 1:
return AUDIO_SOUND_MODE_MONO;
case 2:
return AUDIO_SOUND_MODE_STEREO;
default:
return AUDIO_SOUND_MODE_BUTT;
}
}
int ao_init(void)
{
AO_CHN_PARAM_S pstParams;
RK_S32 result;
memset(&aoAttr, 0, sizeof(AIO_ATTR_S));
snprintf(aoAttr.u8CardName,
sizeof(aoAttr.u8CardName), "default");
aoAttr.soundCard.channels = AUDIO_CH;
aoAttr.soundCard.sampleRate = AUDIO_RATE;
aoAttr.soundCard.bitWidth = AUDIO_BITS;
aoAttr.enBitwidth = AUDIO_BITS;
aoAttr.enSamplerate = AUDIO_RATE;
aoAttr.enSoundmode = sound_mode(AUDIO_CH_IN);
aoAttr.u32FrmNum = AUDIO_PERIOD_CNT;
aoAttr.u32PtNumPerFrm = AUDIO_PERIOD_SZ;
aoAttr.u32EXFlag = 0;
aoAttr.u32ChnCnt = 2;
RK_LOGI("rate %d bit %d ch %d", aoAttr.enSamplerate, aoAttr.enBitwidth,
aoAttr.enSoundmode);
result = RK_MPI_AO_SetPubAttr(aoDevId, &aoAttr);
if (result != 0)
{
RK_LOGE("ai set attr fail, reason = %x", result);
return -1;
}
result = RK_MPI_AO_Enable(aoDevId);
if (result != 0)
{
RK_LOGE("ai enable fail, reason = %x", result);
return -1;
}
memset(&pstParams, 0, sizeof(AO_CHN_PARAM_S));
pstParams.enLoopbackMode = AUDIO_LOOPBACK_NONE;
result = RK_MPI_AO_SetChnParams(aoDevId, aoChn, &pstParams);
if (result != RK_SUCCESS)
{
RK_LOGE("ai set channel params, aoChn = %d", aoChn);
goto ai_chn_err;
}
RK_MPI_AO_SetTrackMode(aoDevId, AUDIO_TRACK_OUT_STEREO);
result = RK_MPI_AO_EnableChn(aoDevId, aoChn);
if (result != 0)
{
RK_LOGE("ai enable channel fail, aoChn = %d, reason = %x", aoChn, result);
goto ai_chn_err;
}
result = RK_MPI_AO_EnableReSmp(aoDevId, aoChn,
AUDIO_RATE);
#if ADEC_EN
adAttr.stCodecAttr.enType = RK_AUDIO_ID_PCM_ALAW;
adAttr.stCodecAttr.u32Channels = AUDIO_CH_IN;
adAttr.stCodecAttr.u32SampleRate = AUDIO_RATE;
adAttr.stCodecAttr.u32BitPerCodedSample = 4;
adAttr.enType = RK_AUDIO_ID_PCM_ALAW;
adAttr.enMode = ADEC_MODE_STREAM;
adAttr.u32BufCount = 4;
adAttr.u32BufSize = 50 * 1024;
adAttr.u32Depth = 0;
result = RK_MPI_ADEC_CreateChn(adChn, &adAttr);
if (result)
{
RK_LOGE("create adec chn %d err:0x%x\n", adChn, result);
goto adec_err;
}
adecBindAttr.enModId = RK_ID_ADEC;
adecBindAttr.s32DevId = aoDevId;
adecBindAttr.s32ChnId = adChn;
aoBindAttr.enModId = RK_ID_AO;
aoBindAttr.s32DevId = aoDevId;
aoBindAttr.s32ChnId = aoChn;
result = RK_MPI_SYS_Bind(&adecBindAttr, &aoBindAttr);
if (result)
{
RK_LOGE("bind ai adec failed:0x%x\n", result);
goto bind_err;
}
#endif
return RK_SUCCESS;
#if ADEC_EN
bind_err:
RK_MPI_ADEC_DestroyChn(adChn);
adec_err:
RK_MPI_AO_DisableChn(aoDevId, aoChn);
#endif
ai_chn_err:
RK_MPI_AO_Disable(aoDevId);
return RK_FAILURE;
}
static RK_S32 free_cb(void *opaque)
{
if (opaque)
free(opaque);
return 0;
}
int ao_push(int (*hook)(void *, char *, int), void *arg)
{
#if !ADEC_EN
static RK_U64 timeStamp = 0;
AUDIO_FRAME_S frame;
MB_EXT_CONFIG_S extConfig;
RK_S32 result;
RK_U8 *buf;
int size = 1024;
int ret;
buf = malloc(size * sizeof(RK_U8));
if ((ret = hook(arg, buf, size)) != size)
{
printf("input size error %d\n", ret);
free(buf);
return RK_FAILURE;
}
frame.u32Len = size;
frame.u64TimeStamp = timeStamp++;
frame.enBitWidth = AUDIO_BITS;
frame.enSoundMode = sound_mode(AUDIO_CH_IN);
frame.bBypassMbBlk = RK_FALSE;
memset(&extConfig, 0, sizeof(extConfig));
extConfig.pOpaque = buf;
extConfig.pu8VirAddr = buf;
extConfig.u64Size = size;
RK_MPI_SYS_CreateMB(&(frame.pMbBlk), &extConfig);
result = RK_MPI_AO_SendFrame(aoDevId, aoChn, &frame, -1);
if (result < 0)
{
RK_LOGE("send frame fail, result = %X, TimeStamp = %lld, s32MilliSec = -1",
result, frame.u64TimeStamp);
}
RK_MPI_MB_ReleaseMB(frame.pMbBlk);
free(buf);
#else
static RK_U64 timeStamp = 0;
static RK_U64 count = 0;
AUDIO_STREAM_S stream;
MB_EXT_CONFIG_S extConfig;
RK_S32 result;
RK_U8 *buf;
int size = 1024;
buf = malloc(size * sizeof(RK_U8));
if ((size = hook(arg, buf, size)) <= 0)
{
free(buf);
return RK_FAILURE;
}
stream.u32Len = size;
stream.u64TimeStamp = timeStamp++;
stream.u32Seq = ++count;
stream.bBypassMbBlk = RK_FALSE;
memset(&extConfig, 0, sizeof(extConfig));
extConfig.pFreeCB = free_cb;
extConfig.pOpaque = buf;
extConfig.pu8VirAddr = buf;
extConfig.u64Size = size;
RK_MPI_SYS_CreateMB(&(stream.pMbBlk), &extConfig);
result = RK_MPI_ADEC_SendStream(adChn, &stream, RK_TRUE);
if (result < 0)
{
RK_LOGE("send frame fail, result = %X, TimeStamp = %lld, s32MilliSec = -1",
result, stream.u64TimeStamp);
}
RK_MPI_MB_ReleaseMB(stream.pMbBlk);
#endif
return result;
}
int ao_deinit(void)
{
int ret = 0;
#if ADEC_EN
ret = RK_MPI_SYS_UnBind(&adecBindAttr, &aoBindAttr);
if (ret)
{
RK_LOGE("ai disable chn failed:0x%x\n", ret);
}
#endif
ret = RK_MPI_AO_DisableChn(aoDevId, aoChn);
if (ret)
{
RK_LOGE("ai disable chn failed:0x%x\n", ret);
}
ret = RK_MPI_AO_Disable(aoDevId);
if (ret)
{
RK_LOGE("ai disable chn failed:0x%x\n", ret);
}
#if ADEC_EN
ret = RK_MPI_ADEC_DestroyChn(adChn);
if (ret)
{
RK_LOGE("ai disable chn failed:0x%x\n", ret);
}
#endif
return 0;
}
#ifdef AUDIO_OUT_MAIN
static int duration = 0;
static int last_ts = -1;
static int ao_read(void *arg, char *buf, int len)
{
int ret = fread(buf, 1, len, arg);
duration += len / sizeof(short) / AUDIO_CH_IN / (AUDIO_RATE / 1000);
if (duration / 1000 != last_ts)
{
last_ts = duration / 1000;
RK_LOGI("duration: %.3fs %d", duration / 1000.0, len);
}
return ret;
}
void main(int argc, char *argv[])
{
void *buf;
int len;
FILE *fd;
char *file;
file = (argc > 1) ? argv[1] : "/tmp/out.pcm";
fd = fopen(file, "rb");
if (!fd)
{
RK_LOGE("cannot open %s", file);
return;
}
RK_MPI_SYS_Init();
ao_init();
while (1)
ao_push(ao_read, fd);
ao_deinit();
RK_MPI_SYS_Exit();
fclose(fd);
}
#endif