Files
2025-12-03 11:12:34 +08:00

215 lines
6.2 KiB
C

#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".agc_node.data.bss")
#pragma data_seg(".agc_node.data")
#pragma const_seg(".agc_node.text.const")
#pragma code_seg(".agc_node.text")
#endif
#include "jlstream.h"
#include "app_config.h"
#include "audio_config.h"
#include "effects/effects_adj.h"
#include "frame_length_adaptive.h"
#include "audio_agc.h"
#if 1
#define agc_log printf
#else
#define agc_log(...)
#endif/*log_en*/
#define AGC_FRAME_SIZE 128
#if TCFG_AGC_NODE_ENABLE
struct agc_cfg_t {
float AGC_max_lvl; //最大幅度压制,range[0 : -90] dB
float AGC_fade_in_step; //淡入步进,range[0.1 : 5] dB
float AGC_fade_out_step; //淡出步进,range[0.1 : 5] dB
float AGC_max_gain; //放大上限, range[-90 : 40] dB
float AGC_min_gain; //放大下限, range[-90 : 40] dB
float AGC_speech_thr; //放大阈值, range[-70 : -40] dB
} __attribute__((packed));
struct agc_node_hdl {
u16 sr;
void *agc;
struct stream_frame *out_frame;
struct stream_node *node; //节点句柄
agc_param_t parm;
struct frame_length_adaptive_hdl *olen_adaptive;//输出长度适配
};
int agc_param_cfg_read(struct stream_node *node)
{
struct agc_cfg_t config;
struct agc_node_hdl *hdl = (struct agc_node_hdl *)node->private_data;
if (!hdl) {
return -1 ;
}
/*
*获取配置文件内的参数,及名字
* */
if (!jlstream_read_node_data_new(NODE_UUID_AGC, node->subid, (void *)&config, NULL)) {
printf("%s, read node data err\n", __FUNCTION__);
return -1 ;
}
memcpy(&hdl->parm, &config, sizeof(config));
agc_log("AGC_max_lvl %d/10\n", (int)(hdl->parm.AGC_max_lvl * 10));
agc_log("AGC_fade_in_step %d/10\n", (int)(hdl->parm.AGC_fade_in_step * 10));
agc_log("AGC_fade_out_step %d/10\n", (int)(hdl->parm.AGC_fade_out_step * 10));
agc_log("AGC_max_gain %d/10\n", (int)(hdl->parm.AGC_max_gain * 10));
agc_log("AGC_min_gain %d/10\n", (int)(hdl->parm.AGC_min_gain * 10));
agc_log("AGC_speech_thr %d/10\n", (int)(hdl->parm.AGC_speech_thr * 10));
return 0;
}
/*节点输出回调处理,可处理数据或post信号量*/
static void agc_handle_frame(struct stream_iport *iport, struct stream_note *note)
{
struct agc_node_hdl *hdl = (struct agc_node_hdl *)iport->private_data;
struct stream_node *node = iport->node;
struct stream_frame *in_frame;
int wlen;
while (1) {
in_frame = jlstream_pull_frame(iport, note); //从iport读取数据
if (!in_frame) {
break;
}
int out_frame_len = in_frame->len > (hdl->parm.AGC_frame_size << 1) ?
in_frame->len : (hdl->parm.AGC_frame_size << 1);
if (!hdl->out_frame) {
hdl->out_frame = jlstream_get_frame(node->oport, out_frame_len);
if (!hdl->out_frame) {
jlstream_return_frame(iport, in_frame);
return;
}
}
wlen = audio_agc_run(hdl->agc, (s16 *)in_frame->data,
(s16 *)hdl->out_frame->data, in_frame->len);
/*保证节点输入输出长度一样*/
if (!hdl->olen_adaptive) {
hdl->olen_adaptive = frame_length_adaptive_open(in_frame->len, out_frame_len);
}
int len = frame_length_adaptive_run(hdl->olen_adaptive, (s16 *)hdl->out_frame->data, (s16 *)hdl->out_frame->data, wlen);
if (len) {
hdl->out_frame->len = len;
jlstream_push_frame(node->oport, hdl->out_frame); //将数据推到oport
hdl->out_frame = NULL;
}
jlstream_free_frame(in_frame); //释放iport资源
}
}
/*节点预处理-在ioctl之前*/
static int agc_adapter_bind(struct stream_node *node, u16 uuid)
{
struct agc_node_hdl *hdl = zalloc(sizeof(*hdl));
hdl->node = node;
node->private_data = hdl; //保存私有信息
agc_param_cfg_read(node);
return 0;
}
/*打开改节点输入接口*/
static void agc_ioc_open_iport(struct stream_iport *iport)
{
iport->handle_frame = agc_handle_frame; //注册输出回调
iport->private_data = iport->node->private_data; //保存节点私有句柄
}
/*节点参数协商*/
static int agc_ioc_negotiate(struct stream_iport *iport)
{
return 0;
}
/*节点start函数*/
static void agc_ioc_start(struct agc_node_hdl *hdl)
{
struct stream_fmt *fmt = &hdl->node->oport->fmt;
hdl->parm.AGC_samplerate = fmt->sample_rate;
hdl->parm.AGC_frame_size = AGC_FRAME_SIZE;
agc_log("AGC_samplerate : %d", hdl->parm.AGC_samplerate);
agc_log("AGC_frame_size : %d", hdl->parm.AGC_frame_size);
hdl->agc = audio_agc_open(&hdl->parm);
}
/*节点stop函数*/
static void agc_ioc_stop(struct agc_node_hdl *hdl)
{
if (hdl->agc) {
audio_agc_close(hdl->agc);
hdl->agc = NULL;
}
if (hdl->olen_adaptive) {
frame_length_adaptive_close(hdl->olen_adaptive);
hdl->olen_adaptive = NULL;
}
if (hdl->out_frame) {
jlstream_free_frame(hdl->out_frame);
hdl->out_frame = NULL;
}
}
/*节点ioctl函数*/
static int agc_adapter_ioctl(struct stream_iport *iport, int cmd, int arg)
{
int ret = 0;
struct agc_node_hdl *hdl = (struct agc_node_hdl *)iport->private_data;
switch (cmd) {
case NODE_IOC_OPEN_IPORT:
agc_ioc_open_iport(iport);
break;
case NODE_IOC_NEGOTIATE:
*(int *)arg |= agc_ioc_negotiate(iport);
break;
case NODE_IOC_START:
agc_ioc_start(hdl);
break;
case NODE_IOC_SUSPEND:
case NODE_IOC_STOP:
agc_ioc_stop(hdl);
break;
}
return ret;
}
/*节点用完释放函数*/
static void agc_adapter_release(struct stream_node *node)
{
struct agc_node_hdl *hdl = (struct agc_node_hdl *)node->private_data;
if (!hdl) {
return;
}
free(hdl);
}
/*节点adapter 注意需要在sdk_used_list声明,否则会被优化*/
REGISTER_STREAM_NODE_ADAPTER(agc_node_adapter) = {
.name = "agc",
.uuid = NODE_UUID_AGC,
.bind = agc_adapter_bind,
.ioctl = agc_adapter_ioctl,
.release = agc_adapter_release,
};
//注册工具在线调试
REGISTER_ONLINE_ADJUST_TARGET(agc_process) = {
.uuid = NODE_UUID_AGC,
};
#endif /*TCFG_AGC_NODE_ENABLE*/