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

374 lines
11 KiB
C
Raw Permalink 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(".spk_eq.data.bss")
#pragma data_seg(".spk_eq.data")
#pragma const_seg(".spk_eq.text.const")
#pragma code_seg(".spk_eq.text")
#endif
#include "system/includes.h"
#include "media/includes.h"
#include "app_config.h"
#include "audio_config.h"
#include "effects/effects_adj.h"
#include "effects/audio_spk_eq.h"
#include "jlstream.h"
#include "user_cfg_id.h"
#include "online_db_deal.h"
#if TCFG_SPEAKER_EQ_NODE_ENABLE
static u8 spk_eq_read_from_ram = 0;
static float spk_eq_global_gain[2];
static struct eq_seg_info spk_eq_tab[20] = {
//left
{0, EQ_IIR_TYPE_BAND_PASS, 31, 0, 0.7f},
{1, EQ_IIR_TYPE_BAND_PASS, 62, 0, 0.7f},
{2, EQ_IIR_TYPE_BAND_PASS, 125, 0, 0.7f},
{3, EQ_IIR_TYPE_BAND_PASS, 250, 0, 0.7f},
{4, EQ_IIR_TYPE_BAND_PASS, 500, 0, 0.7f},
{5, EQ_IIR_TYPE_BAND_PASS, 1000, 0, 0.7f},
{6, EQ_IIR_TYPE_BAND_PASS, 2000, 0, 0.7f},
{7, EQ_IIR_TYPE_BAND_PASS, 4000, 0, 0.7f},
{8, EQ_IIR_TYPE_BAND_PASS, 8000, 0, 0.7f},
{9, EQ_IIR_TYPE_BAND_PASS, 16000, 0, 0.7f},
//right
{0, EQ_IIR_TYPE_BAND_PASS, 31, 0, 0.7f},
{1, EQ_IIR_TYPE_BAND_PASS, 62, 0, 0.7f},
{2, EQ_IIR_TYPE_BAND_PASS, 125, 0, 0.7f},
{3, EQ_IIR_TYPE_BAND_PASS, 250, 0, 0.7f},
{4, EQ_IIR_TYPE_BAND_PASS, 500, 0, 0.7f},
{5, EQ_IIR_TYPE_BAND_PASS, 1000, 0, 0.7f},
{6, EQ_IIR_TYPE_BAND_PASS, 2000, 0, 0.7f},
{7, EQ_IIR_TYPE_BAND_PASS, 4000, 0, 0.7f},
{8, EQ_IIR_TYPE_BAND_PASS, 8000, 0, 0.7f},
{9, EQ_IIR_TYPE_BAND_PASS, 16000, 0, 0.7f},
};
/*
*spk_eq 系数更新接口,更新第几段eq系数
*parm: *seg
*seg->index:第几段(0~9)
*seg->iir_type:滤波器类型(EQ_IIR_TYPE)
*seg->freq:中心截止频率(20~20kHz)
*seg->gain:增益(-12~13dB
* */
void spk_eq_seg_update(struct eq_seg_info *seg)
{
//段系数更新
struct spk_eq_seg_parm sparm;
sparm.type = UPDATE_SPK_EQ_SEG;
sparm.left_right = 0;
memcpy(&sparm.seg, seg, sizeof(struct eq_seg_info));
int ret = jlstream_set_node_param(NODE_UUID_SPEAKER_EQ, "spk_eq", &sparm, sizeof(sparm));
if (ret <= 0) {
struct eq_seg_info *tar_seg = (struct eq_seg_info *)spk_eq_tab;
memcpy(&tar_seg[sparm.seg.index], &sparm.seg, sizeof(struct eq_seg_info));
}
}
/*
*spk_eq 右声道系数更新接口,更新第几段eq系数
*parm: *seg
*seg->index:第几段(0~9)
*seg->iir_type:滤波器类型(EQ_IIR_TYPE)
*seg->freq:中心截止频率(20~20kHz)
*seg->gain:增益(-12~13dB
* */
void spk_eq_seg_update_R(struct eq_seg_info *seg)
{
//段系数更新
struct spk_eq_seg_parm sparm;
sparm.type = UPDATE_SPK_EQ_SEG;
sparm.left_right = 1;
memcpy(&sparm.seg, seg, sizeof(struct eq_seg_info));
int ret = jlstream_set_node_param(NODE_UUID_SPEAKER_EQ, "spk_eq", &sparm, sizeof(sparm));
if (ret <= 0) {
struct eq_seg_info *tar_seg = (struct eq_seg_info *)&spk_eq_tab[10];
memcpy(&tar_seg[sparm.seg.index], &sparm.seg, sizeof(struct eq_seg_info));
}
}
/*
*spk_eq 左声道总增益更新
* */
void spk_eq_global_gain_udapte(float global_gain)
{
struct spk_eq_global_gain gparm;
gparm.type = UPDATE_SPK_EQ_GLOBAL_GAIN;
gparm.left_right = 0;
gparm.global_gain = global_gain;
printf("dbug 1\n");
int ret = jlstream_set_node_param(NODE_UUID_SPEAKER_EQ, "spk_eq", &gparm, sizeof(gparm));
spk_eq_global_gain[gparm.left_right] = gparm.global_gain;
}
/*
*spk_eq 右声道总增益更新
* */
void spk_eq_global_gain_udapte_R(float global_gain)
{
struct spk_eq_global_gain gparm;
gparm.type = UPDATE_SPK_EQ_GLOBAL_GAIN;
gparm.left_right = 1;
gparm.global_gain = global_gain;
int ret = jlstream_set_node_param(NODE_UUID_SPEAKER_EQ, "spk_eq", &gparm, sizeof(gparm));
spk_eq_global_gain[gparm.left_right] = gparm.global_gain;
}
int spk_eq_save_to_vm(void)
{
int ret_tmp = 0;
struct spk_eq_get_seg_tab seg_tab = {0};
seg_tab.type = GET_SPK_EQ_SEG_TAB;//获取系数表
int ret = jlstream_get_node_param(NODE_UUID_SPEAKER_EQ, "spk_eq", (void *)&seg_tab, sizeof(seg_tab));
if (ret <= 0) {
seg_tab.seg = (struct eq_seg_info *)spk_eq_tab;
seg_tab.tab_size = sizeof(spk_eq_tab);
}
ret = syscfg_write(CFG_SPK_EQ_SEG_SAVE, seg_tab.seg, seg_tab.tab_size);
if (ret <= 0) {
printf("spk_eq tab write to vm err, ret %d\n", ret);
ret_tmp = -1;
}
struct spk_eq_get_global_gain g_gain = {0};
g_gain.type = GET_SPK_EQ_GLOBAL_GAIN;//获取总增益
ret = jlstream_get_node_param(NODE_UUID_SPEAKER_EQ, "spk_eq", (void *)&g_gain, sizeof(g_gain));
if (ret <= 0) {
memcpy(g_gain.global_gain, spk_eq_global_gain, sizeof(spk_eq_global_gain));
}
ret = syscfg_write(CFG_SPK_EQ_GLOBAL_GAIN_SAVE, g_gain.global_gain, sizeof(g_gain.global_gain));
if (ret <= 0) {
printf("spk_eq global gain write to vm err ret %d\n", ret);
ret_tmp = -1;
}
return ret_tmp;
}
/*
*spk_eq 系数表从vm中读取
* */
int spk_eq_read_from_vm(void *priv)
{
struct spk_eq_get_parm *spk_parm = (struct spk_eq_get_parm *)priv;
if (spk_parm->type == GET_SPK_EQ_SEG_TAB) {
spk_parm->seg_tab.seg = (struct eq_seg_info *)spk_eq_tab;
spk_parm->seg_tab.tab_size = sizeof(spk_eq_tab) / 2;
//printf("-------spk tab %x, %d\n", (int)spk_eq_tab, spk_parm->seg_tab.tab_size);
} else if (spk_parm->type == GET_SPK_EQ_VM_DATA) {
struct spk_eq_get_seg_tab *seg_tab = (struct spk_eq_get_seg_tab *)&spk_parm->seg_tab;
struct spk_eq_get_global_gain *g_gain = (struct spk_eq_get_global_gain *)&spk_parm->g_gain;
if (spk_eq_read_from_ram) {
memcpy(g_gain->global_gain, spk_eq_global_gain, sizeof(spk_eq_global_gain));
return 0;
}
spk_eq_read_from_ram = 1;
int ret = syscfg_read(CFG_SPK_EQ_SEG_SAVE, seg_tab->seg, seg_tab->tab_size);
if (ret <= 0) {
printf("skp_eq read from vm err\n");
return -1;
}
ret = syscfg_read(CFG_SPK_EQ_GLOBAL_GAIN_SAVE, g_gain->global_gain, sizeof(g_gain->global_gain));
if (ret <= 0) {
printf("spk_eq global gain read from vm err\n");
return -1;
}
}
return 0;
}
typedef struct {
u16 magic; //0x3344
u16 crc; //data crc
u8 data[32]; //data
} SPK_EQ_PACK;
#define CMD_SEG 0x1
#define CMD_GLOBAL 0x2
#define CMD_SAVE_PARM 0x3
#define CMD_RESET_PARM 0x4
/*
*右声道更新命令
* */
#define CMD_SEG_R 0x5
#define CMD_GLOBAL_R 0x6
#define CMD_SUPPORT_GLOBAL_GAIN 0x7
#define CMD_READ_SEG_L 0x8//左声道或者单声道获取系数表
#define CMD_READ_SEG_R 0x9//右声道获取系数表
#define CMD_READ_GLOBAL_L 0xa //左声道或者单声道获取总增益
#define CMD_READ_GLOBAL_R 0xb //右声道获取总增益
#define SPK_EQ_CRC_EN 0//是否使能crc校验
static u8 parse_seq = 0;
void (*send_data_handler)(u8 seq, u8 *packet, u8 size);
static int spk_eq_ack_packet(u8 seq, u8 *packet, u8 size)
{
if (send_data_handler) {
send_data_handler(seq, packet, size);
} else {
return app_online_db_ack(seq, packet, size);
}
return 0;
}
int spk_eq_spp_rx_packet(u8 *packet, u8 len)
{
SPK_EQ_PACK pack = {0};//packet;
memcpy(&pack, packet, len);
if (pack.magic != 0x3344) {
printf("magic err 0x%x\n", pack.magic);
return -1;
}
struct eq_seg_info seg = {0};
float global_gain = 0;
u8 cmd = pack.data[0];
u16 crc;
printf("cmd %d\n", cmd);
switch (cmd) {
case CMD_SEG:
#if SPK_EQ_CRC_EN
crc = CRC16(pack.data, len - 4);
if (crc != pack.crc) {
printf("spk_seg pack crc err %x, %x\n", crc, pack.crc);
return -1;
}
#endif
memcpy(&seg, &pack.data[1], sizeof(struct eq_seg_info));
spk_eq_seg_update(&seg);
printf("idx:%d, iir:%d, frq:%d, gain:0x%x, q:0x%x \n", seg.index, seg.iir_type, seg.freq, *(int *)&seg.gain, *(int *)&seg.q);
break;
case CMD_GLOBAL:
#if SPK_EQ_CRC_EN
crc = CRC16(pack.data, len - 4);
if (crc != pack.crc) {
printf("spk global gain info pack crc err %x, %x\n", crc, pack.crc);
return -1;
}
#endif
memcpy(&global_gain, &pack.data[1], sizeof(float));
spk_eq_global_gain_udapte(global_gain);
printf("global_gain 0x%x\n", *(int *)&global_gain);
break;
case CMD_SEG_R:
#if SPK_EQ_CRC_EN
crc = CRC16(pack.data, len - 4);
if (crc != pack.crc) {
printf("spk_seg_r pack crc err %x, %x\n", crc, pack.crc);
return -1;
}
#endif
memcpy(&seg, &pack.data[1], sizeof(struct eq_seg_info));
spk_eq_seg_update_R(&seg);
printf("R idx:%d, iir:%d, frq:%d, gain:0x%x, q:0x%x \n", seg.index, seg.iir_type, seg.freq, *(int *)&seg.gain, *(int *)&seg.q);
break;
case CMD_GLOBAL_R:
#if SPK_EQ_CRC_EN
crc = CRC16(pack.data, len - 4);
if (crc != pack.crc) {
printf("spk global gain info pack crc err %x, %x\n", crc, pack.crc);
return -1;
}
#endif
memcpy(&global_gain, &pack.data[1], sizeof(float));
spk_eq_global_gain_udapte_R(global_gain);
printf("R global_gain 0x%x\n", *(int *)&global_gain);
break;
case CMD_SAVE_PARM:
return spk_eq_save_to_vm();
break;
case CMD_RESET_PARM:
struct eq_seg_info seg;
for (int i = 0; i < 10; i++) {
seg.index = i;
seg.freq = 100;
seg.iir_type = EQ_IIR_TYPE_BAND_PASS;
seg.gain = 0.0f;
seg.q = 0.7f;
spk_eq_seg_update(&seg);
spk_eq_seg_update_R(&seg);
}
spk_eq_global_gain_udapte(0);
spk_eq_global_gain_udapte_R(0);
return spk_eq_save_to_vm();
break;
case CMD_SUPPORT_GLOBAL_GAIN:
//suuport global_gain
break;
case CMD_READ_SEG_L:
spk_eq_ack_packet(parse_seq, (u8 *)spk_eq_tab, sizeof(spk_eq_tab) / 2);
return 1;
case CMD_READ_SEG_R:
spk_eq_ack_packet(parse_seq, (u8 *)&spk_eq_tab[10], sizeof(spk_eq_tab) / 2);
return 1;
case CMD_READ_GLOBAL_L:
spk_eq_ack_packet(parse_seq, (u8 *)&spk_eq_global_gain[0], 4);
return 1;
case CMD_READ_GLOBAL_R:
spk_eq_ack_packet(parse_seq, (u8 *)&spk_eq_global_gain[1], 4);
return 1;
default:
printf("crc %d\n", pack.crc);
printf("cmd err %x\n", cmd);
return -1;
}
return 0;
}
int spk_eq_read_seg_l(u8 **buf)
{
*buf = (u8 *)(&spk_eq_tab[0]);
return sizeof(spk_eq_tab) / 2;
}
int spk_eq_read_seg_r(u8 **buf)
{
#if AUDIO_SPK_EQ_STERO
*buf = (u8 *)(&spk_eq_tab[10]);
return sizeof(spk_eq_tab) / 2;
#else
return 0;
#endif
}
int spk_eq_app_online_parse(u8 *packet, u8 size, u8 *ext_data, u16 ext_size)
{
if (ext_data) {
parse_seq = ext_data[1];
} else {
parse_seq = 0xff;
}
printf("parse_seq %x\n", parse_seq);
int ret = spk_eq_spp_rx_packet(packet, size);
if (!ret) {
u8 ack[] = "OK";
spk_eq_ack_packet(parse_seq, ack, sizeof(ack));
} else if (ret != 1) {
u8 ack[] = "ER";
spk_eq_ack_packet(parse_seq, ack, sizeof(ack));
}
return 0;
}
void spk_eq_set_send_data_handler(void (*handler)(u8 seq, u8 *packet, u8 size))
{
send_data_handler = handler;
}
int spk_eq_init(void)
{
#if APP_ONLINE_DEBUG
app_online_db_register_handle(DB_PKT_TYPE_SPK_EQ, spk_eq_app_online_parse);
#endif
return 0;
}
__initcall(spk_eq_init);
#endif