Files
AC707N/SDK/audio/CVP/audio_cvp_ref_task.c
T
2025-12-03 11:12:34 +08:00

363 lines
11 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".audio_cvp_ref_task.data.bss")
#pragma data_seg(".audio_cvp_ref_task.data")
#pragma const_seg(".audio_cvp_ref_task.text.const")
#pragma code_seg(".audio_cvp_ref_task.text")
#endif
/*
****************************************************************
* AUDIO CVP REF SRC
* File : audio_cvp_ref_src.c
* By :
* Notes : CVP回音消除的外部参考数变采样
*
****************************************************************
*/
#include "audio_cvp.h"
#include "system/includes.h"
#include "media/includes.h"
#include "circular_buf.h"
#include "Resample_api.h"
#include "media/audio_general.h"
#include "effects/convert_data.h"
#include "jlstream.h"
#include "esco_player.h"
#include "pc_spk_player.h"
#define CVP_REF_SRC_TASK_NAME "CVP_RefTask"
#define ALINK_CH_IDX 0 //iis输出使用的通道
#define CVP_REF_SRC_FRAME_SIZE (480 * 2)//512
typedef struct {
volatile u8 state;
volatile u8 busy;
RS_STUCT_API *sw_src_api;
u32 *sw_src_buf;
u16 input_rate;
u16 output_rate;
u8 channel;
s16 *ref_tmp_buf;
cbuffer_t cbuf;
u8 ref_buf[2048 * 10];//和输入的数据大小有关系
u8 align_flag;
u8 bit_width;
u8 data_multiple;//输入输出数据倍数
} cvp_ref_src_t;
static cvp_ref_src_t *cvp_ref_src = NULL;
extern void iis_node_write_callback_add(const char *name, u8 is_after_write_over, u8 scene, void (*cb)(void *, int));
extern void iis_node_write_callback_del(const char *name);
#define IIS_READ_MAGIC 0x55AA
static int iis_read_pos = IIS_READ_MAGIC;
/*获取iis dma里面还有多少数据没有播放*/
static u32 get_alink_data_len(u8 ch_idx)
{
u32 len = 0;
switch (ch_idx) {
case 0:
len = (JL_ALNK0->LEN - JL_ALNK0->SHN0) * 4;
break;
case 1:
len = (JL_ALNK0->LEN - JL_ALNK0->SHN1) * 4;
break;
case 2:
len = (JL_ALNK0->LEN - JL_ALNK0->SHN2) * 4;
break;
case 3:
len = (JL_ALNK0->LEN - JL_ALNK0->SHN3) * 4;
break;
}
return len;
}
/*iis硬件写指针位置*/
static u32 get_alink_hwptr(u8 ch_idx)
{
u32 val = 0;
switch (ch_idx) {
case 0:
val = JL_ALNK0->HWPTR0;
break;
case 1:
val = JL_ALNK0->HWPTR1;
break;
case 2:
val = JL_ALNK0->HWPTR2;
break;
case 3:
val = JL_ALNK0->HWPTR3;
break;
}
return val;
}
/*重新对齐iis延时*/
int audio_cvp_ref_data_align_reset(void)
{
iis_read_pos = IIS_READ_MAGIC;
cvp_ref_src_t *hdl = cvp_ref_src;
if (hdl) {
hdl->align_flag = 0;
cbuf_clear(&hdl->cbuf);
}
return 0;
}
/*对齐iis的数据延时,在第一次mic数据来时调用对齐*/
void audio_cvp_ref_data_align()
{
cvp_ref_src_t *hdl = cvp_ref_src;
/* !iis_read_pos iis有数据了才么开始对齐
!hdl->align_flag 表示还没有做对齐*/
if (hdl && !hdl->align_flag && !iis_read_pos) {
int iis_data_len = get_alink_data_len(ALINK_CH_IDX);
int cbuf_total_len = cbuf_get_data_len(&hdl->cbuf);
printf("hdl->cbuf len %d ", cbuf_total_len);
int need_read_len = cbuf_total_len - iis_data_len;
printf("adc_iis_data_align: %d %d", iis_data_len, need_read_len);
if (need_read_len >= 0) {
cbuf_read_updata(&hdl->cbuf, need_read_len);
} else {
cbuf_write_updata(&hdl->cbuf, need_read_len * (-1));
}
hdl->align_flag = 1;
//有参考数据进来,并且对齐后,取消忽略参考数据
audio_cvp_ioctl(CVP_OUTWAY_REF_IGNORE, 0, NULL);
}
}
static void audio_cvp_ref_src_run(s16 *data, int len)
{
cvp_ref_src_t *hdl = cvp_ref_src;
u16 ref_len = len;
if (hdl) {
if (hdl->bit_width) {
audio_convert_data_32bit_to_16bit_round((s32 *)data, (s16 *)data, ref_len >> 2);
ref_len >>= 1;
}
if (hdl->channel == 2) {
/* putchar('2'); */
/*双变单*/
for (int i = 0; i < (ref_len >> 2); i++) {
data[i] = ((int)data[2 * i] + (int)data[2 * i + 1]) / 2;
}
ref_len >>= 1;
}
if (hdl->sw_src_api) {
/* putchar('s'); */
ref_len = hdl->sw_src_api->run(hdl->sw_src_buf, data, ref_len >> 1, data);
ref_len <<= 1;
}
/* printf("ref_len %d : %d", ref_len, len); */
audio_aec_refbuf(data, NULL, ref_len);
}
}
static void audio_cvp_ref_src_task(void *p)
{
int msg[16];
cvp_ref_src_t *hdl = NULL;
while (1) {
os_taskq_pend("taskq", msg, ARRAY_SIZE(msg));
hdl = cvp_ref_src;
if (hdl && hdl->state) {
s16 *data = (s16 *)msg[1];
int len = msg[2];
/* putchar('r'); */
hdl->busy = 1;
int cbuf_data_len = cbuf_get_data_len(&hdl->cbuf);
/*判断cbuf的缓存够一帧数据,并且参考数据可写长度大于1帧时*/
while (cbuf_data_len >= CVP_REF_SRC_FRAME_SIZE && (get_audio_cvp_output_way_writable_len() * hdl->data_multiple) >= CVP_REF_SRC_FRAME_SIZE) {
cbuf_data_len -= CVP_REF_SRC_FRAME_SIZE;
cbuf_read(&hdl->cbuf, hdl->ref_tmp_buf, CVP_REF_SRC_FRAME_SIZE);
audio_cvp_ref_src_run((s16 *)hdl->ref_tmp_buf, CVP_REF_SRC_FRAME_SIZE);
}
hdl->busy = 0;
}
}
}
int audio_cvp_ref_src_data_fill(void *p, s16 *data, int len)
{
cvp_ref_src_t *hdl = cvp_ref_src;
int ret = 0;
if ((!esco_player_runing()
#if TCFG_USB_SLAVE_AUDIO_SPK_ENABLE
&& !pc_spk_player_runing()
#endif
) || (len == 0)) {
return 0;
}
if (hdl && hdl->state) {
if (0 == cbuf_write(&hdl->cbuf, data, len) && hdl->align_flag) {
cbuf_clear(&hdl->cbuf);
hdl->align_flag = 0;
printf("ref src cbuf wfail!!");
}
if (hdl->align_flag) {
if (cbuf_get_data_len(&hdl->cbuf) >= CVP_REF_SRC_FRAME_SIZE) {
ret = os_taskq_post_msg(CVP_REF_SRC_TASK_NAME, 2, (int)data, len);
}
}
}
return ret;
}
static void iis_write_callback(void *data, int len)
{
cvp_ref_src_t *hdl = cvp_ref_src;
if (hdl) {
if (iis_read_pos == IIS_READ_MAGIC) {
u32 iis_hwptr = get_alink_hwptr(ALINK_CH_IDX);
if (iis_hwptr) {
iis_read_pos = 0;
printf("JL_ALNK HWPTR %d, data_len %d", iis_hwptr, len);
}
}
if (iis_read_pos == 0) {
if (esco_player_runing()
#if TCFG_USB_SLAVE_AUDIO_SPK_ENABLE
|| pc_spk_player_runing()
#endif
) {
audio_cvp_ref_start(1);
}
}
audio_cvp_ref_src_data_fill(NULL, data, len);
}
}
/*
*********************************************************************
* Audio CVP Ref Src
* Description: 打开外部参考数据变采样
* Arguments : scene 场景
* insr 输入采样率
* outsr 输出采样率
* nch 输入数据的通道数
* Return : None.
* Note(s) : 声卡设备是DAC,默认不用外部提供参考数据
*********************************************************************
*/
int audio_cvp_ref_src_open(u8 scene, u32 insr, u32 outsr, u8 nch)
{
printf("audio_cvp_ref_src_open");
if (cvp_ref_src) {
printf("aec_ref_src alreadly open !!!");
return -1;
}
cvp_ref_src_t *hdl = zalloc(sizeof(cvp_ref_src_t));
if (hdl == NULL) {
printf("aec_ref_src malloc fail !!!");
return -1;
}
cbuf_init(&hdl->cbuf, hdl->ref_buf, sizeof(hdl->ref_buf));
int err = task_create(audio_cvp_ref_src_task, NULL, CVP_REF_SRC_TASK_NAME);
if (err != OS_NO_ERR) {
printf("task create error!");
free(hdl);
hdl = NULL;
return -1;
}
audio_cvp_set_output_way(1);
iis_node_write_callback_add(CVP_REF_SRC_TASK_NAME, 1, scene, iis_write_callback);
hdl->input_rate = insr;
hdl->output_rate = outsr;
hdl->channel = nch;
hdl->bit_width = audio_general_out_dev_bit_width();
hdl->sw_src_api = get_rs16_context();
printf("sw_src_api:0x%x\n", (int)(hdl->sw_src_api));
ASSERT(hdl->sw_src_api);
int sw_src_need_buf = hdl->sw_src_api->need_buf();
printf("sw_src_buf:%d\n", sw_src_need_buf);
hdl->sw_src_buf = zalloc(sw_src_need_buf);
ASSERT(hdl->sw_src_buf, "sw_src_buf zalloc fail");
RS_PARA_STRUCT rs_para_obj;
rs_para_obj.nch = 1;
rs_para_obj.dataTypeobj.IndataBit = 0;
rs_para_obj.dataTypeobj.OutdataBit = 0;
rs_para_obj.dataTypeobj.IndataInc = 1;
rs_para_obj.dataTypeobj.OutdataInc = 1;
rs_para_obj.dataTypeobj.Qval = 15;
int multiple_cnt;//倍数
if ((insr % 8000) == 0) {
multiple_cnt = insr / 8000;
rs_para_obj.new_insample = 6250;
if (outsr == 16000) {
//48k->16k
rs_para_obj.new_outsample = 2080 * (6 / multiple_cnt);
} else {
//48k->8k
rs_para_obj.new_outsample = (2080 / 2) * (6 / multiple_cnt);
}
} else {
multiple_cnt = insr / 11025;
rs_para_obj.new_insample = 12000;
if (outsr == 16000) {
//44.1k->16k
rs_para_obj.new_outsample = (17 * 256) * (4 / multiple_cnt);
} else {
//44.1k->8k
rs_para_obj.new_outsample = (17 * 256 / 2) * (4 / multiple_cnt);
}
}
printf("sw src,ch = %d, in = %d,out = %d\n", rs_para_obj.nch, rs_para_obj.new_insample, rs_para_obj.new_outsample);
hdl->sw_src_api->open(hdl->sw_src_buf, &rs_para_obj);
hdl->data_multiple = (insr / outsr) * nch * (1 << hdl->bit_width);
printf("indata nch %d, bitw %d, data_multiple %d", hdl->channel, hdl->bit_width, hdl->data_multiple);
hdl->ref_tmp_buf = zalloc(CVP_REF_SRC_FRAME_SIZE);
audio_cvp_ref_data_align_reset();
hdl->state = 1;
cvp_ref_src = hdl;
return 0;
}
void audio_cvp_ref_src_close()
{
cvp_ref_src_t *hdl = cvp_ref_src;
if (hdl) {
hdl->state = 0;
while (hdl->busy) {
putchar('w');
os_time_dly(2);
}
int err = task_kill(CVP_REF_SRC_TASK_NAME);
if (err) {
printf("kill task %s: err=%d\n", CVP_REF_SRC_TASK_NAME, err);
}
iis_node_write_callback_del(CVP_REF_SRC_TASK_NAME);
if (hdl->sw_src_api) {
hdl->sw_src_api = NULL;
}
if (hdl->sw_src_buf) {
free(hdl->sw_src_buf);
hdl->sw_src_buf = NULL;
}
if (hdl->ref_tmp_buf) {
free(hdl->ref_tmp_buf);
hdl->ref_tmp_buf = NULL;
}
free(hdl);
hdl = NULL;
cvp_ref_src = NULL;
}
}