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
|