KT24-1110_65E-HA-651B/cpu/br25/audio_dec/audio_dec.c

1155 lines
32 KiB
C
Raw Normal View History

2024-11-10 10:44:17 +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 "audio_effect/audio_eq_drc_demo.h"
#include "app_config.h"
#include "audio_config.h"
#include "audio_enc.h"
#include "audio_dec.h"
#include "app_main.h"
#include "audio_digital_vol.h"
/* #include "fm_emitter/fm_emitter_manage.h" */
/* #include "asm/audio_spdif.h" */
#include "clock_cfg.h"
#include "btstack/avctp_user.h"
#include "application/audio_output_dac.h"
#include "application/audio_energy_detect.h"
#include "application/audio_dig_vol.h"
#include "audio_dongle_codec.h"
#include "media/audio_equalloudness_eq.h"
#include "audio_spectrum.h"
#include "application/audio_vocal_remove.h"
#include "audio_effect/audio_sound_track_2_p_x.h"
#include "audio_utils.h"
#ifndef CONFIG_LITE_AUDIO
#include "aec_user.h"
#include "encode/encode_write.h"
#include "common/Resample_api.h"
#include "audio_link.h"
#include "audio_sbc_codec.h"
#if (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_FM)
#include "fm_emitter/fm_emitter_manage.h"
#endif
#include "audio_common/audio_iis.h"
#endif /*CONFIG_LITE_AUDIO*/
#if (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_DONGLE)
void *dongle_digvol_last = NULL;
void *dongle_digvol_last_entry = NULL;
#endif
#if (AUDIO_OUTPUT_INCLUDE_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
#define AUDIO_CODEC_SUPPORT_SYNC 1 // 同步
#define AUDIO_DECODE_TASK_WAKEUP_TIME 0 // 解码定时唤醒 // ms
//////////////////////////////////////////////////////////////////////////////
struct audio_decoder_task decode_task = {0};
struct audio_mixer mixer = {0};
#if TCFG_MIXER_CYCLIC_TASK_EN
struct audio_mixer_task mixer_task = {0};
#endif
#if TCFG_DEC2TWS_TASK_ENABLE
struct audio_decoder_task localtws_decode_task = {0};
#endif
u8 audio_dec_inited = 0;
#if AUDIO_EQUALLOUDNESS_CONFIG
loudness_hdl *loudness;
#endif
u8 audio_src_hw_filt[SRC_FILT_POINTS * SRC_CHI * 2 * MAX_SRC_NUMBER] ALIGNED(4); /*SRC的滤波器必须4个byte对齐*/
s16 mix_buff[AUDIO_MIXER_LEN / 2] SEC(.dec_mix_buff);
#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);
struct channel_switch *vocal_remove_mix_ch_switch = NULL;//声道变换,单声道时,先让解码出立体声,做完人声消除,再变单声道
#endif
extern const int config_mixer_en;
//////////////////////////////////////////////////////////////////////////////
#if AUDIO_SPECTRUM_CONFIG
extern spectrum_fft_hdl *spec_hdl;
#endif
//////////////////////////////////////////////////////////////////////////////
struct _audio_phase_inver_hdl {
struct audio_stream_entry entry; // 音频流入口
} audio_phase_inver_hdl;
static void audio_phase_inver_output_data_process_len(struct audio_stream_entry *entry, int len)
{
}
static int audio_phase_inver_data_handler(struct audio_stream_entry *entry,
struct audio_data_frame *in,
struct audio_data_frame *out)
{
struct _audio_phase_inver_hdl *hdl = container_of(entry, struct _audio_phase_inver_hdl, entry);
out->data_len = in->data_len;
out->data = in->data;
out->data_sync = in->data_sync;
out->channel = in->channel;
if (in->data_len - in->offset > 0) {
digital_phase_inverter_s16(in->data + in->offset / 2, in->data_len - in->offset);
}
return in->data_len;
}
//////////////////////////////////////////////////////////////////////////////
/*----------------------------------------------------------------------------*/
/**@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);
if (mix_out_automute_hdl) {
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);
#if TCFG_DEC2TWS_TASK_ENABLE
audio_decoder_resume_all(&localtws_decode_task);
#endif
}
#if AUDIO_DECODE_TASK_WAKEUP_TIME
#include "timer.h"
/*----------------------------------------------------------------------------*/
/**@brief 解码定时处理
@param *priv:
@return
@note
*/
/*----------------------------------------------------------------------------*/
static void audio_decoder_wakeup_timer(void *priv)
{
//putchar('k');
struct audio_decoder_task *task = priv;
audio_decoder_resume_all(task);
}
/*----------------------------------------------------------------------------*/
/**@brief 添加一个解码预处理
@param *task:
@return 0: ok
@note
*/
/*----------------------------------------------------------------------------*/
int audio_decoder_task_add_probe(struct audio_decoder_task *task)
{
if (task->wakeup_timer == 0) {
task->wakeup_timer = sys_hi_timer_add(task, 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");
if (audio_decoder_task_wait_state(task) > 0) {
/*解码任务列表还有任务*/
return 0;
}
if (task->wakeup_timer) {
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)
{
if (decode_task.wakeup_timer) {
sys_hi_timer_modify(decode_task.wakeup_timer, msecs);
}
return 0;
}
#endif/*AUDIO_DECODE_TASK_WAKEUP_TIME*/
/*----------------------------------------------------------------------------*/
/**@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
}
static u8 dac_fixed_16k = 0;
void set_fixed_dac_output_rate16K(u8 mark)
{
dac_fixed_16k = mark ? 1 : 0;
}
u8 get_t_fixed_dac_output_rate16k(void)
{
return dac_fixed_16k;
}
/*----------------------------------------------------------------------------*/
/**@brief 获取输出默认采样率
@param
@return 0:
@return 0:
@note
*/
/*----------------------------------------------------------------------------*/
u32 audio_output_nor_rate(void)
{
#if (TCFG_IIS_ENABLE && TCFG_IIS_OUTPUT_EN)
/* return 0; */
return TCFG_IIS_OUTPUT_SR;
#endif
#if TCFG_SPDIF_ENABLE
return 44100;
#endif
#if (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_DAC)
#if (TCFG_MIC_EFFECT_ENABLE)
if (dac_fixed_16k) {
return 16000;
} else {
return TCFG_REVERB_SAMPLERATE_DEFUAL;
}
#endif
/* return app_audio_output_samplerate_select(input_rate, 1); */
#elif (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_BT)
#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();
if (out_rate) {
return out_rate;
}
#if (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_BT)
if ((bt_user_priv_var.emitter_or_receiver == BT_EMITTER_EN) && (!bt_phone_dec_is_running())
&& (!bt_media_is_running())) {
y_printf("+++ \n");
return audio_sbc_enc_get_rate();
}
#elif (AUDIO_OUTPUT_WAY_DONGLE && AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_DONGLE)
return DONGLE_OUTPUT_SAMPLE_RATE;
#endif
#if (TCFG_MIC_EFFECT_ENABLE)
if (input_rate > 48000) {
return 48000;
}
#endif
return app_audio_output_samplerate_select(input_rate, 1);
}
/*----------------------------------------------------------------------------*/
/**@brief 获取输出通道数
@param
@return
@note
*/
/*----------------------------------------------------------------------------*/
u32 audio_output_channel_num(void)
{
#if AUDIO_OUTPUT_INCLUDE_DAC
/*根据DAC输出的方式选择输出的声道*/
u8 dac_connect_mode = app_audio_output_mode_get();
if (dac_connect_mode == DAC_OUTPUT_LR || dac_connect_mode == DAC_OUTPUT_DUAL_LR_DIFF) {
return 2;
} else {
#if AUDIO_VOCAL_REMOVE_EN
return 2;
#endif
return 1;
}
#elif (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_FM)
return 2;
#else
return 2;
#endif
}
/*----------------------------------------------------------------------------*/
/**@brief 获取输出通道类型
@param
@return
@note
*/
/*----------------------------------------------------------------------------*/
u32 audio_output_channel_type(void)
{
#if AUDIO_OUTPUT_INCLUDE_DAC
/*根据DAC输出的方式选择输出的声道*/
u8 dac_connect_mode = app_audio_output_mode_get();
if (dac_connect_mode == DAC_OUTPUT_LR || dac_connect_mode == DAC_OUTPUT_DUAL_LR_DIFF) {
return AUDIO_CH_LR;
} else if (dac_connect_mode == DAC_OUTPUT_MONO_L) {
return AUDIO_CH_DIFF; //要输出左右合成的单声道数据选这个
/* return AUDIO_CH_L; */ //只要输出左声道的数据选这个
} else if (dac_connect_mode == DAC_OUTPUT_MONO_R) {
return AUDIO_CH_DIFF; //要输出左右合成的单声道数据选这个
/* return AUDIO_CH_R; */ //只要输出右声道的数据选这个
} else {
return AUDIO_CH_DIFF;
}
#elif (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_FM)
return AUDIO_CH_LR;
#else
return AUDIO_CH_LR;
#endif
}
/*----------------------------------------------------------------------------*/
/**@brief 设置输出音量状态
@param state:
@return 0: ok
@note
*/
/*----------------------------------------------------------------------------*/
int audio_output_set_start_volume(u8 state)
{
s16 vol_max = get_max_sys_vol();
if (state == APP_AUDIO_STATE_CALL) {
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)
{
if (reset_rate) {
app_audio_output_samplerate_set(sample_rate);
}
if (audio_output_flag) {
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,
int (*output_handler)(void *, void *, int),
u8 channel,
u16 input_sample_rate,
u16 output_sample_rate)
{
struct audio_src_handle *hdl;
hdl = zalloc(sizeof(struct audio_src_handle));
if (hdl) {
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)
{
if (hdl) {
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)
{
switch (event) {
case MIXER_EVENT_OPEN:
if (audio_mixer_get_ch_num(mixer) >= 1) {
clock_add_set(DEC_MIX_CLK);
}
break;
case MIXER_EVENT_CLOSE:
if (audio_mixer_get_ch_num(mixer) == 0) {
clock_remove_set(DEC_MIX_CLK);
}
if (config_mixer_en) {
os_mutex_pend(&mixer->mutex, 0);
if (audio_mixer_get_active_ch_num(mixer) == 0) {
/*输出通道可以进行stop处理*/
audio_mixer_output_stop(mixer);
//通道关闭时清掉节点记录的偏移防止下个解码打开时mix之后的同步节点断言
audio_stream_clear_from(&mixer->entry);
}
os_mutex_post(&mixer->mutex);
}
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)
{
return audio_output_rate(sr);;
}
/*----------------------------------------------------------------------------*/
/**@brief 重新设置mixer采样率
@param sr:
@return
@note
*/
/*----------------------------------------------------------------------------*/
void audio_mixer_reset_sample_rate(u32 sr)
{
audio_mixer_set_sample_rate(&mixer, MIXER_SR_SPEC, sr);
}
/*----------------------------------------------------------------------------*/
/**@brief audio解码任务cpu跟踪回调
@param idle_total
@return
@note
*/
/*----------------------------------------------------------------------------*/
int audio_dec_occupy_trace_hdl(void *priv, u32 idle_total)
{
struct audio_decoder_occupy *occupy = priv;
if (idle_total < occupy->idle_expect) {
if (occupy->pend_time) {
os_time_dly(occupy->pend_time);
}
}
return 0;
}
extern void audio_adda_gain_dump(void);//打印所有adc,dac的增益
/*音频配置实时跟踪可以用来查看ADC/DAC增益或者其他寄存器配置*/
static void audio_config_trace(void *priv)
{
printf(">>Audio_Config_Trace:\n");
//audio_adda_gain_dump();
//audio_adda_dump();
//mem_stats();
}
/*----------------------------------------------------------------------------*/
/**@brief 音频解码初始化
@param
@return
@note
*/
/*----------------------------------------------------------------------------*/
extern struct audio_dac_hdl dac_hdl;
struct audio_dac_channel default_dac = {0};
int audio_dec_init()
{
int err;
printf("audio_dec_init\n");
// 创建解码任务
err = audio_decoder_task_create(&decode_task, "audio_dec");
#if TCFG_AUDIO_DECODER_OCCUPY_TRACE
decode_task.occupy.pend_time = 1;
decode_task.occupy.idle_expect = 4;
decode_task.occupy.trace_period = 200;
//decode_task.occupy.trace_hdl = audio_dec_occupy_trace_hdl;
#endif/*TCFG_AUDIO_DECODER_OCCUPY_TRACE*/
#if TCFG_AUDIO_DEC_OUT_TASK
audio_decoder_out_task_create(&decode_task, "audio_out");
#endif
#if TCFG_DEC2TWS_TASK_ENABLE
// 创建本地转发解码任务
audio_decoder_task_create(&localtws_decode_task, "local_dec");
#endif
// 初始化音频输出
app_audio_output_init();
#if TCFG_KEY_TONE_EN
// 按键音初始化
audio_key_tone_init();
#endif
#if SYS_DIGVOL_GROUP_EN
sys_digvol_group_open();
#endif // SYS_DIGVOL_GROUP_EN
/*硬件SRC模块滤波器buffer设置可根据最大使用数量设置整体buffer*/
audio_src_base_filt_init(audio_src_hw_filt, sizeof(audio_src_hw_filt));
if (!AUDIO_DEC_MIXER_EN) {
#if AUDIO_OUTPUT_INCLUDE_DAC
// 创建dac通道
audio_dac_new_channel(&dac_hdl, &default_dac);
struct audio_dac_channel_attr attr;
audio_dac_channel_get_attr(&default_dac, &attr);
attr.delay_time = 50;
attr.protect_time = 5;
attr.write_mode = WRITE_MODE_BLOCK;
audio_dac_channel_set_attr(&default_dac, &attr);
#endif
goto __mixer_init_end;
}
// 初始化mixer
audio_mixer_open(&mixer);
// 使能mixer事件回调
audio_mixer_set_event_handler(&mixer, mixer_event_handler);
// 使能mixer采样率检测
audio_mixer_set_check_sr_handler(&mixer, audio_mixer_check_sr);
if (config_mixer_en) {
/*初始化mix_buf的长度*/
audio_mixer_set_output_buf(&mixer, mix_buff, sizeof(mix_buff));
#ifdef CONFIG_MIXER_CYCLIC
#define MIXER_MIN_LEN (128*4*2)
// 设置mixer最小输出长度
audio_mixer_set_min_len(&mixer, sizeof(mix_buff) < (MIXER_MIN_LEN * 2) ? (sizeof(mix_buff) / 2) : MIXER_MIN_LEN);
#endif
}
// 获取音频输出声道数
u8 ch_num = audio_output_channel_num();
// 设置mixer输出声道数
audio_mixer_set_channel_num(&mixer, ch_num);
// 检测音频输出采样率是否为固定输出
u32 sr = audio_output_nor_rate();
if (sr) {
// 固定采样率输出
audio_mixer_set_sample_rate(&mixer, MIXER_SR_SPEC, sr);
}
#ifdef CONFIG_MIXER_CYCLIC
#if TCFG_MIXER_CYCLIC_TASK_EN
// mixer使用单独task输出
audio_mixer_task_init(&mixer_task, "mix_out");
audio_mixer_task_ch_open(&mixer, &mixer_task);
#endif
#endif
struct audio_stream_entry *entries[8] = {NULL};
#if AUDIO_OUTPUT_AUTOMUTE
// 自动mute
mix_out_automute_open();
#endif
#if AUDIO_SPECTRUM_CONFIG
//频响能量值获取接口
spec_hdl = spectrum_open_demo(sr, ch_num);
#endif
#if AUDIO_EQUALLOUDNESS_CONFIG
if (ch_num != 4) {
loudness_open_parm parm = {0};
parm.sr = sr;
parm.ch_num = ch_num;
parm.threadhold_vol = LOUDNESS_THREADHOLD_VOL;
parm.vol_cb = vol_get_test;
loudness = audio_equal_loudness_open(&parm);//不支持四声道
}
#endif
#if AUDIO_VOCAL_REMOVE_EN
mix_vocal_remove_hdl = vocal_remove_open(ch_num);
u8 dac_connect_mode = app_audio_output_mode_get();
if ((dac_connect_mode == DAC_OUTPUT_MONO_L)
|| (dac_connect_mode == DAC_OUTPUT_MONO_R)
|| (dac_connect_mode == DAC_OUTPUT_MONO_LR_DIFF)) {
vocal_remove_mix_ch_switch = channel_switch_open(AUDIO_CH_DIFF, 512);
}
#endif
// 数据流串联。可以在mixer和last中间添加其他的数据流比如eq等
u8 entry_cnt = 0;
entries[entry_cnt++] = &mixer.entry;
#if TCFG_DIG_PHASE_INVERTER_EN
audio_phase_inver_hdl.entry.data_process_len = audio_phase_inver_output_data_process_len;
audio_phase_inver_hdl.entry.data_handler = audio_phase_inver_data_handler;
entries[entry_cnt++] = &(audio_phase_inver_hdl.entry);
#endif/*TCFG_DIG_PHASE_INVERTER_EN*/
#if AUDIO_EQUALLOUDNESS_CONFIG
if (loudness) {
entries[entry_cnt++] = &loudness->loudness->entry;
}
#endif
#if AUDIO_SPECTRUM_CONFIG
if (spec_hdl) {
entries[entry_cnt++] = &spec_hdl->entry;
}
#endif
#if AUDIO_VOCAL_REMOVE_EN
if (mix_vocal_remove_hdl) {
entries[entry_cnt++] = &mix_vocal_remove_hdl->entry;
}
if (vocal_remove_mix_ch_switch) {
entries[entry_cnt++] = &vocal_remove_mix_ch_switch->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
// 创建dac通道
audio_dac_new_channel(&dac_hdl, &default_dac);
struct audio_dac_channel_attr attr;
audio_dac_channel_get_attr(&default_dac, &attr);
attr.delay_time = 50;
attr.protect_time = 5;
attr.write_mode = WRITE_MODE_BLOCK;
audio_dac_channel_set_attr(&default_dac, &attr);
entries[entry_cnt++] = &default_dac.entry;
/*entries[entry_cnt++] = &dac_hdl.entry;*/
#endif
// 创建数据流,把所有节点连接起来
mixer.stream = audio_stream_open(&mixer, audio_mixer_stream_resume);
audio_stream_add_list(mixer.stream, entries, entry_cnt);
#if (!AUDIO_OUTPUT_INCLUDE_DAC)
entry_cnt++;
#endif
#if AUDIO_OUTPUT_INCLUDE_IIS
// 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(TCFG_IIS_OUTPUT_PORT, TCFG_IIS_OUTPUT_DATAPORT_SEL);
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;
for (int i = 0; i < entry_cnt - 1; i++) {
audio_stream_add_entry(entries[i], entries[i + 1]);
}
#endif
#if (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_DONGLE)
// 蓝牙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;
for (int i = 0; i < entry_cnt - 1; i++) {
audio_stream_add_entry(entries[i], entries[i + 1]);
}
#endif
#if (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_BT)
// 蓝牙发射。从倒数第二个节点分流
extern int audio_data_set_zero(struct audio_stream_entry * entry, struct audio_data_frame * data_buf);
default_dac.entry.prob_handler = audio_data_set_zero;
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
#if (RECORDER_MIX_EN)
// 录音
recorder_mix_audio_stream_entry_add(entries[entry_cnt - 2]);
#endif
__mixer_init_end:
// 音频音量初始化
app_audio_volume_init();
audio_output_set_start_volume(APP_AUDIO_STATE_MUSIC);
#if AUDIO_OUTPUT_INCLUDE_DAC
/* 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音频
spdif_init();
#endif
audio_dec_inited = 1;
#if (TCFG_MIC_EFFECT_ENABLE && TCFG_MIC_EFFECT_START_DIR)
mic_effect_start();
#endif
#if TCFG_AUDIO_CONFIG_TRACE
sys_timer_add(NULL, audio_config_trace, 3000);
#endif/*TCFG_AUDIO_CONFIG_TRACE*/
#if TCFG_EQ_ENABLE
#if defined(TCFG_DRC_ENABLE) && TCFG_DRC_ENABLE
audio_drc_code_movable_load();//加载代码到ram
#endif
#endif
return err;
}
/*----------------------------------------------------------------------------*/
/**@brief 音频解码初始化判断
@param
@return 1:
@return 0:
@note
*/
/*----------------------------------------------------------------------------*/
static u8 audio_dec_init_complete()
{
/*不支持Audio功能返回idle*/
#if (defined TCFG_AUDIO_ENABLE && (TCFG_AUDIO_ENABLE == 0))
return 1;
#endif/*TCFG_AUDIO_ENABLE*/
if (!audio_dec_inited) {
return 0;
}
return 1;
}
REGISTER_LP_TARGET(audio_dec_init_lp_target) = {
.name = "audio_dec_init",
.is_idle = audio_dec_init_complete,
};
#if AUDIO_OUTPUT_AUTOMUTE
void audio_mix_out_automute_mute(u8 mute)
{
printf(">>>>>>>>>>>>>>>>>>>> %s\n", mute ? ("MUTE") : ("UNMUTE"));
}
/* #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"));
if (ch == app_audio_output_channel_get()) {
audio_mix_out_automute_mute(event);
}
}
void mix_out_automute_skip(u8 skip)
{
u8 mute = !skip;
if (mix_out_automute_hdl) {
audio_energy_detect_skip(mix_out_automute_hdl, 0xFFFF, skip);
audio_mix_out_automute_mute(mute);
}
}
void mix_out_automute_open()
{
if (mix_out_automute_hdl) {
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()
{
if (mix_out_automute_hdl) {
audio_energy_detect_close(mix_out_automute_hdl);
}
}
#endif //#if AUDIO_OUTPUT_AUTOMUTE
/*****************************************************************************
*
*
*
****************************************************************************/
#if SYS_DIGVOL_GROUP_EN
char *music_dig_logo[] = {
"music_a2dp",
"music_file",
"music_fm",
"music_linein",
"music_pc",
"NULL"
};
void *sys_digvol_group = NULL;
int sys_digvol_group_open(void)
{
if (sys_digvol_group == NULL) {
sys_digvol_group = audio_dig_vol_group_open();
return 0;
}
return -1;
}
int sys_digvol_group_close(void)
{
if (sys_digvol_group != NULL) {
return audio_dig_vol_group_close(sys_digvol_group);
}
return -1;
}
// 根据每个解码通道的logo来决定启动时候的数字音量等级
u16 __attribute__((weak)) get_ch_digvol_start(char *logo)
{
#if 0
if (!strcmp(logo, "music_a2dp")) {
return 100;
} else if (!strcmp(logo, "music_fm")) {
return 100;
}
#endif
return get_max_sys_vol();
}
/*******************************************************
* Function name : sys_digvol_group_ch_open
* Description :
* Parameter :
* @logo
* @vol_start , -1 get_ch_digvol_start
* Return : digvol audio stream entry
*******************************************************/
void *sys_digvol_group_ch_open(char *logo, int vol_start, audio_dig_vol_param *parm)
{
if (sys_digvol_group == NULL || logo == NULL) {
return NULL;
}
if (vol_start == -1) {
vol_start = get_ch_digvol_start(logo);
}
audio_dig_vol_param temp_digvol_param = {
.vol_start = vol_start,
.vol_max = get_max_sys_vol(),
.ch_total = 2,
.fade_en = 1,
.fade_points_step = 5,
.fade_gain_step = 10,
.vol_list = NULL,
};
if (parm == NULL) {
parm = &temp_digvol_param;
}
void *digvol_hdl = audio_dig_vol_open(parm);
if (digvol_hdl) {
audio_dig_vol_group_add(sys_digvol_group, digvol_hdl, logo);
return audio_dig_vol_entry_get(digvol_hdl);
}
return NULL;
}
int sys_digvol_group_ch_close(char *logo)
{
if (sys_digvol_group == NULL || logo == NULL) {
return -1;
}
void *hdl = audio_dig_vol_group_hdl_get(sys_digvol_group, logo);
if (hdl != NULL) {
void *entry = audio_dig_vol_entry_get(hdl);
if (entry != NULL) {
audio_stream_del_entry(entry);
}
}
audio_dig_vol_close(audio_dig_vol_group_hdl_get(sys_digvol_group, logo));
audio_dig_vol_group_del(sys_digvol_group, logo);
return 0;
}
#endif // SYS_DIGVOL_GROUP_EN
#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()
{
if (mix_vocal_remove_hdl) {
audio_vocal_remove_close(mix_vocal_remove_hdl);
mix_vocal_remove_hdl = NULL;
}
}
#endif