#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]); } } }