初版
This commit is contained in:
@@ -0,0 +1,289 @@
|
||||
#ifdef SUPPORT_MS_EXTENSIONS
|
||||
#pragma bss_seg(".cvp_develop_node.data.bss")
|
||||
#pragma data_seg(".cvp_develop_node.data")
|
||||
#pragma const_seg(".cvp_develop_node.text.const")
|
||||
#pragma code_seg(".cvp_develop_node.text")
|
||||
#endif
|
||||
#include "jlstream.h"
|
||||
#include "media/audio_base.h"
|
||||
#include "circular_buf.h"
|
||||
#include "cvp_node.h"
|
||||
#include "app_config.h"
|
||||
|
||||
#if TCFG_AUDIO_DUT_ENABLE
|
||||
#include "audio_dut_control.h"
|
||||
#endif
|
||||
|
||||
#if TCFG_AUDIO_CVP_DEVELOP_ENABLE
|
||||
#define CVP_INPUT_SIZE 256*3 //CVP输入缓存,short
|
||||
|
||||
struct cvp_cfg_t {
|
||||
u8 mic_num;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct cvp_node_hdl {
|
||||
struct stream_frame *frame[3]; //输入frame存储,算法输入缓存使用
|
||||
struct stream_node *node; //节点句柄
|
||||
struct cvp_cfg_t cfg;
|
||||
u8 buf_cnt; //循环输入buffer位置
|
||||
s16 *buf;
|
||||
s16 *buf_ref;
|
||||
s16 *buf_ref_1;
|
||||
u32 ref_sr;
|
||||
u16 source_uuid; //源节点uuid
|
||||
};
|
||||
|
||||
static struct cvp_node_hdl *g_cvp_hdl;
|
||||
|
||||
int cvp_node_output_handle(s16 *data, u16 len)
|
||||
{
|
||||
struct stream_frame *frame;
|
||||
frame = jlstream_get_frame(g_cvp_hdl->node->oport, len);
|
||||
if (!frame) {
|
||||
return 0;
|
||||
}
|
||||
frame->len = len;
|
||||
memcpy(frame->data, data, len);
|
||||
jlstream_push_frame(g_cvp_hdl->node->oport, frame);
|
||||
return len;
|
||||
}
|
||||
|
||||
int cvp_node_param_cfg_read(void *priv, u8 ignore_subid)
|
||||
{
|
||||
struct cvp_node_hdl *hdl = (struct cvp_node_hdl *)priv;
|
||||
int len = 0;
|
||||
u8 subid;
|
||||
if (g_cvp_hdl) {
|
||||
subid = g_cvp_hdl->node->subid;
|
||||
} else {
|
||||
subid = 0XFF;
|
||||
}
|
||||
|
||||
struct node_param ncfg = {0};
|
||||
len = jlstream_read_node_data(NODE_UUID_CVP_DEVELOP, subid, (u8 *)&ncfg);
|
||||
if (len != sizeof(ncfg)) {
|
||||
printf("cvp_dms_name read ncfg err\n");
|
||||
return -2;
|
||||
}
|
||||
char mode_index = 0;
|
||||
char cfg_index = 0;//目标配置项序号
|
||||
struct cfg_info info = {0};
|
||||
if (!jlstream_read_form_node_info_base(mode_index, ncfg.name, cfg_index, &info)) {
|
||||
len = jlstream_read_form_cfg_data(&info, &hdl->cfg);
|
||||
}
|
||||
printf(" %s len %d, sizeof(cfg) %d\n", __func__, len, (int)sizeof(struct cvp_cfg_t));
|
||||
if (len != sizeof(struct cvp_cfg_t)) {
|
||||
printf("cvp_develop_param read ncfg err\n");
|
||||
return -1 ;
|
||||
}
|
||||
g_printf("mic_num %d\n", hdl->cfg.mic_num);
|
||||
if (!hdl->cfg.mic_num) {
|
||||
hdl->cfg.mic_num = 1;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
/*节点输出回调处理,可处理数据或post信号量*/
|
||||
static void cvp_handle_frame(struct stream_iport *iport, struct stream_note *note)
|
||||
{
|
||||
struct cvp_node_hdl *hdl = (struct cvp_node_hdl *)iport->private_data;
|
||||
s16 *dat, *tbuf, *tbuf_ref, *tbuf_ref_1;
|
||||
int wlen;
|
||||
struct stream_frame *in_frame;
|
||||
|
||||
while (1) {
|
||||
in_frame = jlstream_pull_frame(iport, note); //从iport读取数据
|
||||
if (!in_frame) {
|
||||
break;
|
||||
}
|
||||
#if TCFG_AUDIO_DUT_ENABLE
|
||||
//产测bypass 模式 不经过算法
|
||||
if (cvp_dut_mode_get() == CVP_DUT_MODE_BYPASS) {
|
||||
struct stream_node *node = iport->node;
|
||||
jlstream_push_frame(node->oport, in_frame);
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
//模仿ADCbuff的存储方法
|
||||
if (hdl->cfg.mic_num == 1) { //单麦第三方算法
|
||||
dat = hdl->buf + (in_frame->len / 2 * hdl->buf_cnt);
|
||||
memcpy((u8 *)dat, in_frame->data, in_frame->len);
|
||||
audio_aec_inbuf(dat, in_frame->len);
|
||||
} else if (hdl->cfg.mic_num == 2) { //双麦第三方算法
|
||||
wlen = in_frame->len >> 2; //单个ADC的点数
|
||||
tbuf = hdl->buf + (wlen * hdl->buf_cnt);
|
||||
tbuf_ref = hdl->buf_ref + (wlen * hdl->buf_cnt);
|
||||
dat = (s16 *)in_frame->data;
|
||||
for (int i = 0; i < wlen; i++) {
|
||||
tbuf[i] = dat[2 * i];
|
||||
tbuf_ref[i] = dat[2 * i + 1];
|
||||
}
|
||||
#if TCFG_AUDIO_DMS_MIC_MANAGE == DMS_MASTER_MIC0
|
||||
audio_aec_inbuf_ref(tbuf_ref, wlen << 1);
|
||||
audio_aec_inbuf(tbuf, wlen << 1);
|
||||
#else
|
||||
audio_aec_inbuf_ref(tbuf, wlen << 1);
|
||||
audio_aec_inbuf(tbuf_ref, wlen << 1);
|
||||
#endif/*TCFG_AUDIO_DMS_MIC_MANAGE*/
|
||||
} else if (hdl->cfg.mic_num == 3) { //三麦第三方算法
|
||||
wlen = in_frame->len / 6; //单个ADC的点数
|
||||
tbuf = hdl->buf + (wlen * hdl->buf_cnt);
|
||||
tbuf_ref = hdl->buf_ref + (wlen * hdl->buf_cnt);
|
||||
tbuf_ref_1 = hdl->buf_ref_1 + (wlen * hdl->buf_cnt);
|
||||
dat = (s16 *)in_frame->data;
|
||||
for (int i = 0; i < wlen; i++) {
|
||||
tbuf[i] = dat[3 * i];
|
||||
tbuf_ref[i] = dat[3 * i + 1];
|
||||
tbuf_ref_1[i] = dat[3 * i + 2];
|
||||
}
|
||||
audio_aec_inbuf_ref(tbuf_ref, wlen << 1);
|
||||
audio_aec_inbuf_ref_1(tbuf_ref_1, wlen << 1);
|
||||
audio_aec_inbuf(tbuf, wlen << 1);
|
||||
}
|
||||
if (++hdl->buf_cnt > ((CVP_INPUT_SIZE / 256) - 1)) { //计算下一个ADCbuffer位置
|
||||
hdl->buf_cnt = 0;
|
||||
}
|
||||
jlstream_free_frame(in_frame); //释放iport资源
|
||||
}
|
||||
}
|
||||
|
||||
static int cvp_adapter_bind(struct stream_node *node, u16 uuid)
|
||||
{
|
||||
struct cvp_node_hdl *hdl = malloc(sizeof(*hdl));
|
||||
|
||||
memset(hdl, 0, sizeof(*hdl));
|
||||
|
||||
node->type = NODE_TYPE_ASYNC;
|
||||
hdl->node = node;
|
||||
node->private_data = hdl;
|
||||
hdl->buf_cnt = 0;
|
||||
cvp_node_param_cfg_read(hdl, 0);
|
||||
//根据算法单麦/双麦分配对应的空间
|
||||
hdl->buf = (s16 *)malloc(CVP_INPUT_SIZE << 1);
|
||||
if (hdl->cfg.mic_num == 2) {
|
||||
hdl->buf_ref = (s16 *)malloc(CVP_INPUT_SIZE << 1);
|
||||
} else if (hdl->cfg.mic_num == 3) {
|
||||
hdl->buf_ref = (s16 *)malloc(CVP_INPUT_SIZE << 1);
|
||||
hdl->buf_ref_1 = (s16 *)malloc(CVP_INPUT_SIZE << 1);
|
||||
}
|
||||
g_cvp_hdl = hdl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*打开改节点输入接口*/
|
||||
static void cvp_ioc_open_iport(struct stream_iport *iport)
|
||||
{
|
||||
iport->handle_frame = cvp_handle_frame;
|
||||
iport->private_data = iport->node->private_data;
|
||||
}
|
||||
|
||||
/*节点参数协商*/
|
||||
static int cvp_ioc_negotiate(struct stream_iport *iport)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*节点start函数*/
|
||||
static void cvp_ioc_start(struct cvp_node_hdl *hdl)
|
||||
{
|
||||
struct stream_fmt *fmt = &hdl->node->oport->fmt;
|
||||
struct audio_aec_init_param_t init_param;
|
||||
init_param.sample_rate = fmt->sample_rate;
|
||||
init_param.ref_sr = hdl->ref_sr;
|
||||
init_param.mic_num = hdl->cfg.mic_num;
|
||||
|
||||
if (hdl->source_uuid == NODE_UUID_ADC) {
|
||||
if (audio_adc_file_get_esco_mic_num() != hdl->cfg.mic_num) {
|
||||
#if TCFG_AUDIO_DUT_ENABLE
|
||||
//使能产测时,只有算法模式才需判断
|
||||
if (cvp_dut_mode_get() == CVP_DUT_MODE_ALGORITHM) {
|
||||
ASSERT(0, "CVP_develop ESCO MIC num is %d != %d\n", audio_adc_file_get_esco_mic_num(), hdl->cfg.mic_num);
|
||||
}
|
||||
#else
|
||||
ASSERT(0, "CVP_develop ESCO MIC num is %d != %d\n", audio_adc_file_get_esco_mic_num(), hdl->cfg.mic_num);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
audio_aec_init(&init_param);
|
||||
}
|
||||
|
||||
/*节点stop函数*/
|
||||
static void cvp_ioc_stop(struct cvp_node_hdl *hdl)
|
||||
{
|
||||
if (hdl) {
|
||||
/* for (int i = 0; i < 3; i++) { */
|
||||
/* if (hdl->frame[i] != NULL) { //检查是否存在未释放的iport缓存 */
|
||||
/* jlstream_free_frame(hdl->frame[i]); //释放iport缓存 */
|
||||
/* } */
|
||||
/* } */
|
||||
audio_aec_close();
|
||||
}
|
||||
}
|
||||
|
||||
/*节点ioctl函数*/
|
||||
static int cvp_adapter_ioctl(struct stream_iport *iport, int cmd, int arg)
|
||||
{
|
||||
int ret = 0;
|
||||
struct cvp_node_hdl *hdl = (struct cvp_node_hdl *)iport->private_data;
|
||||
|
||||
switch (cmd) {
|
||||
case NODE_IOC_OPEN_IPORT:
|
||||
cvp_ioc_open_iport(iport);
|
||||
break;
|
||||
case NODE_IOC_OPEN_OPORT:
|
||||
break;
|
||||
case NODE_IOC_CLOSE_IPORT:
|
||||
break;
|
||||
case NODE_IOC_NEGOTIATE:
|
||||
*(int *)arg |= cvp_ioc_negotiate(iport);
|
||||
break;
|
||||
case NODE_IOC_SET_FMT:
|
||||
hdl->ref_sr = (u32)arg;
|
||||
break;
|
||||
case NODE_IOC_START:
|
||||
cvp_ioc_start(hdl);
|
||||
break;
|
||||
case NODE_IOC_SUSPEND:
|
||||
case NODE_IOC_STOP:
|
||||
cvp_ioc_stop(hdl);
|
||||
break;
|
||||
case NODE_IOC_SET_PRIV_FMT:
|
||||
hdl->source_uuid = (u16)arg;
|
||||
printf("source_uuid %x", (int)hdl->source_uuid);
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*节点用完释放函数*/
|
||||
static void cvp_adapter_release(struct stream_node *node)
|
||||
{
|
||||
struct cvp_node_hdl *hdl = (struct cvp_node_hdl *)node->private_data;
|
||||
//根据算法单麦/双麦释放对应的空间
|
||||
free(hdl->buf);
|
||||
if (hdl->cfg.mic_num == 2) {
|
||||
free(hdl->buf_ref);
|
||||
hdl->buf_ref = NULL;
|
||||
} else if (hdl->cfg.mic_num == 3) {
|
||||
free(hdl->buf_ref);
|
||||
hdl->buf_ref = NULL;
|
||||
free(hdl->buf_ref_1);
|
||||
hdl->buf_ref_1 = NULL;
|
||||
}
|
||||
free(hdl);
|
||||
g_cvp_hdl = NULL;
|
||||
}
|
||||
|
||||
/*节点adapter 注意需要在sdk_used_list声明,否则会被优化*/
|
||||
REGISTER_STREAM_NODE_ADAPTER(cvp_node_adapter) = {
|
||||
.name = "cvp_develop",
|
||||
.uuid = NODE_UUID_CVP_DEVELOP,
|
||||
.bind = cvp_adapter_bind,
|
||||
.ioctl = cvp_adapter_ioctl,
|
||||
.release = cvp_adapter_release,
|
||||
};
|
||||
|
||||
#endif/*TCFG_CVP_DEVELOP_ENABLE*/
|
||||
Reference in New Issue
Block a user