KT25-0812_82A-UART/cpu/br25/audio_dec/audio_dec.c

1063 lines
28 KiB
C
Raw Normal View History

2025-08-12 10:09:23 +00:00
#include "asm/includes.h"
#include "media/includes.h"
#include "system/includes.h"
#include "classic/tws_api.h"
#include "classic/hci_lmp.h"
#include "effectrs_sync.h"
#include "application/audio_eq_drc_apply.h"
#include "app_config.h"
#include "audio_config.h"
#include "aec_user.h"
#include "audio_enc.h"
#include "audio_dec.h"
#include "app_main.h"
#include "encode/encode_write.h"
#include "audio_digital_vol.h"
#include "common/Resample_api.h"
#include "fm_emitter/fm_emitter_manage.h"
/* #include "asm/audio_spdif.h" */
#include "clock_cfg.h"
#include "audio_link.h"
/* #include "audio_reverb.h" */
#include "btstack/avctp_user.h"
#include "application/audio_output_dac.h"
#include "application/audio_energy_detect.h"
#include "application/audio_vocal_remove.h"
#include "application/audio_dig_vol.h"
#include "audio_dongle_codec.h"
#include "audio_sbc_codec.h"
#include "audio_iis.h"
#if (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_DONGLE)
void *dongle_digvol_last = NULL;
void *dongle_digvol_last_entry = NULL;
#endif
#if (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_IIS)
void *iis_digvol_last = NULL;
void *iis_digvol_last_entry = NULL;
struct audio_stream_entry *iis_last_entry = NULL;
#endif
#if (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_BT)
void *bt_digvol_last = NULL;
void *bt_digvol_last_entry = NULL;
#endif
#if TCFG_USER_TWS_ENABLE
#include "bt_tws.h"
#endif
#if AUDIO_OUTPUT_AUTOMUTE
void *mix_out_automute_hdl = NULL;
struct list_head *mix_out_automute_entry = NULL;
extern void mix_out_automute_open();
extern void mix_out_automute_close();
#endif
2025-08-27 16:29:07 +00:00
#define AUDIO_CODEC_SUPPORT_SYNC 1 // 同步
2025-08-12 10:09:23 +00:00
#if (RECORDER_MIX_EN)
2025-08-27 16:29:07 +00:00
#define MAX_SRC_NUMBER 4 // 最大支持src个数
2025-08-12 10:09:23 +00:00
#else
2025-08-27 16:29:07 +00:00
#define MAX_SRC_NUMBER 3 // 最大支持src个数
#endif /*RECORDER_MIX_EN*/
2025-08-12 10:09:23 +00:00
2025-08-27 16:29:07 +00:00
#define AUDIO_DECODE_TASK_WAKEUP_TIME 0 // 解码定时唤醒 // ms
2025-08-12 10:09:23 +00:00
//////////////////////////////////////////////////////////////////////////////
2025-08-27 16:29:07 +00:00
struct audio_decoder_task decode_task = {0};
struct audio_mixer mixer = {0};
2025-08-12 10:09:23 +00:00
/*struct audio_stream_dac_out *dac_last = NULL;*/
static u8 audio_dec_inited = 0;
struct audio_eq_drc *mix_eq_drc = NULL;
#if (TCFG_PREVENT_TASK_FILL)
struct prevent_task_fill *prevent_fill = NULL;
#endif
2025-08-27 16:29:07 +00:00
u8 audio_src_hw_filt[SRC_FILT_POINTS * SRC_CHI * 2 * MAX_SRC_NUMBER];
2025-08-12 10:09:23 +00:00
s16 mix_buff[AUDIO_MIXER_LEN / 2] SEC(.dec_mix_buff);
#if (RECORDER_MIX_EN)
struct audio_mixer recorder_mixer = {0};
s16 recorder_mix_buff[AUDIO_MIXER_LEN / 2] SEC(.dec_mix_buff);
2025-08-27 16:29:07 +00:00
#endif /*RECORDER_MIX_EN*/
2025-08-12 10:09:23 +00:00
#if (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_DAC)
#if AUDIO_CODEC_SUPPORT_SYNC
s16 dac_sync_buff[256];
#endif
#endif
#if AUDIO_VOCAL_REMOVE_EN
vocal_remove_hdl *mix_vocal_remove_hdl = NULL;
void *vocal_remove_open(u8 ch_num);
#endif
extern const int config_mixer_en;
2025-08-27 16:29:07 +00:00
#define AUDIO_DEC_MIXER_EN config_mixer_en
2025-08-12 10:09:23 +00:00
//////////////////////////////////////////////////////////////////////////////
void *mix_out_eq_drc_open(u16 sample_rate, u8 ch_num);
void mix_out_eq_drc_close(struct audio_eq_drc *eq_drc);
extern void audio_reverb_set_src_by_dac_sync(int in_rate, int out_rate);
extern void audio_linein_set_src_by_dac_sync(int in_rate, int out_rate);
extern void audio_usb_set_src_by_dac_sync(int in_rate, int out_rate);
//////////////////////////////////////////////////////////////////////////////
/*----------------------------------------------------------------------------*/
/**@brief 获取dac能量值
@param
@return
@note
*/
/*----------------------------------------------------------------------------*/
int audio_dac_energy_get(void)
{
#if AUDIO_OUTPUT_AUTOMUTE
int audio_energy_detect_energy_get(void *_hdl, u8 ch);
2025-08-27 16:29:07 +00:00
if (mix_out_automute_hdl)
{
2025-08-12 10:09:23 +00:00
return audio_energy_detect_energy_get(mix_out_automute_hdl, BIT(0));
}
return (-1);
#else
return 0;
#endif
}
//////////////////////////////////////////////////////////////////////////////
/*----------------------------------------------------------------------------*/
/**@brief 激活所有解码
@param
@return
@note
*/
/*----------------------------------------------------------------------------*/
void audio_resume_all_decoder(void)
{
audio_decoder_resume_all(&decode_task);
}
/*----------------------------------------------------------------------------*/
/**@brief src中断处理
@param
@return
@note
*/
/*----------------------------------------------------------------------------*/
void audio_src_isr_deal(void)
{
audio_resume_all_decoder();
}
/*----------------------------------------------------------------------------*/
/**@brief dac变采样处理同步
@param in_rate:
@param out_rate:
@return
@note
*/
/*----------------------------------------------------------------------------*/
void audio_dac_sync_src_deal(int in_rate, int out_rate)
{
#if TCFG_REVERB_ENABLE
audio_reverb_set_src_by_dac_sync(in_rate, out_rate);
#endif
#if TCFG_LINEIN_ENABLE
audio_linein_set_src_by_dac_sync(in_rate, out_rate);
#endif
#if TCFG_APP_PC_EN
#if TCFG_PC_ENABLE
audio_usb_set_src_by_dac_sync(in_rate, out_rate);
#endif
#endif
}
#if AUDIO_DECODE_TASK_WAKEUP_TIME
#include "timer.h"
/*----------------------------------------------------------------------------*/
/**@brief 解码定时处理
@param *priv:
@return
@note
*/
/*----------------------------------------------------------------------------*/
static void audio_decoder_wakeup_timer(void *priv)
{
2025-08-27 16:29:07 +00:00
// putchar('k');
2025-08-12 10:09:23 +00:00
audio_resume_all_decoder();
}
/*----------------------------------------------------------------------------*/
/**@brief 添加一个解码预处理
@param *task:
@return 0: ok
@note
*/
/*----------------------------------------------------------------------------*/
int audio_decoder_task_add_probe(struct audio_decoder_task *task)
{
2025-08-27 16:29:07 +00:00
if (task->wakeup_timer == 0)
{
2025-08-12 10:09:23 +00:00
task->wakeup_timer = sys_hi_timer_add(NULL, audio_decoder_wakeup_timer, AUDIO_DECODE_TASK_WAKEUP_TIME);
log_i("audio_decoder_task_add_probe:%d\n", task->wakeup_timer);
}
return 0;
}
/*----------------------------------------------------------------------------*/
/**@brief 删除一个解码预处理
@param *task:
@return 0: ok
@note
*/
/*----------------------------------------------------------------------------*/
int audio_decoder_task_del_probe(struct audio_decoder_task *task)
{
log_i("audio_decoder_task_del_probe\n");
2025-08-27 16:29:07 +00:00
if (audio_decoder_task_wait_state(task) > 0)
{
2025-08-12 10:09:23 +00:00
/*解码任务列表还有任务*/
return 0;
}
2025-08-27 16:29:07 +00:00
if (task->wakeup_timer)
{
2025-08-12 10:09:23 +00:00
log_i("audio_decoder_task_del_probe:%d\n", task->wakeup_timer);
sys_hi_timer_del(task->wakeup_timer);
task->wakeup_timer = 0;
}
return 0;
}
/*----------------------------------------------------------------------------*/
/**@brief 重定义唤醒时间
@param msecs: ms
@return 0: ok
@note
*/
/*----------------------------------------------------------------------------*/
int audio_decoder_wakeup_modify(int msecs)
{
2025-08-27 16:29:07 +00:00
if (decode_task.wakeup_timer)
{
2025-08-12 10:09:23 +00:00
sys_hi_timer_modify(decode_task.wakeup_timer, msecs);
}
return 0;
}
2025-08-27 16:29:07 +00:00
#endif /*AUDIO_DECODE_TASK_WAKEUP_TIME*/
2025-08-12 10:09:23 +00:00
/*----------------------------------------------------------------------------*/
/**@brief 各模式主解码open
@param state:
@return
@note
*/
/*----------------------------------------------------------------------------*/
void audio_mode_main_dec_open(u32 state)
{
#if 0
// 等待提示音解码完
tone_dec_wait_stop(200);
// 等待当前dac中的数据输出完
os_time_dly(audio_output_buf_time() / 10 + 1);
#endif
}
/*----------------------------------------------------------------------------*/
/**@brief 获取输出默认采样率
@param
@return 0:
@return 0:
@note
*/
/*----------------------------------------------------------------------------*/
u32 audio_output_nor_rate(void)
{
#if TCFG_IIS_ENABLE
return TCFG_IIS_OUTPUT_SR;
#endif
#if AUDIO_OUTPUT_INCLUDE_DAC
#if (TCFG_REVERB_ENABLE || TCFG_MIC_EFFECT_ENABLE)
return TCFG_REVERB_SAMPLERATE_DEFUAL;
#endif
/* return app_audio_output_samplerate_select(input_rate, 1); */
#elif (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_FM)
return 41667;
#else
return 44100;
#endif
/* #if TCFG_VIR_UDISK_ENABLE */
/* return 44100; */
/* #endif */
return 0;
}
/*----------------------------------------------------------------------------*/
/**@brief 获取输出采样率
@param input_rate:
@return
@note
*/
/*----------------------------------------------------------------------------*/
u32 audio_output_rate(int input_rate)
{
u32 out_rate = audio_output_nor_rate();
2025-08-27 16:29:07 +00:00
if (out_rate)
{
2025-08-12 10:09:23 +00:00
return out_rate;
}
#if (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_BT)
2025-08-27 16:29:07 +00:00
if (bt_user_priv_var.emitter_or_receiver == BT_EMITTER_EN)
{
2025-08-12 10:09:23 +00:00
y_printf("+++ \n");
return audio_sbc_enc_get_rate();
}
#elif (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_DONGLE)
return DONGLE_OUTPUT_SAMPLE_RATE;
#endif
#if (TCFG_REVERB_ENABLE || TCFG_MIC_EFFECT_ENABLE)
2025-08-27 16:29:07 +00:00
if (input_rate > 48000)
{
2025-08-12 10:09:23 +00:00
return 48000;
}
#endif
2025-08-27 16:29:07 +00:00
return app_audio_output_samplerate_select(input_rate, 1);
2025-08-12 10:09:23 +00:00
}
/*----------------------------------------------------------------------------*/
/**@brief 获取输出通道数
@param
@return
@note
*/
/*----------------------------------------------------------------------------*/
u32 audio_output_channel_num(void)
{
#if AUDIO_OUTPUT_INCLUDE_DAC
#if (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_BT)
2025-08-27 16:29:07 +00:00
if (bt_user_priv_var.emitter_or_receiver == BT_EMITTER_EN)
{
2025-08-12 10:09:23 +00:00
return audio_sbc_enc_get_channel_num();
}
#endif
/*根据DAC输出的方式选择输出的声道*/
2025-08-27 16:29:07 +00:00
u8 dac_connect_mode = app_audio_output_mode_get();
if (dac_connect_mode == DAC_OUTPUT_LR || dac_connect_mode == DAC_OUTPUT_DUAL_LR_DIFF)
{
2025-08-12 10:09:23 +00:00
return 2;
2025-08-27 16:29:07 +00:00
}
else
{
2025-08-12 10:09:23 +00:00
return 1;
}
#elif (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_FM)
2025-08-27 16:29:07 +00:00
return 2;
2025-08-12 10:09:23 +00:00
#else
2025-08-27 16:29:07 +00:00
return 2;
2025-08-12 10:09:23 +00:00
#endif
}
u32 audio_output_channel_type(void)
{
#if AUDIO_OUTPUT_INCLUDE_DAC
#if (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_BT)
2025-08-27 16:29:07 +00:00
if (bt_user_priv_var.emitter_or_receiver == BT_EMITTER_EN)
{
if (audio_sbc_enc_get_channel_num() == 2)
{
2025-08-12 10:09:23 +00:00
return AUDIO_CH_LR;
}
return AUDIO_CH_DIFF;
}
#endif
/*根据DAC输出的方式选择输出的声道*/
2025-08-27 16:29:07 +00:00
u8 dac_connect_mode = app_audio_output_mode_get();
if (dac_connect_mode == DAC_OUTPUT_LR || dac_connect_mode == DAC_OUTPUT_DUAL_LR_DIFF)
{
2025-08-12 10:09:23 +00:00
return AUDIO_CH_LR;
2025-08-27 16:29:07 +00:00
}
else if (dac_connect_mode == DAC_OUTPUT_MONO_L)
{
2025-08-12 10:09:23 +00:00
return AUDIO_CH_L;
2025-08-27 16:29:07 +00:00
}
else if (dac_connect_mode == DAC_OUTPUT_MONO_R)
{
2025-08-12 10:09:23 +00:00
return AUDIO_CH_R;
2025-08-27 16:29:07 +00:00
}
else
{
2025-08-12 10:09:23 +00:00
return AUDIO_CH_DIFF;
}
#elif (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_FM)
2025-08-27 16:29:07 +00:00
return AUDIO_CH_LR;
2025-08-12 10:09:23 +00:00
#else
2025-08-27 16:29:07 +00:00
return AUDIO_CH_LR;
2025-08-12 10:09:23 +00:00
#endif
}
/*----------------------------------------------------------------------------*/
/**@brief 设置输出音量状态
@param state:
@return 0: ok
@note
*/
/*----------------------------------------------------------------------------*/
int audio_output_set_start_volume(u8 state)
{
s16 vol_max = get_max_sys_vol();
2025-08-27 16:29:07 +00:00
if (state == APP_AUDIO_STATE_CALL)
{
2025-08-12 10:09:23 +00:00
vol_max = app_var.aec_dac_gain;
}
app_audio_state_switch(state, vol_max);
return 0;
}
/*----------------------------------------------------------------------------*/
/**@brief 开始音频输出
@param sample_rate:
@param reset_rate:
@return 0: ok
@note
*/
/*----------------------------------------------------------------------------*/
u8 audio_output_flag = 0;
int audio_output_start(u32 sample_rate, u8 reset_rate)
{
2025-08-27 16:29:07 +00:00
if (reset_rate)
{
2025-08-12 10:09:23 +00:00
app_audio_output_samplerate_set(sample_rate);
}
2025-08-27 16:29:07 +00:00
if (audio_output_flag)
{
2025-08-12 10:09:23 +00:00
return 0;
}
audio_output_flag = 1;
app_audio_output_start();
return 0;
}
/*----------------------------------------------------------------------------*/
/**@brief 关闭音频输出
@param
@return
@note
*/
/*----------------------------------------------------------------------------*/
void audio_output_stop(void)
{
audio_output_flag = 0;
app_audio_output_stop();
}
/*----------------------------------------------------------------------------*/
/**@brief 打开一个变采样通道
@param *priv: output回调私有句柄
@param *output_handler:
@param *channel:
@param *input_sample_rate:
@param *output_sample_rate:
@return
@note
*/
/*----------------------------------------------------------------------------*/
struct audio_src_handle *audio_hw_resample_open(void *priv,
2025-08-27 16:29:07 +00:00
int (*output_handler)(void *, void *, int),
u8 channel,
u16 input_sample_rate,
u16 output_sample_rate)
2025-08-12 10:09:23 +00:00
{
struct audio_src_handle *hdl;
hdl = zalloc(sizeof(struct audio_src_handle));
2025-08-27 16:29:07 +00:00
if (hdl)
{
2025-08-12 10:09:23 +00:00
audio_hw_src_open(hdl, channel, SRC_TYPE_RESAMPLE);
audio_hw_src_set_rate(hdl, input_sample_rate, output_sample_rate);
audio_src_set_output_handler(hdl, priv, output_handler);
}
return hdl;
}
/*----------------------------------------------------------------------------*/
/**@brief 关闭变采样
@param *hdl:
@return
@note
*/
/*----------------------------------------------------------------------------*/
void audio_hw_resample_close(struct audio_src_handle *hdl)
{
2025-08-27 16:29:07 +00:00
if (hdl)
{
2025-08-12 10:09:23 +00:00
audio_hw_src_stop(hdl);
audio_hw_src_close(hdl);
free(hdl);
}
}
/*----------------------------------------------------------------------------*/
/**@brief mixer事件处理
@param *mixer:
@param event:
@return
@note
*/
/*----------------------------------------------------------------------------*/
static void mixer_event_handler(struct audio_mixer *mixer, int event)
{
2025-08-27 16:29:07 +00:00
switch (event)
{
2025-08-12 10:09:23 +00:00
case MIXER_EVENT_OPEN:
2025-08-27 16:29:07 +00:00
if (audio_mixer_get_ch_num(mixer) >= 1)
{
2025-08-12 10:09:23 +00:00
clock_add_set(DEC_MIX_CLK);
}
break;
case MIXER_EVENT_CLOSE:
2025-08-27 16:29:07 +00:00
if (audio_mixer_get_ch_num(mixer) == 0)
{
2025-08-12 10:09:23 +00:00
clock_remove_set(DEC_MIX_CLK);
}
{
#if TCFG_REVERB_ENABLE
reset_reverb_src_out(audio_output_rate(audio_mixer_get_sample_rate(mixer)));
#endif
}
break;
case MIXER_EVENT_SR_CHANGE:
#if 0
y_printf("sr change:%d \n", mixer->sample_rate);
#endif
break;
}
}
/*----------------------------------------------------------------------------*/
/**@brief 检测mixer采样率支持
@param *mixer:
@param sr:
@return
@note
*/
/*----------------------------------------------------------------------------*/
static u32 audio_mixer_check_sr(struct audio_mixer *mixer, u32 sr)
{
2025-08-27 16:29:07 +00:00
return audio_output_rate(sr);
;
2025-08-12 10:09:23 +00:00
}
/*----------------------------------------------------------------------------*/
/**@brief 最后一级stream激活
@param *p:
@return
@note
*/
/*----------------------------------------------------------------------------*/
static void audio_last_out_stream_resume(void *p)
{
}
/*----------------------------------------------------------------------------*/
/**@brief 音频解码初始化
@param
@return
@note
*/
/*----------------------------------------------------------------------------*/
extern struct audio_dac_hdl dac_hdl;
int audio_dec_init()
{
int err;
printf("audio_dec_init\n");
err = audio_decoder_task_create(&decode_task, "audio_dec");
#if (TCFG_PREVENT_TASK_FILL)
prevent_fill = prevent_task_fill_create("prevent");
2025-08-27 16:29:07 +00:00
if (prevent_fill)
{
2025-08-12 10:09:23 +00:00
decode_task.prevent_fill = prevent_task_fill_ch_open(prevent_fill, 20);
}
#endif
app_audio_output_init();
/*硬件SRC模块滤波器buffer设置可根据最大使用数量设置整体buffer*/
audio_src_base_filt_init(audio_src_hw_filt, sizeof(audio_src_hw_filt));
2025-08-27 16:29:07 +00:00
if (!AUDIO_DEC_MIXER_EN)
{
2025-08-12 10:09:23 +00:00
goto __mixer_init_end;
}
audio_mixer_open(&mixer);
audio_mixer_set_event_handler(&mixer, mixer_event_handler);
audio_mixer_set_check_sr_handler(&mixer, audio_mixer_check_sr);
2025-08-27 16:29:07 +00:00
if (config_mixer_en)
{
2025-08-12 10:09:23 +00:00
/*初始化mix_buf的长度*/
audio_mixer_set_output_buf(&mixer, mix_buff, sizeof(mix_buff));
}
u8 ch_num = audio_output_channel_num();
audio_mixer_set_channel_num(&mixer, ch_num);
u32 sr = audio_output_nor_rate();
2025-08-27 16:29:07 +00:00
if (sr)
{
2025-08-12 10:09:23 +00:00
// 固定采样率输出
audio_mixer_set_sample_rate(&mixer, MIXER_SR_SPEC, sr);
}
struct audio_stream_entry *entries[8] = {NULL};
/*dac_last = audio_stream_dac_out_open();*/
mix_eq_drc = mix_out_eq_drc_open(sr, ch_num);
#if AUDIO_VOCAL_REMOVE_EN
mix_vocal_remove_hdl = vocal_remove_open(ch_num);
#endif
#if AUDIO_OUTPUT_AUTOMUTE
mix_out_automute_open();
#endif
// 数据流串联。可以在mixer和last中间添加其他的数据流比如eq等
u8 entry_cnt = 0;
entries[entry_cnt++] = &mixer.entry;
#if TCFG_EQ_ENABLE && TCFG_AUDIO_OUT_EQ_ENABLE
2025-08-27 16:29:07 +00:00
if (mix_eq_drc)
{
2025-08-12 10:09:23 +00:00
entries[entry_cnt++] = &mix_eq_drc->entry;
}
#endif
#if AUDIO_VOCAL_REMOVE_EN
2025-08-27 16:29:07 +00:00
if (mix_vocal_remove_hdl)
{
2025-08-12 10:09:23 +00:00
entries[entry_cnt++] = &mix_vocal_remove_hdl->entry;
}
#endif
#if AUDIO_OUTPUT_AUTOMUTE
entries[entry_cnt++] = mix_out_automute_entry;
#endif
/* #if (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_DAC) */
#if AUDIO_OUTPUT_INCLUDE_DAC
entries[entry_cnt++] = &dac_hdl.entry;
#endif
mixer.stream = audio_stream_open(NULL, audio_last_out_stream_resume);
audio_stream_add_list(mixer.stream, entries, entry_cnt);
/* #if (AUDIO_OUTPUT_WAY != AUDIO_OUTPUT_WAY_DAC) */
#if (!AUDIO_OUTPUT_INCLUDE_DAC)
entry_cnt++;
#endif
#if (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_IIS)
audio_dig_vol_param iis_digvol_last_param = {
.vol_start = app_var.music_volume,
.vol_max = SYS_MAX_VOL,
.ch_total = 2,
.fade_en = 1,
.fade_points_step = 5,
.fade_gain_step = 10,
.vol_list = NULL,
};
iis_digvol_last = audio_dig_vol_open(&iis_digvol_last_param);
iis_digvol_last_entry = audio_dig_vol_entry_get(iis_digvol_last);
iis_last_entry = audio_iis_output_start(0);
struct audio_stream_entry *iis_entries_start = entries[entry_cnt - 2];
entry_cnt = 0;
entries[entry_cnt++] = iis_entries_start;
entries[entry_cnt++] = iis_digvol_last_entry;
entries[entry_cnt++] = iis_last_entry;
2025-08-27 16:29:07 +00:00
for (int i = 0; i < entry_cnt - 1; i++)
{
2025-08-12 10:09:23 +00:00
audio_stream_add_entry(entries[i], entries[i + 1]);
}
#endif
#if (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_DONGLE)
/* #if 1 */
{
audio_dig_vol_param dongle_digvol_last_param = {
.vol_start = 30,
.vol_max = 30,
.ch_total = 2,
.fade_en = 1,
.fade_points_step = 5,
.fade_gain_step = 10,
.vol_list = NULL,
};
dongle_digvol_last = audio_dig_vol_open(&dongle_digvol_last_param);
dongle_digvol_last_entry = audio_dig_vol_entry_get(dongle_digvol_last);
}
audio_dongle_emitter_init();
struct audio_stream_entry *dongle_entries_start = entries[entry_cnt - 2];
entry_cnt = 0;
entries[entry_cnt++] = dongle_entries_start;
entries[entry_cnt++] = dongle_digvol_last_entry;
entries[entry_cnt++] = &dongle_emitter.mix_ch.entry;
2025-08-27 16:29:07 +00:00
for (int i = 0; i < entry_cnt - 1; i++)
{
2025-08-12 10:09:23 +00:00
audio_stream_add_entry(entries[i], entries[i + 1]);
}
#endif
#if (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_BT)
audio_dig_vol_param bt_digvol_last_param = {
.vol_start = app_var.music_volume,
.vol_max = SYS_MAX_VOL,
.ch_total = 2,
.fade_en = 1,
.fade_points_step = 5,
.fade_gain_step = 10,
.vol_list = NULL,
};
bt_digvol_last = audio_dig_vol_open(&bt_digvol_last_param);
bt_digvol_last_entry = audio_dig_vol_entry_get(bt_digvol_last);
audio_stream_add_entry(entries[entry_cnt - 2], bt_digvol_last_entry);
audio_sbc_emitter_init();
audio_stream_add_entry(bt_digvol_last_entry, &sbc_emitter.entry);
#endif
__mixer_init_end:
#if (RECORDER_MIX_EN)
recorder_mix_init(&recorder_mixer, recorder_mix_buff, sizeof(recorder_mix_buff));
2025-08-27 16:29:07 +00:00
#endif // RECORDER_MIX_EN
2025-08-12 10:09:23 +00:00
app_audio_volume_init();
audio_output_set_start_volume(APP_AUDIO_STATE_MUSIC);
#if TCFG_IIS_ENABLE
/* audio_link_init(); */
/* #if TCFG_IIS_OUTPUT_EN */
/* audio_link_open(TCFG_IIS_OUTPUT_PORT, ALINK_DIR_TX); */
/* #endif */
#endif
#if TCFG_SPDIF_ENABLE
spdif_init();
#endif
audio_dec_inited = 1;
return err;
}
/*----------------------------------------------------------------------------*/
/**@brief 音频解码初始化判断
@param
@return 1:
@return 0:
@note
*/
/*----------------------------------------------------------------------------*/
static u8 audio_dec_init_complete()
{
2025-08-27 16:29:07 +00:00
if (!audio_dec_inited)
{
2025-08-12 10:09:23 +00:00
return 0;
}
return 1;
}
REGISTER_LP_TARGET(audio_dec_init_lp_target) = {
.name = "audio_dec_init",
.is_idle = audio_dec_init_complete,
};
struct drc_ch high_bass_drc = {0};
static int high_bass_th = 0;
/*----------------------------------------------------------------------------*/
/**@brief 高低音限幅器系数回调
@param *drc:
@param *info:
@return
@note
*/
/*----------------------------------------------------------------------------*/
int high_bass_drc_set_filter_info(int th)
{
/* int th = 0; // -60 ~ 0 db */
2025-08-27 16:29:07 +00:00
if (th < -60)
{
2025-08-12 10:09:23 +00:00
th = -60;
}
2025-08-27 16:29:07 +00:00
if (th > 0)
{
2025-08-12 10:09:23 +00:00
th = 0;
}
local_irq_disable();
high_bass_th = th;
2025-08-27 16:29:07 +00:00
if (mix_eq_drc && mix_eq_drc->drc)
{
2025-08-12 10:09:23 +00:00
mix_eq_drc->drc->updata = 1;
}
local_irq_enable();
return 0;
}
/*----------------------------------------------------------------------------*/
/**@brief 高低音限幅器系数回调
@param *drc:
@param *info:
@return
@note
*/
/*----------------------------------------------------------------------------*/
int high_bass_drc_get_filter_info(struct audio_drc *drc, struct audio_drc_filter_info *info)
{
2025-08-27 16:29:07 +00:00
int th = high_bass_th; //-60 ~0db
2025-08-12 10:09:23 +00:00
int threshold = round(pow(10.0, th / 20.0) * 32768); // 0db:32768, -60db:33
high_bass_drc.nband = 1;
high_bass_drc.type = 1;
high_bass_drc._p.limiter[0].attacktime = 5;
high_bass_drc._p.limiter[0].releasetime = 300;
high_bass_drc._p.limiter[0].threshold[0] = threshold;
high_bass_drc._p.limiter[0].threshold[1] = 32768;
info->pch = info->R_pch = &high_bass_drc;
return 0;
}
/*----------------------------------------------------------------------------*/
/**@brief 高低音eq打开
@param sample_rate:
@param ch_num:
@return
@note
*/
/*----------------------------------------------------------------------------*/
void *mix_out_eq_drc_open(u16 sample_rate, u8 ch_num)
{
#if TCFG_EQ_ENABLE
struct audio_eq_drc *eq_drc = NULL;
struct audio_eq_drc_parm effect_parm = {0};
#if TCFG_AUDIO_OUT_EQ_ENABLE
effect_parm.high_bass = 1;
effect_parm.eq_en = 1;
#if TCFG_DRC_ENABLE
#if TCFG_AUDIO_OUT_DRC_ENABLE
effect_parm.drc_en = 1;
effect_parm.drc_cb = high_bass_drc_get_filter_info;
#endif
#endif
log_i("=====sr %d, ch_num %d\n", sample_rate, ch_num);
2025-08-27 16:29:07 +00:00
if (effect_parm.eq_en)
{
2025-08-12 10:09:23 +00:00
effect_parm.async_en = 1;
effect_parm.out_32bit = 1;
effect_parm.online_en = 0;
effect_parm.mode_en = 0;
}
effect_parm.eq_name = song_eq_mode;
#if TCFG_EQ_DIVIDE_ENABLE
effect_parm.divide_en = 1;
#endif
effect_parm.ch_num = ch_num;
effect_parm.sr = sample_rate;
printf("ch_num %d\n,sr %d\n", ch_num, sample_rate);
eq_drc = audio_eq_drc_open(&effect_parm);
clock_add(EQ_CLK);
2025-08-27 16:29:07 +00:00
if (effect_parm.drc_en)
{
2025-08-12 10:09:23 +00:00
clock_add(EQ_DRC_CLK);
}
#endif
return eq_drc;
#endif
return NULL;
}
/*----------------------------------------------------------------------------*/
/**@brief 高低音eq关闭
@param *eq_drc:
@return
@note
*/
/*----------------------------------------------------------------------------*/
void mix_out_eq_drc_close(struct audio_eq_drc *eq_drc)
{
#if TCFG_EQ_ENABLE
#if TCFG_AUDIO_OUT_EQ_ENABLE
2025-08-27 16:29:07 +00:00
if (eq_drc)
{
2025-08-12 10:09:23 +00:00
audio_eq_drc_close(eq_drc);
eq_drc = NULL;
clock_remove(EQ_CLK);
#if TCFG_DRC_ENABLE
#if TCFG_AUDIO_OUT_DRC_ENABLE
clock_remove(EQ_DRC_CLK);
#endif
#endif
}
#endif
#endif
return;
}
/*----------------------------------------------------------------------------*/
/**@brief mix out后 做高低音
@param cmd:AUDIO_EQ_HIGH ,AUDIO_EQ_BASS
@param hb:,0使125 125khz
@return
@note
*/
/*----------------------------------------------------------------------------*/
void mix_out_high_bass(u32 cmd, struct high_bass *hb)
{
2025-08-27 16:29:07 +00:00
if (mix_eq_drc)
{
2025-08-12 10:09:23 +00:00
audio_eq_drc_parm_update(mix_eq_drc, cmd, (void *)hb);
}
}
/*----------------------------------------------------------------------------*/
/**@brief mix out后 是否做高低音处理
@param cmd:AUDIO_EQ_HIGH_BASS_DIS
@param dis:0 1
@return
@note
*/
/*----------------------------------------------------------------------------*/
void mix_out_high_bass_dis(u32 cmd, u8 dis)
{
2025-08-27 16:29:07 +00:00
if (mix_eq_drc)
{
2025-08-12 10:09:23 +00:00
audio_eq_drc_parm_update(mix_eq_drc, cmd, (void *)dis);
}
}
#if AUDIO_OUTPUT_AUTOMUTE
2025-08-27 16:29:07 +00:00
#include "kt.h"
2025-08-12 10:09:23 +00:00
void audio_mix_out_automute_mute(u8 mute)
{
printf(">>>>>>>>>>>>>>>>>>>> %s\n", mute ? ("MUTE") : ("UNMUTE"));
2025-08-27 16:29:07 +00:00
if (mute)
{
2025-08-28 08:08:12 +00:00
//PA_MUTE();
2025-08-27 16:29:07 +00:00
}
else
{
2025-08-28 08:08:12 +00:00
//PA_UNMUTE();
2025-08-27 16:29:07 +00:00
}
2025-08-12 10:09:23 +00:00
}
/* #define AUDIO_E_DET_UNMUTE (0x00) */
/* #define AUDIO_E_DET_MUTE (0x01) */
void mix_out_automute_handler(u8 event, u8 ch)
{
printf(">>>> ch:%d %s\n", ch, event ? ("MUTE") : ("UNMUTE"));
2025-08-27 16:29:07 +00:00
if (ch == app_audio_output_channel_get())
{
2025-08-12 10:09:23 +00:00
audio_mix_out_automute_mute(event);
}
}
void mix_out_automute_skip(u8 skip)
{
u8 mute = !skip;
2025-08-27 16:29:07 +00:00
if (mix_out_automute_hdl)
{
2025-08-12 10:09:23 +00:00
audio_energy_detect_skip(mix_out_automute_hdl, 0xFFFF, skip);
audio_mix_out_automute_mute(mute);
}
}
void mix_out_automute_open()
{
2025-08-27 16:29:07 +00:00
if (mix_out_automute_hdl)
{
2025-08-12 10:09:23 +00:00
printf("mix_out_automute is already open !\n");
return;
}
audio_energy_detect_param e_det_param = {0};
e_det_param.mute_energy = 5;
e_det_param.unmute_energy = 10;
e_det_param.mute_time_ms = 1000;
e_det_param.unmute_time_ms = 50;
e_det_param.count_cycle_ms = 10;
e_det_param.sample_rate = 44100;
e_det_param.event_handler = mix_out_automute_handler;
e_det_param.ch_total = app_audio_output_channel_get();
e_det_param.dcc = 1;
mix_out_automute_hdl = audio_energy_detect_open(&e_det_param);
mix_out_automute_entry = audio_energy_detect_entry_get(mix_out_automute_hdl);
}
void mix_out_automute_close()
{
2025-08-27 16:29:07 +00:00
if (mix_out_automute_hdl)
{
2025-08-12 10:09:23 +00:00
audio_energy_detect_close(mix_out_automute_hdl);
}
}
2025-08-27 16:29:07 +00:00
#endif // #if AUDIO_OUTPUT_AUTOMUTE
2025-08-12 10:09:23 +00:00
#if AUDIO_VOCAL_REMOVE_EN
/*----------------------------------------------------------------------------*/
/**@brief 人声消除打开例子
@param ch_num:
@return
@note
*/
/*----------------------------------------------------------------------------*/
void *vocal_remove_open(u8 ch_num)
{
vocal_remove_hdl *hdl = NULL;
vocal_remove_open_parm parm = {0};
parm.channel = ch_num;
hdl = audio_vocal_remove_open(&parm);
return hdl;
}
/*----------------------------------------------------------------------------*/
/**@brief 人声消除关闭例子
@param
@return
@note
*/
/*----------------------------------------------------------------------------*/
void vocal_remove_close()
{
2025-08-27 16:29:07 +00:00
if (mix_vocal_remove_hdl)
{
2025-08-12 10:09:23 +00:00
audio_vocal_remove_close(mix_vocal_remove_hdl);
mix_vocal_remove_hdl = NULL;
}
}
#endif