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

298 lines
8.6 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(".mic_effect.data.bss")
#pragma data_seg(".mic_effect.data")
#pragma const_seg(".mic_effect.text.const")
#pragma code_seg(".mic_effect.text")
#endif
#include "system/includes.h"
#include "jlstream.h"
#include "effects/audio_echo.h"
#include "effects/effects_adj.h"
#include "media/audio_general.h"
#include "media/audio_def.h"
#include "volume_node.h"
#include "app_main.h"
#include "mic_effect.h"
#include "app_config.h"
#include "fm_api.h"
static void mic_effect_ram_code_load();
static void mic_effect_ram_code_unload();
struct mic_effect_player {
struct jlstream *stream;
s16 dvol;
u8 dvol_index;
unsigned int echo_delay; //回声的延时时间 0-300ms
unsigned int echo_decayval; // 0-70%
};
u8 vol_table[] = {0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100};
static struct mic_effect_player *g_mic_effect_player = NULL;
static u16 mic_irq_point_unit = AUDIO_ADC_IRQ_POINTS;
void mic_effect_set_irq_point_unit(u16 point_unit)
{
mic_irq_point_unit = point_unit;
}
static void mic_effect_player_callback(void *private_data, int event)
{
struct mic_effect_player *player = g_mic_effect_player;
struct jlstream *stream = (struct jlstream *)private_data;
switch (event) {
case STREAM_EVENT_START:
char *vol_name = "VolEff";
struct volume_cfg cfg = {0};
cfg.bypass = VOLUME_NODE_CMD_SET_VOL;
cfg.cur_vol = app_var.mic_eff_volume;
jlstream_set_node_param(NODE_UUID_VOLUME_CTRLER, vol_name, (void *)&cfg, sizeof(struct volume_cfg));
break;
}
}
int mic_effect_player_open()
{
#if TCFG_APP_FM_EN
if (g_mic_effect_player || get_fm_scan_status()) { //fm搜台中不能开混响
#else
if (g_mic_effect_player) {
#endif
return 0;
}
mic_effect_ram_code_load();
int err;
struct mic_effect_player *player;
u16 uuid = jlstream_event_notify(STREAM_EVENT_GET_PIPELINE_UUID, (int)"mic_effect");
if (uuid == 0) {
return -EFAULT;
}
player = malloc(sizeof(*player));
if (!player) {
return -ENOMEM;
}
player->stream = jlstream_pipeline_parse_by_node_name(uuid, "IIS0_RX1");
if (!player->stream) {
player->stream = jlstream_pipeline_parse(uuid, NODE_UUID_ADC);
}
if (!player->stream) {
err = -ENOMEM;
goto __exit0;
}
//设置中断点数
jlstream_node_ioctl(player->stream, NODE_UUID_SOURCE, NODE_IOC_SET_PRIV_FMT, mic_irq_point_unit);
jlstream_node_ioctl(player->stream, NODE_UUID_VOCAL_TRACK_SYNTHESIS, NODE_IOC_SET_PRIV_FMT, mic_irq_point_unit);//四声道时,指定声道合并单个声道的点数
jlstream_set_callback(player->stream, player->stream, mic_effect_player_callback);
jlstream_set_scene(player->stream, STREAM_SCENE_MIC_EFFECT);
jlstream_add_thread(player->stream, "mic_effect1");
if (CONFIG_JLSTREAM_MULTI_THREAD_ENABLE) {
jlstream_add_thread(player->stream, "mic_effect2");
}
err = jlstream_start(player->stream);
if (err) {
goto __exit1;
}
//记录echo、Dvol节点的参数 供按键调节使用
echo_param_tool_set echo_cfg = {0};
char *node_name = "EchoEff"; //节点名称(节点内的第一参数,用户自定义,长度小于等于15byte)
int ret = jlstream_read_form_data(0, node_name, 0, &echo_cfg);
if (ret) {
printf("read echo parm delay %d\n", echo_cfg.parm.delay);
player->echo_delay = echo_cfg.parm.delay;
player->echo_decayval = echo_cfg.parm.decayval;
}
player->dvol = app_var.mic_eff_volume;
player->dvol_index = player->dvol / 10;
if (player->dvol_index >= sizeof(vol_table) / sizeof(vol_table[0])) {
player->dvol_index = sizeof(vol_table) / sizeof(vol_table[0]) - 1;
}
printf("\n mic dvol %d \n", player->dvol);
g_mic_effect_player = player;
return 0;
__exit1:
jlstream_release(player->stream);
__exit0:
free(player);
return err;
}
bool mic_effect_player_runing()
{
return g_mic_effect_player != NULL;
}
int mic_effect_player_is_playing()
{
return true;
}
void mic_effect_player_close()
{
struct mic_effect_player *player = g_mic_effect_player;
if (!player) {
return;
}
jlstream_stop(player->stream, 0);
jlstream_release(player->stream);
mic_effect_ram_code_unload();
free(player);
g_mic_effect_player = NULL;
jlstream_event_notify(STREAM_EVENT_CLOSE_PLAYER, (int)"mic_effect");
}
static u8 pause_mark = 0;
//混响暂停恢复接口
void mic_effect_player_pause(u8 mark)
{
if (mark) { //暂停
//混响在运行时才暂停(关闭)
if (mic_effect_player_runing()) {
mic_effect_player_close();
pause_mark = 1;
}
} else {
if (pause_mark) {
mic_effect_player_open();
}
pause_mark = 0;
}
}
#if defined(TCFG_CODE_RUN_RAM_MIC_EFF_CODE) && TCFG_CODE_RUN_RAM_MIC_EFF_CODE
static spinlock_t mic_eff_code_ram;
static u8 *mic_eff_code_run_addr = NULL;
extern u32 __mic_eff_movable_slot_start[];
extern u32 __mic_eff_movable_slot_end[];
extern u8 __mic_eff_movable_region_start[];
extern u8 __mic_eff_movable_region_end[];
//代码动态加载
static void mic_effect_ram_code_load()
{
int code_size = __mic_eff_movable_region_end - __mic_eff_movable_region_start;
//printf("mic_eff code size %d\n", code_size);
//mem_stats();
if (code_size && !mic_eff_code_run_addr) {
mic_eff_code_run_addr = phy_malloc(code_size);
}
spin_lock(&mic_eff_code_ram);
if (mic_eff_code_run_addr) {
//printf("mic_eff_code_run_addr: %x\n", (unsigned int)mic_eff_code_run_addr);
code_movable_load(__mic_eff_movable_region_start, code_size, mic_eff_code_run_addr, __mic_eff_movable_slot_start, __mic_eff_movable_slot_end);
}
spin_unlock(&mic_eff_code_ram);
}
static void mic_effect_ram_code_unload()
{
if (mic_eff_code_run_addr) {
//mem_stats();
spin_lock(&mic_eff_code_ram);
code_movable_unload(__mic_eff_movable_region_start, __mic_eff_movable_slot_start, __mic_eff_movable_slot_end);
spin_unlock(&mic_eff_code_ram);
phy_free(mic_eff_code_run_addr);
mic_eff_code_run_addr = NULL;
//mem_stats();
//printf("mic_eff code unload end\n");
}
}
#else
static void mic_effect_ram_code_load()
{
}
static void mic_effect_ram_code_unload()
{
}
#endif
//echo 调节接口
void mic_effect_set_echo_delay(u32 delay)
{
if (!g_mic_effect_player) {
return;
}
echo_param_tool_set cfg = {0};
/*
*解析配置文件内效果配置
* */
char mode_index = 0; //模式序号(当前节点无多参数组,mode_index是0
char *node_name = "EchoEff"; //节点名称(节点内的第一参数,用户自定义,长度小于等于15byte)
char cfg_index = 0; //目标配置项序号(当前节点无多参数组,cfg_index是0)
int ret = jlstream_read_form_data(mode_index, node_name, cfg_index, &cfg);
if (!ret) {
printf("read parm err\n");
return;
}
g_mic_effect_player->echo_delay = delay;
cfg.parm.delay = g_mic_effect_player->echo_delay;
/*
*将配置文件内获取得到的参数更新到目标节点
* */
jlstream_set_node_param(NODE_UUID_ECHO, node_name, &cfg, sizeof(cfg));
}
u32 mic_effect_get_echo_delay(void)
{
if (g_mic_effect_player) {
return g_mic_effect_player->echo_delay;
}
return 0;
}
//mic音量调节接口
void mic_effect_set_dvol(u8 vol)
{
char *vol_name = "VolEff";
struct volume_cfg cfg = {0};
cfg.bypass = VOLUME_NODE_CMD_SET_VOL;
cfg.cur_vol = vol;
if (g_mic_effect_player) {
jlstream_set_node_param(NODE_UUID_VOLUME_CTRLER, vol_name, (void *)&cfg, sizeof(struct volume_cfg));
g_mic_effect_player->dvol = vol;
app_var.mic_eff_volume = vol;
syscfg_write(CFG_MIC_EFF_VOLUME_INDEX, &app_var.mic_eff_volume, 2);
}
}
u8 mic_effect_get_dvol(void)
{
if (g_mic_effect_player) {
return g_mic_effect_player->dvol;
}
return 0;
}
void mic_effect_dvol_up(void)
{
if (g_mic_effect_player) {
if (g_mic_effect_player->dvol_index < sizeof(vol_table) / sizeof(vol_table[0]) - 1) {
g_mic_effect_player->dvol_index++;
mic_effect_set_dvol(vol_table[g_mic_effect_player->dvol_index]);
}
}
}
void mic_effect_dvol_down(void)
{
if (g_mic_effect_player) {
if (g_mic_effect_player->dvol_index) {
g_mic_effect_player->dvol_index--;
mic_effect_set_dvol(vol_table[g_mic_effect_player->dvol_index]);
}
}
}