AC63_BT_SDK/cpu/br30/audio_dec.c
2025-02-18 15:40:42 +08:00

3530 lines
93 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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/eq_config.h"
#include "application/audio_energy_detect.h"
#include "application/audio_surround.h"
#include "app_config.h"
#include "audio_config.h"
#include "aec_user.h"
#include "audio_enc.h"
#include "app_main.h"
#include "btstack/avctp_user.h"
#include "btstack/a2dp_media_codec.h"
#include "tone_player.h"
#include "application/audio_vbass.h"
#include "audio_iis.h"
#include "math.h"
#include "audio_syncts.h"
#include "media/bt_audio_timestamp.h"
#include "media/a2dp_sample_detect.h"
#include "audio_codec_clock.h"
#include "audio_dec_eff.h"
#include "audio_utils.h"
#include "audio_dec_mic2pcm.h"
#if TCFG_USER_TWS_ENABLE
#include "bt_tws.h"
#endif/*TCFG_USER_TWS_ENABLE*/
#if (SYS_VOL_TYPE == VOL_TYPE_DIGITAL)
#include "audio_digital_vol.h"
#endif/*VOL_TYPE_DIGITAL*/
#include "audio_plc.h"
/*限幅器/噪声门限*/
#if TCFG_AUDIO_NOISE_GATE
#include "audio_noise_gate.h"
/*限幅器上限*/
#define LIMITER_THR -10000 /*-12000 = -12dB,放大1000倍,(-10000参考)*/
/*小于CONST_NOISE_GATE的当成噪声处理*/
#define LIMITER_NOISE_GATE -40000 /*-12000 = -12dB,放大1000倍,(-30000参考)*/
/*低于噪声门限阈值的增益 */
#define LIMITER_NOISE_GAIN (0 << 30) /*(0~1)*2^30*/
#endif/*TCFG_AUDIO_NOISE_GATE*/
#if TCFG_AUDIO_ANC_ENABLE
#include "audio_anc.h"
#endif/*TCFG_AUDIO_ANC_ENABLE*/
#if TCFG_APP_FM_EMITTER_EN
#include "fm_emitter/fm_emitter_manage.h"
#endif/*TCFG_APP_FM_EMITTER_EN*/
#include "phone_message/phone_message.h"
#define AUDIO_CODEC_SUPPORT_SYNC 1
#define A2DP_AUDIO_PLC_ENABLE 1
#if A2DP_AUDIO_PLC_ENABLE
#include "media/tech_lib/LFaudio_plc_api.h"
#endif
#define A2DP_RX_AND_AUDIO_DELAY 1
#define ESCO_DRC_EN 0 //通话下行增加限幅器处理,默认关闭
#if (!TCFG_DRC_ENABLE || !TCFG_PHONE_EQ_ENABLE)
#undef ESCO_DRC_EN 0
#define ESCO_DRC_EN 0
#endif
#if AUDIO_OUT_EFFECT_ENABLE
int audio_out_effect_open(void *priv, u16 sample_rate);
void audio_out_effect_close(void);
int audio_out_effect_stream_clear();
struct dec_eq_drc *audio_out_effect = NULL;
#endif /*AUDIO_OUT_EFFECT_ENABLE*/
static u8 audio_out_effect_dis = 0;
struct tone_dec_hdl {
struct audio_decoder decoder;
void (*handler)(void *, int argc, int *argv);
void *priv;
};
struct a2dp_dec_hdl {
struct audio_decoder decoder;
struct audio_res_wait wait;
struct audio_mixer_ch mix_ch;
enum audio_channel channel;
u8 start;
u8 ch;
s16 header_len;
u8 remain;
u8 fetch_lock;
u8 preempt;
u8 stream_error;
u8 new_frame;
u8 repair;
void *sample_detect;
void *syncts;
void *repair_pkt;
s16 repair_pkt_len;
u16 missed_num;
u16 repair_frames;
u16 overrun_seqn;
u16 slience_frames;
#if AUDIO_CODEC_SUPPORT_SYNC
u8 ts_start;
u8 sync_step;
void *ts_handle;
u32 timestamp;
u32 base_time;
#endif /*AUDIO_CODEC_SUPPORT_SYNC*/
#if A2DP_AUDIO_PLC_ENABLE
LFaudio_PLC_API *plc_ops;
void *plc_mem;
#endif /*A2DP_AUDIO_PLC_ENABLE*/
u32 mix_ch_event_params[3];
u32 pending_time;
u16 seqn;
u16 sample_rate;
int timer;
u32 coding_type;
u16 delay_time;
u16 detect_timer;
u8 underrun_feedback;
#if TCFG_EQ_ENABLE&&TCFG_BT_MUSIC_EQ_ENABLE
struct dec_eq_drc *eq_drc;
#endif//TCFG_BT_MUSIC_EQ_ENABLE
#if (SYS_VOL_TYPE == VOL_TYPE_DIGITAL)
dvol_handle *dvol;
#endif
#if AUDIO_SURROUND_CONFIG
struct dec_sur *sur;
#endif//AUDIO_SURROUND_CONFIG
#if AUDIO_VBASS_CONFIG
vbass_hdl *vbass; //虚拟低音句柄
#endif
};
#if AUDIO_SURROUND_CONFIG
static u8 a2dp_surround_eff; //音效模式记录
void a2dp_surround_set(u8 eff)
{
a2dp_surround_eff = eff;
}
#endif
struct esco_dec_hdl {
struct audio_decoder decoder;
struct audio_res_wait wait;
struct audio_mixer_ch mix_ch;
u32 coding_type;
u8 *frame;
u8 frame_len;
u8 offset;
u8 data_len;
u8 tws_mute_en;
u8 start;
u8 enc_start;
u8 frame_time;
u8 preempt;
u16 slience_frames;
void *syncts;
#if AUDIO_CODEC_SUPPORT_SYNC
void *ts_handle;
u8 ts_start;
u8 sync_step;
u8 preempt_state;
#endif
u32 mix_ch_event_params[3];
u8 esco_len;
u16 remain;
int data[15];/*ALIGNED(4)*/
#if (SYS_VOL_TYPE == VOL_TYPE_DIGITAL)
dvol_handle *dvol;
#endif
u32 hash;
#if TCFG_EQ_ENABLE&&TCFG_PHONE_EQ_ENABLE
struct dec_eq_drc *eq_drc;
#endif//TCFG_PHONE_EQ_ENABLE
};
#if AUDIO_OUTPUT_AUTOMUTE
void *mix_out_automute_hdl = NULL;
extern void mix_out_automute_open();
extern void mix_out_automute_close();
#endif //#if AUDIO_OUTPUT_AUTOMUTE
void *audio_sync = NULL;
#if (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_LR)
#define MIX_POINTS_NUM 256
#else
#define MIX_POINTS_NUM 128
#endif
#if A2DP_RX_AND_AUDIO_DELAY
#define AUDIO_DAC_DELAY_TIME 30
#else
#define AUDIO_DAC_DELAY_TIME 50
#endif
/*播歌过程,语音识别的数据做回音消除*/
#define A2DP_KSR_AEC_ENABLE 0
#define A2DP_TO_PCM_DEVICE_FORMAT 0//48000
#if (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_LR)
s16 dac_buff[4 * 1024];
#else
#if A2DP_KSR_AEC_ENABLE
#undef A2DP_TO_PCM_DEVICE_FORMAT
#define A2DP_TO_PCM_DEVICE_FORMAT 48000
s16 dac_buff[4 * 1024 - 512];
#else
s16 dac_buff[2 * 1024 - 512];
#endif/*A2DP_KSR_AEC_ENABLE*/
#endif/*TCFG_AUDIO_DAC_CONNECT_MODE*/
#if AUDIO_CODEC_SUPPORT_SYNC
#define DEC_RUN_BY_ITSELF 0
#define DEC_PREEMTED_BY_PRIORITY 1
#define DEC_PREEMTED_BY_OUTSIDE 3
#define DEC_RESUME_BY_OUTSIDE 2
/* [>AAC解码需要加大同步和MIX的buffer用来提高异步效率<] */
s16 dac_sync_filt[24 * 2 * 2];
#endif
s16 mix_buff[MIX_POINTS_NUM];
#define MAX_SRC_NUMBER 3
s16 audio_src_hw_filt[24 * 2 * MAX_SRC_NUMBER];
#define A2DP_TO_PCM_DEVICE_FORMAT 0//48000
#define A2DP_FLUENT_STREAM_MODE 1//流畅模式
#define A2DP_FLUENT_DETECT_INTERVAL 100000//ms 流畅播放延时检测时长
#if A2DP_FLUENT_STREAM_MODE
#define A2DP_MAX_PENDING_TIME 120
#else
#define A2DP_MAX_PENDING_TIME 40
#endif
#define A2DP_STREAM_NO_ERR 0
#define A2DP_STREAM_UNDERRUN 1
#define A2DP_STREAM_OVERRUN 2
#define A2DP_STREAM_MISSED 3
#define A2DP_STREAM_DECODE_ERR 4
#define A2DP_STREAM_LOW_UNDERRUN 5
/*OS_SEM dac_sem;*/
static u16 dac_idle_delay_max = 10000;
static u16 dac_idle_delay_cnt = 10000;
static struct tone_dec_hdl *tone_dec = NULL;
struct audio_decoder_task decode_task;
struct audio_dac_hdl dac_hdl;
struct audio_mixer mixer;
extern struct dac_platform_data dac_data;
extern struct audio_adc_hdl adc_hdl;
static u16 a2dp_delay_time;
static u8 a2dp_low_latency = 0;
static u16 drop_a2dp_timer;
static u16 a2dp_low_latency_seqn = 0;
extern const int CONFIG_LOW_LATENCY_ENABLE;
extern const int CONFIG_A2DP_DELAY_TIME;
extern const int CONFIG_A2DP_DELAY_TIME_LO;
extern const int CONFIG_A2DP_SBC_DELAY_TIME_LO;
extern const int const_surround_en;
struct a2dp_dec_hdl *a2dp_dec = NULL;
struct esco_dec_hdl *esco_dec = NULL;
extern int platform_device_sbc_init();
int lmp_private_get_esco_remain_buffer_size();
int lmp_private_get_esco_data_len();
void *lmp_private_get_esco_packet(int *len, u32 *hash);
void lmp_private_free_esco_packet(void *packet);
extern int lmp_private_esco_suspend_resume(int flag);
extern int bt_audio_sync_nettime_select(u8 basetime);
extern u32 bt_audio_sync_lat_time(void);
void *a2dp_play_sync_open(u8 channel, u32 sample_rate, u32 output_rate, u32 coding_type);
void *esco_play_sync_open(u8 channel, u16 sample_rate, u16 output_rate);
//void audio_adc_init(void);
void *audio_adc_open(void *param, const char *source);
int audio_adc_sample_start(void *adc);
void audio_fade_in_fade_out(u8 left_gain, u8 right_gain);
void set_source_sample_rate(u16 sample_rate);
u8 bt_audio_is_running(void);
void audio_resume_all_decoder(void)
{
audio_decoder_resume_all(&decode_task);
}
void audio_src_isr_deal(void)
{
audio_resume_all_decoder();
}
#define AUDIO_DECODE_TASK_WAKEUP_TIME 4 //ms
#if AUDIO_DECODE_TASK_WAKEUP_TIME
#include "timer.h"
static void audio_decoder_wakeup_timer(void *priv)
{
/*putchar('k');*/
audio_decoder_resume_all(&decode_task);
}
int audio_decoder_task_add_probe(struct audio_decoder_task *task)
{
local_irq_disable();
if (task->wakeup_timer == 0) {
task->wakeup_timer = usr_timer_add(NULL, audio_decoder_wakeup_timer, AUDIO_DECODE_TASK_WAKEUP_TIME, 1);
}
local_irq_enable();
log_i("audio_decoder_task_add_probe:%d\n", task->wakeup_timer);
return 0;
}
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;
}
local_irq_disable();
if (task->wakeup_timer) {
log_i("audio_decoder_task_del_probe:%d\n", task->wakeup_timer);
usr_timer_del(task->wakeup_timer);
task->wakeup_timer = 0;
}
local_irq_enable();
return 0;
}
int audio_decoder_wakeup_modify(int msecs)
{
if (decode_task.wakeup_timer) {
usr_timer_modify(decode_task.wakeup_timer, msecs);
}
return 0;
}
/*
* BR30 : DA输出源启动后可使用DAC irq做唤醒省去hi_timer
*/
int audio_decoder_wakeup_select(u8 source)
{
if (source == 0) {
/*唤醒源为hi_timer*/
local_irq_disable();
if (!decode_task.wakeup_timer) {
decode_task.wakeup_timer = usr_timer_add(NULL, audio_decoder_wakeup_timer, AUDIO_DECODE_TASK_WAKEUP_TIME, 1);
}
local_irq_enable();
} else if (source == 1) {
#if TCFG_AUDIO_OUTPUT_IIS
/*唤醒源为输出目标中断*/
if (!audio_iis_is_working()) {
return audio_decoder_wakeup_select(0);
}
int err = audio_iis_irq_resume_decoder(a2dp_low_latency ? 2 : AUDIO_DECODE_TASK_WAKEUP_TIME, NULL, audio_decoder_wakeup_timer);
#else
/*唤醒源为输出目标中断*/
if (!audio_dac_is_working(&dac_hdl)) {
return audio_decoder_wakeup_select(0);
}
/*int err = audio_dac_set_irq_time(&dac_hdl, a2dp_low_latency ? 2 : AUDIO_DECODE_TASK_WAKEUP_TIME);*/
int err = audio_dac_irq_enable(&dac_hdl, a2dp_low_latency ? 2 : AUDIO_DECODE_TASK_WAKEUP_TIME,
NULL, audio_decoder_wakeup_timer);
#endif
if (err) {
return audio_decoder_wakeup_select(0);
}
local_irq_disable();
if (decode_task.wakeup_timer) {
usr_timer_del(decode_task.wakeup_timer);
decode_task.wakeup_timer = 0;
}
local_irq_enable();
}
return 0;
}
#endif/*AUDIO_DECODE_TASK_WAKEUP_TIME*/
static u8 bt_dec_idle_query()
{
if (a2dp_dec || esco_dec) {
return 0;
}
return 1;
}
REGISTER_LP_TARGET(bt_dec_lp_target) = {
.name = "bt_dec",
.is_idle = bt_dec_idle_query,
};
___interrupt
static void audio_irq_handler()
{
/* putchar('A'); */
if (JL_AUDIO->DAC_CON & BIT(7)) {
JL_AUDIO->DAC_CON |= BIT(6);
if (JL_AUDIO->DAC_CON & BIT(5)) {
audio_decoder_resume_all(&decode_task);
audio_dac_irq_handler(&dac_hdl);
/*r_printf("resuem\n");*/
}
}
if (JL_AUDIO->ADC_CON & BIT(7)) {
JL_AUDIO->ADC_CON |= BIT(6);
if ((JL_AUDIO->ADC_CON & BIT(5)) && (JL_AUDIO->ADC_CON & BIT(4))) {
audio_adc_irq_handler(&adc_hdl);
}
}
}
#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 == dac_hdl.channel) {
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 = dac_hdl.channel;
e_det_param.dcc = 1;
mix_out_automute_hdl = audio_energy_detect_open(&e_det_param);
}
void mix_out_automute_close()
{
if (mix_out_automute_hdl) {
audio_energy_detect_close(mix_out_automute_hdl);
}
}
#endif //#if AUDIO_OUTPUT_AUTOMUTE
extern void audio_adc_mic_demo(u8 mic_idx, u8 gain, u8 mic_2_dac);
extern void dac_analog_power_control(u8 en);
extern void audio_dac_output_enable(struct audio_dac_hdl *dac);
extern void audio_dac_output_disable(struct audio_dac_hdl *dac);
u8 audio_fast_mode = 0;
void audio_fast_mode_test()
{
audio_fast_mode = 1;
audio_dac_set_volume(&dac_hdl, app_audio_get_volume(APP_AUDIO_CURRENT_STATE));
dac_analog_power_control(1);////将关闭基带,不开可发现,不可连接
audio_dac_start(&dac_hdl);
audio_adc_mic_demo(AUDIO_ADC_MIC_CH, 10, 1);
}
u8 dac_power_off_flag = 1;
u8 is_dac_power_off()
{
if (a2dp_dec || esco_dec || get_call_status() != BT_CALL_HANGUP) {
return 1;
}
return dac_power_off_flag;
}
void dac_analog_power_control(u8 en)
{
#ifdef CONFIG_CURRENT_SOUND_DEAL_ENABLE
if (en) {
dac_power_off_flag = 0;
audio_dac_output_enable(&dac_hdl);
} else {
#if TCFG_AUDIO_ANC_ENABLE
if (!anc_status_get()) {
puts("anc dac_power_off");
audio_dac_output_disable(&dac_hdl);
/* dac_power_off(); */
}
#else
puts("dac_power_off");
/* dac_power_off(); */
audio_dac_output_disable(&dac_hdl);
#endif
dac_power_off_flag = 1;
}
#endif
}
static void mixer_event_handler(struct audio_mixer *mixer, int event)
{
switch (event) {
case MIXER_EVENT_CH_OPEN:
printf("** MIXER_EVENT_CH_OPEN **\n");
if (audio_mixer_get_start_ch_num(mixer) == 1) {
#if AUDIO_OUTPUT_AUTOMUTE
audio_energy_detect_sample_rate_update(mix_out_automute_hdl, audio_mixer_get_sample_rate(mixer));
#endif //#if AUDIO_OUTPUT_AUTOMUTE
#if TCFG_AUDIO_OUTPUT_IIS
audio_iis_output_set_srI(audio_mixer_get_sample_rate(mixer));
audio_iis_output_start(1);
#elif TCFG_APP_FM_EMITTER_EN
#else
if (A2DP_TO_PCM_DEVICE_FORMAT && a2dp_dec && a2dp_dec->start) {
audio_dac_set_sample_rate(&dac_hdl, A2DP_TO_PCM_DEVICE_FORMAT);
} else {
audio_dac_set_sample_rate(&dac_hdl, audio_mixer_get_sample_rate(mixer));
}
audio_dac_set_volume(&dac_hdl, app_audio_get_volume(APP_AUDIO_CURRENT_STATE));
audio_dac_start(&dac_hdl);
dac_analog_power_control(1);
g_printf("MIXER_EVENT_CH_OPEN=%d\n", dac_power_off_flag);
audio_dac_set_input_correct_callback(&dac_hdl,
(void *)mixer,
(void (*)(void *, int))audio_mixer_position_correct);
#endif
#if AUDIO_OUT_EFFECT_ENABLE
if (!audio_out_effect_dis) {
audio_out_effect_open(mixer, audio_mixer_get_sample_rate(mixer));
}
#endif
}
break;
case MIXER_EVENT_CH_CLOSE:
if (audio_mixer_get_ch_num(mixer) == 0) {
audio_dac_set_input_correct_callback(&dac_hdl, NULL, NULL);
#if AUDIO_OUT_EFFECT_ENABLE
audio_out_effect_close();
#endif
#if TCFG_AUDIO_OUTPUT_IIS
audio_iis_output_stop();
#elif TCFG_APP_FM_EMITTER_EN
#else
audio_dac_set_protect_time(&dac_hdl, 0, NULL, NULL);
audio_dac_stop(&dac_hdl);
dac_analog_power_control(0);
g_printf("MIXER_EVENT_CH_CLOSE=%d\n", dac_power_off_flag);
if (audio_fast_mode) {
audio_fast_mode_test();
}
#endif
}
break;
}
}
static int mix_probe_handler(struct audio_mixer *mixer)
{
return 0;
}
#define IIS_MONO_TO_DUAL_POINTS 64
static inline void audio_pcm_mono_to_dual(s16 *dual_pcm, s16 *mono_pcm, int points);
static int mix_output_handler(struct audio_mixer *mixer, s16 *data, u16 len)
{
int rlen = len;
int wlen = 0;
/*os_sem_set(&dac_sem, 0);*/
/* audio_aec_refbuf(data, len); */
#if AUDIO_OUTPUT_AUTOMUTE
audio_energy_detect_run(mix_out_automute_hdl, data, len);
#endif //#if AUDIO_OUTPUT_AUTOMUTE
#if TCFG_AUDIO_OUTPUT_IIS
u8 dac_connect_mode = audio_dac_get_channel(&dac_hdl);
if (dac_connect_mode == DAC_OUTPUT_LR) {
wlen = audio_iis_output_write(data, len);
} else {
s16 *mono_data = (s16 *)data;
s16 point_num = 0;
u16 remain_points = (len >> 1);
s16 two_ch_data[IIS_MONO_TO_DUAL_POINTS * 2];
do {
point_num = IIS_MONO_TO_DUAL_POINTS;
if (point_num >= remain_points) {
point_num = remain_points;
}
audio_pcm_mono_to_dual(two_ch_data, mono_data, point_num);
int tmp_len = audio_iis_output_write(two_ch_data, point_num << 2);
wlen += tmp_len;
remain_points -= (tmp_len >> 2);
if (tmp_len < (point_num << 2)) {
break;
}
mono_data += point_num;
} while (remain_points);
wlen = wlen >> 1;
}
#elif TCFG_APP_FM_EMITTER_EN
fm_emitter_cbuf_write((u8 *)data, len);
#else
wlen = audio_dac_write(&dac_hdl, data, len);
#endif
return wlen;
}
#if AUDIO_OUT_EFFECT_ENABLE
static int mix_output_effect_handler(struct audio_mixer *mixer, s16 *data, u16 len)
{
if (!audio_out_effect) {
return mix_output_handler(mixer, data, len);
}
if (audio_out_effect && audio_out_effect->async) {
return eq_drc_run(audio_out_effect, data, len);
}
if (!audio_out_effect->remain) {
if (audio_out_effect && !audio_out_effect->async) {
eq_drc_run(audio_out_effect, data, len);
}
}
int wlen = mix_output_handler(mixer, data, len);
if (wlen == len) {
audio_out_effect->remain = 0;
} else {
audio_out_effect->remain = 1;
}
return wlen;
}
#endif//AUDIO_OUT_EFFECT_ENABLE
static const struct audio_mix_handler mix_handler = {
.mix_probe = mix_probe_handler,
#if AUDIO_OUT_EFFECT_ENABLE
.mix_output = mix_output_effect_handler,
#else
.mix_output = mix_output_handler,
#endif//AUDIO_OUT_EFFECT_ENABLE
};
void audio_mix_ch_event_handler(void *priv, int event)
{
switch (event) {
case MIXER_EVENT_CH_OPEN:
if (priv) {
u32 *params = (u32 *)priv;
struct audio_mixer_ch *ch = (struct audio_mixer_ch *)params[0];
u32 base_time = params[2];
#if defined(TCFG_AUDIO_OUTPUT_IIS) && TCFG_AUDIO_OUTPUT_IIS
audio_iis_add_syncts_handle((void *)params[1]);
#else
audio_dac_add_syncts_handle(&dac_hdl, (void *)params[1]);
#endif
u32 current_time = (bt_audio_sync_lat_time() * 625 * TIME_US_FACTOR);
u32 time_diff = ((base_time - current_time) & 0xffffffff) / TIME_US_FACTOR;
/*printf("-----base time : %u, current_time : %u------\n", base_time, current_time);*/
if (time_diff < 500000) {
int buf_frame = audio_dac_buffered_frames(&dac_hdl);
#if defined(TCFG_AUDIO_OUTPUT_IIS) && TCFG_AUDIO_OUTPUT_IIS
buf_frame = audio_iis_buffered_frames();
#endif
int slience_frames = (u64)time_diff * audio_mixer_get_sample_rate(&mixer) / 1000000 - buf_frame;
if (slience_frames < 0) {
slience_frames = 0;
}
/*printf("-------slience_frames : %d-------\n", slience_frames);*/
sound_pcm_update_frame_num((void *)params[1], -slience_frames);
audio_mixer_ch_add_slience_samples(ch, slience_frames * dac_hdl.channel);
}
}
break;
case MIXER_EVENT_CH_CLOSE:
if (priv) {
u32 *params = (u32 *)priv;
#if defined(TCFG_AUDIO_OUTPUT_IIS) && TCFG_AUDIO_OUTPUT_IIS
audio_iis_remove_syncts_handle((void *)params[1]);
#else
audio_dac_remove_syncts_handle(&dac_hdl, (void *)params[1]);
#endif
}
break;
}
}
#define RB16(b) (u16)(((u8 *)b)[0] << 8 | (((u8 *)b))[1])
#define RB32(b) (u32)(((u8 *)b)[0] << 24 | (((u8 *)b))[1] << 16 | (((u8 *)b))[2] << 8 | (((u8 *)b))[3])
static int get_rtp_header_len(u8 new_frame, u8 *buf, int len)
{
int ext, csrc;
int byte_len;
int header_len = 0;
u8 *data = buf;
csrc = buf[0] & 0x0f;
ext = buf[0] & 0x10;
byte_len = 12 + 4 * csrc;
buf += byte_len;
if (ext) {
ext = (RB16(buf + 2) + 1) << 2;
}
if (new_frame) {
header_len = byte_len + ext + 1;
} else {
header_len = byte_len + ext;
}
if (a2dp_dec->coding_type == AUDIO_CODING_SBC) {
while (data[header_len] != 0x9c) {
if (++header_len > len) {
return len;
}
}
}
return header_len;
}
__attribute__((weak))
int audio_dac_get_channel(struct audio_dac_hdl *p)
{
return 0;
}
void __a2dp_drop_frame(void *p)
{
int len;
u8 *frame;
#if 0
int num = a2dp_media_get_packet_num();
if (num > 1) {
for (int i = 0; i < num; i++) {
len = a2dp_media_get_packet(&frame);
if (len <= 0) {
break;
}
//printf("a2dp_drop_frame: %d\n", len);
a2dp_media_free_packet(frame);
}
}
#else
while (1) {
len = a2dp_media_try_get_packet(&frame);
if (len <= 0) {
break;
}
a2dp_media_free_packet(frame);
}
#endif
}
static void __a2dp_clean_frame_by_number(struct a2dp_dec_hdl *dec, u16 num)
{
u16 end_seqn = dec->seqn + num;
if (end_seqn == 0) {
end_seqn++;
}
/*__a2dp_drop_frame(NULL);*/
/*dec->drop_seqn = end_seqn;*/
a2dp_media_clear_packet_before_seqn(end_seqn);
}
static void a2dp_tws_clean_frame(void *arg)
{
u8 master = 0;
#if TCFG_USER_TWS_ENABLE
if (tws_api_get_role() == TWS_ROLE_MASTER) {
master = 1;
}
#else
master = 1;
#endif
if (!master) {
return;
}
int msecs = a2dp_media_get_remain_play_time(0);
if (msecs <= 0) {
return;
}
if (a2dp_dec && a2dp_dec->fetch_lock) {
return;
}
int len = 0;
u16 seqn = 0;
u8 *packet = a2dp_media_fetch_packet(&len, NULL);
if (!packet) {
return;
}
seqn = RB16(packet + 2) + 10;
if (seqn == 0) {
seqn = 1;
}
a2dp_media_clear_packet_before_seqn(seqn);
}
static u8 a2dp_suspend = 0;
static u32 a2dp_resume_time = 0;
int a2dp_decoder_pause(void)
{
if (a2dp_dec) {
return audio_decoder_pause(&(a2dp_dec->decoder));
}
return 0;
}
int a2dp_decoder_start(void)
{
if (a2dp_dec) {
return audio_decoder_start(&(a2dp_dec->decoder));
}
return 0;
}
u8 get_a2dp_drop_frame_flag()
{
if (a2dp_dec) {
return a2dp_dec->timer;
}
return 0;
}
void a2dp_drop_frame_start()
{
if (a2dp_dec && (a2dp_dec->timer == 0)) {
a2dp_dec->timer = sys_timer_add(NULL, __a2dp_drop_frame, 50);
a2dp_tws_audio_conn_offline();
}
}
void a2dp_drop_frame_stop()
{
if (a2dp_dec && a2dp_dec->timer) {
sys_timer_del(a2dp_dec->timer);
a2dp_tws_audio_conn_delete();
a2dp_dec->timer = 0;
}
}
static void a2dp_dec_set_output_channel(struct a2dp_dec_hdl *dec)
{
int state = 0;
enum audio_channel channel;
u8 dac_connect_mode = 0;
#if TCFG_USER_TWS_ENABLE
state = tws_api_get_tws_state();
if (state & TWS_STA_SIBLING_CONNECTED) {
channel = tws_api_get_local_channel() == 'L' ? AUDIO_CH_L : AUDIO_CH_R;
dec->ch = 1;
} else {
dac_connect_mode = audio_dac_get_channel(&dac_hdl);
if (dac_connect_mode == DAC_OUTPUT_LR) {
channel = AUDIO_CH_LR;
dec->ch = 2;
} else {
channel = AUDIO_CH_DIFF;
dec->ch = 1;
}
}
#else
dac_connect_mode = audio_dac_get_channel(&dac_hdl);
if (dac_connect_mode == DAC_OUTPUT_LR) {
channel = AUDIO_CH_LR;
dec->ch = 2;
} else {
channel = AUDIO_CH_DIFF;
dec->ch = 1;
}
#endif
#if TCFG_APP_FM_EMITTER_EN
channel = AUDIO_CH_LR;
#endif
if (channel != dec->channel) {
printf("set_channel: %d\n", channel);
audio_decoder_set_output_channel(&dec->decoder, channel);
dec->channel = channel;
#if TCFG_EQ_ENABLE&&TCFG_BT_MUSIC_EQ_ENABLE
if (dec->eq_drc && dec->eq_drc->eq) {
audio_eq_set_channel(dec->eq_drc->eq, dec->ch);
}
#endif//TCFG_BT_MUSIC_EQ_ENABLE
/* #if TCFG_USER_TWS_ENABLE */
#if AUDIO_SURROUND_CONFIG
if (dec->sur) {
audio_surround_set_ch(dec->sur, channel);
}
#endif//AUDIO_SURROUND_CONFIG
/* #endif//TCFG_USER_TWS_ENABLE */
}
}
/*
*
*/
static int a2dp_decoder_set_timestamp(struct a2dp_dec_hdl *dec, u16 seqn)
{
#if AUDIO_CODEC_SUPPORT_SYNC
u32 timestamp;
timestamp = a2dp_audio_update_timestamp(dec->ts_handle, seqn, audio_syncts_get_dts(dec->syncts));
if (!dec->ts_start) {
dec->ts_start = 1;
dec->mix_ch_event_params[2] = timestamp;
} else {
audio_syncts_next_pts(dec->syncts, timestamp);
audio_syncts_update_sample_rate(dec->syncts, a2dp_audio_sample_rate(dec->ts_handle));;
}
dec->timestamp = timestamp;
/*printf("timestamp : %d, %d\n", seqn, timestamp / TIME_US_FACTOR / 625);*/
#endif
return 0;
}
static bool a2dp_audio_is_underrun(struct a2dp_dec_hdl *dec)
{
#if AUDIO_CODEC_SUPPORT_SYNC
if (dec->ts_start != 2) {
return false;
}
#endif
int underrun_time = a2dp_low_latency ? 1 : 20;
#if defined(TCFG_AUDIO_OUTPUT_IIS) && TCFG_AUDIO_OUTPUT_IIS
if (audio_iis_data_time() < underrun_time) {
return true;
}
#else
if (audio_dac_data_time(&dac_hdl) < underrun_time) {
return true;
}
#endif
return false;
}
static bool a2dp_bt_rx_overrun(void)
{
return a2dp_media_get_remain_buffer_size() < 768 ? true : false;
}
static void a2dp_decoder_stream_free(struct a2dp_dec_hdl *dec, void *packet)
{
if (packet) {
a2dp_media_free_packet(packet);
}
if ((void *)packet == (void *)dec->repair_pkt) {
dec->repair_pkt = NULL;
}
if (dec->repair_pkt) {
a2dp_media_free_packet(dec->repair_pkt);
dec->repair_pkt = NULL;
}
dec->repair_pkt_len = 0;
}
static void a2dp_stream_underrun_feedback(void *priv);
static int a2dp_audio_delay_time(struct a2dp_dec_hdl *dec);
#define a2dp_seqn_before(a, b) ((a < b && (u16)(b - a) < 1000) || (a > b && (u16)(a - b) > 1000))
static int a2dp_buffered_stream_sample_rate(struct a2dp_dec_hdl *dec, u8 *from_packet, u16 *end_seqn)
{
u8 *packet = from_packet;
int len = 0;
int sample_rate = 0;
if (!dec->sample_detect) {
return dec->sample_rate;
}
a2dp_frame_sample_detect_start(dec->sample_detect, a2dp_media_dump_rx_time(packet));
while (1) {
packet = a2dp_media_fetch_packet(&len, packet);
if (!packet) {
break;
}
sample_rate = a2dp_frame_sample_detect(dec->sample_detect, packet, len, a2dp_media_dump_rx_time(packet));
*end_seqn = RB16(packet + 2);
}
/*printf("A2DP sample detect : %d - %d\n", sample_rate, dec->sample_rate);*/
return sample_rate;
}
static int a2dp_stream_overrun_handler(struct a2dp_dec_hdl *dec, u8 **frame, int *len)
{
u8 *packet = NULL;
int rlen = 0;
int msecs = 0;
int overrun = 0;
int sample_rate = 0;
u16 from_seqn = RB16(dec->repair_pkt + 2);
u16 seqn = from_seqn;
u16 end_seqn = 0;
overrun = 1;
while (1) {
msecs = a2dp_audio_delay_time(dec);
if (msecs < (CONFIG_A2DP_DELAY_TIME + 50) && !a2dp_bt_rx_overrun()) {
break;
}
overrun = 0;
rlen = a2dp_media_try_get_packet(&packet);
if (rlen <= 0) {
break;
}
sample_rate = a2dp_buffered_stream_sample_rate(dec, dec->repair_pkt, &end_seqn);
a2dp_decoder_stream_free(dec, NULL);
dec->repair_pkt = packet;
dec->repair_pkt_len = rlen;
seqn = RB16(packet + 2);
if (!a2dp_seqn_before(seqn, dec->overrun_seqn)) {
*frame = packet;
*len = rlen;
/*printf("------> end frame : %d\n", dec->overrun_seqn);*/
return 1;
}
if (/*sample_rate < (dec->sample_rate * 4 / 5) || */sample_rate > (dec->sample_rate * 4 / 3)) {
if (a2dp_seqn_before(dec->overrun_seqn, end_seqn)) {
dec->overrun_seqn = end_seqn;
}
continue;
}
}
if (overrun) {
/*putchar('+');*/
/* dec->overrun_seqn++; */
} else {
/*putchar('-');*/
}
*frame = dec->repair_pkt;
*len = dec->repair_pkt_len;
return 0;
}
static int a2dp_stream_missed_handler(struct a2dp_dec_hdl *dec, u8 **frame, int *len)
{
int msecs = a2dp_audio_delay_time(dec);
*frame = dec->repair_pkt;
*len = dec->repair_pkt_len;
if ((msecs >= (dec->delay_time + 50) || a2dp_bt_rx_overrun()) || --dec->missed_num == 0) {
/*putchar('M');*/
return 1;
}
/*putchar('m');*/
return 0;
}
static int a2dp_stream_underrun_handler(struct a2dp_dec_hdl *dec, u8 **packet)
{
if (!a2dp_audio_is_underrun(dec)) {
putchar('x');
return 0;
}
putchar('X');
if (dec->stream_error != A2DP_STREAM_UNDERRUN) {
if (!dec->stream_error) {
a2dp_stream_underrun_feedback(dec);
}
dec->stream_error = a2dp_low_latency ? A2DP_STREAM_LOW_UNDERRUN : A2DP_STREAM_UNDERRUN;
dec->repair = a2dp_low_latency ? 0 : 1;
}
*packet = dec->repair_pkt;
dec->repair_frames++;
return dec->repair_pkt_len;
}
static int a2dp_stream_error_filter(struct a2dp_dec_hdl *dec, u8 new_packet, u8 *packet, int len)
{
int err = 0;
if (dec->coding_type == AUDIO_CODING_AAC) {
dec->header_len = get_rtp_header_len(dec->new_frame, packet, len);
dec->new_frame = 0;
} else {
dec->header_len = get_rtp_header_len(1, packet, len);
}
if (dec->header_len >= len) {
printf("##A2DP header error : %d\n", dec->header_len);
a2dp_decoder_stream_free(dec, packet);
return -EFAULT;
}
u16 seqn = RB16(packet + 2);
if (new_packet) {
if (dec->stream_error == A2DP_STREAM_UNDERRUN) {
int missed_frames = (u16)(seqn - dec->seqn) - 1;
if (missed_frames > dec->repair_frames) {
dec->stream_error = A2DP_STREAM_MISSED;
dec->missed_num = missed_frames - dec->repair_frames + 1;
/*printf("case 0 : %d, %d\n", missed_frames, dec->repair_frames);*/
err = -EAGAIN;
} else if (missed_frames < dec->repair_frames) {
dec->stream_error = A2DP_STREAM_OVERRUN;
dec->overrun_seqn = seqn + dec->repair_frames - missed_frames;
/*printf("case 1 : %d, %d, seqn : %d, %d\n", missed_frames, dec->repair_frames, seqn, dec->overrun_seqn); */
err = -EAGAIN;
}
} else if (!dec->stream_error && (u16)(seqn - dec->seqn) > 1) {
dec->stream_error = A2DP_STREAM_MISSED;
if (a2dp_audio_delay_time(dec) < dec->delay_time) {
dec->missed_num = (u16)(seqn - dec->seqn);
err = -EAGAIN;
}
int pkt_len;
void *head = a2dp_media_fetch_packet(&pkt_len, NULL);
/*printf("case 2 : %d, %d, pkt : 0x%x, 0x%x\n", seqn, dec->seqn, (u32)head, (u32)packet);*/
if (dec->missed_num > 30) {
printf("##A serious mistake : A2DP stream missed too much, %d\n", dec->missed_num);
dec->missed_num = 30;
}
}
dec->repair_frames = 0;
}
if (!err && new_packet) {
dec->seqn = seqn;
}
dec->repair_pkt = packet;
dec->repair_pkt_len = len;
return err;
}
static int a2dp_dec_get_frame(struct audio_decoder *decoder, u8 **frame)
{
struct a2dp_dec_hdl *dec = container_of(decoder, struct a2dp_dec_hdl, decoder);
u8 *packet = NULL;
int len = 0;
u8 new_packet = 0;
try_again:
switch (dec->stream_error) {
case A2DP_STREAM_OVERRUN:
new_packet = a2dp_stream_overrun_handler(dec, &packet, &len);
break;
case A2DP_STREAM_MISSED:
new_packet = a2dp_stream_missed_handler(dec, &packet, &len);
break;
default:
len = a2dp_media_try_get_packet(&packet);
if (len <= 0) {
len = a2dp_stream_underrun_handler(dec, &packet);
} else {
a2dp_decoder_stream_free(dec, NULL);
new_packet = 1;
}
break;
}
if (len <= 0) {
return 0;
}
int err = a2dp_stream_error_filter(dec, new_packet, packet, len);
if (err) {
if (-err == EAGAIN) {
dec->new_frame = 1;
goto try_again;
}
return 0;
}
*frame = packet + dec->header_len;
len -= dec->header_len;
if (dec->stream_error && new_packet) {
#if AUDIO_CODEC_SUPPORT_SYNC && TCFG_USER_TWS_ENABLE
if (dec->ts_handle) {
tws_a2dp_share_timestamp(dec->ts_handle);
}
#endif
dec->stream_error = 0;
}
if (dec->slience_frames) {
dec->slience_frames--;
}
a2dp_decoder_set_timestamp(dec, dec->seqn);
return len;
}
static void a2dp_dec_put_frame(struct audio_decoder *decoder, u8 *frame)
{
struct a2dp_dec_hdl *dec = container_of(decoder, struct a2dp_dec_hdl, decoder);
if (frame) {
if (!a2dp_media_channel_exist() || app_var.goto_poweroff_flag) {
a2dp_decoder_stream_free(dec, (void *)(frame - dec->header_len));
}
/*a2dp_media_free_packet((void *)(frame - dec->header_len));*/
}
}
static int a2dp_dec_fetch_frame(struct audio_decoder *decoder, u8 **frame)
{
struct a2dp_dec_hdl *dec = container_of(decoder, struct a2dp_dec_hdl, decoder);
u8 *packet = NULL;
int len = 0;
u32 wait_timeout = 0;
if (!dec->start) {
wait_timeout = jiffies + msecs_to_jiffies(500);
}
dec->fetch_lock = 1;
__retry_fetch:
packet = a2dp_media_fetch_packet(&len, NULL);
if (packet) {
dec->header_len = get_rtp_header_len(1, packet, len);
*frame = packet + dec->header_len;
len -= dec->header_len;
} else if (!dec->start) {
if (time_before(jiffies, wait_timeout)) {
os_time_dly(1);
goto __retry_fetch;
}
}
dec->fetch_lock = 0;
return len;
}
static const struct audio_dec_input a2dp_input = {
.coding_type = AUDIO_CODING_SBC,
.data_type = AUDIO_INPUT_FRAME,
.ops = {
.frame = {
.fget = a2dp_dec_get_frame,
.fput = a2dp_dec_put_frame,
.ffetch = a2dp_dec_fetch_frame,
}
}
};
#define bt_time_before(t1, t2) \
(((t1 < t2) && ((t2 - t1) & 0x7ffffff) < 0xffff) || \
((t1 > t2) && ((t1 - t2) & 0x7ffffff) > 0xffff))
#define bt_time_to_msecs(clk) (((clk) * 625) / 1000)
#define msecs_to_bt_time(m) (((m + 1)* 1000) / 625)
static int a2dp_audio_delay_time(struct a2dp_dec_hdl *dec)
{
/*struct a2dp_dec_hdl *dec = container_of(decoder, struct a2dp_dec_hdl, decoder);*/
int msecs = 0;
#if TCFG_USER_TWS_ENABLE
msecs = a2dp_media_get_remain_play_time(1);
#else
msecs = a2dp_media_get_remain_play_time(0);
#endif
if (dec->syncts) {
msecs += sound_buffered_between_syncts_and_device(dec->syncts, 0);
}
#if defined(TCFG_AUDIO_OUTPUT_IIS) && TCFG_AUDIO_OUTPUT_IIS
msecs += audio_iis_data_time();
#else
msecs += audio_dac_data_time(&dac_hdl);
#endif
return msecs;
}
static int a2dp_decoder_stream_delay_update(struct audio_decoder *decoder)
{
struct a2dp_dec_hdl *dec = container_of(decoder, struct a2dp_dec_hdl, decoder);
int msecs = 0;
int err = 0;
#if AUDIO_CODEC_SUPPORT_SYNC
msecs = a2dp_audio_delay_time(dec);
if (dec->stream_error) {
return 0;
}
if (dec->sync_step == 2) {
int distance_time = msecs - a2dp_delay_time;
if (a2dp_bt_rx_overrun() && distance_time < 50) {
distance_time = 50;
}
if (dec->ts_handle) {
a2dp_audio_delay_offset_update(dec->ts_handle, distance_time);
}
}
#endif
/*printf("%d -> %dms, delay_time : %dms\n", msecs1, msecs, a2dp_delay_time);*/
return 0;
}
/*
* A2DP 音频同步控制处理函数
* 1.包括音频延时浮动参数;
* 2.处理因为超时等情况丢弃音频样点;
* 3.调用与蓝牙主机音频延时做同步的功能;
* 4.处理TWS从机加入与解码被打断的情况。
*
*/
static int a2dp_decoder_audio_sync_handler(struct audio_decoder *decoder)
{
struct a2dp_dec_hdl *dec = container_of(decoder, struct a2dp_dec_hdl, decoder);
int err;
if (!dec->syncts) {
return 0;
}
err = a2dp_decoder_stream_delay_update(decoder);
if (err) {
audio_decoder_suspend(decoder, 0);
return -EAGAIN;
}
return 0;
}
static u16 a2dp_max_interval = 0;
#define A2DP_EST_AUDIO_CAPACITY 350//ms
static void a2dp_stream_underrun_feedback(void *priv)
{
struct a2dp_dec_hdl *dec = (struct a2dp_dec_hdl *)priv;
dec->underrun_feedback = 1;
if (a2dp_delay_time < a2dp_max_interval + 50) {
a2dp_delay_time = a2dp_max_interval + 50;
} else {
a2dp_delay_time += 50;
}
if (a2dp_delay_time > A2DP_EST_AUDIO_CAPACITY) {
a2dp_delay_time = A2DP_EST_AUDIO_CAPACITY;
}
}
/*void a2dp_stream_interval_time_handler(int time)*/
void reset_a2dp_sbc_instant_time(u16 time)
{
if (a2dp_max_interval < time) {
a2dp_max_interval = time;
#if A2DP_FLUENT_STREAM_MODE
if (a2dp_max_interval > a2dp_delay_time) {
a2dp_delay_time = a2dp_max_interval + 5;
if (a2dp_delay_time > A2DP_EST_AUDIO_CAPACITY) {
a2dp_delay_time = A2DP_EST_AUDIO_CAPACITY;
}
}
#endif
/*printf("Max : %dms\n", time);*/
}
}
static void a2dp_stream_stability_detect(void *priv)
{
struct a2dp_dec_hdl *dec = (struct a2dp_dec_hdl *)priv;
if (dec->underrun_feedback) {
dec->underrun_feedback = 0;
return;
}
if (a2dp_delay_time > dec->delay_time) {
if (a2dp_max_interval < a2dp_delay_time) {
a2dp_delay_time -= 50;
if (a2dp_delay_time < dec->delay_time) {
a2dp_delay_time = dec->delay_time;
}
if (a2dp_delay_time < a2dp_max_interval) {
a2dp_delay_time = a2dp_max_interval + 5;
}
}
a2dp_max_interval = dec->delay_time;
}
}
#if AUDIO_CODEC_SUPPORT_SYNC
static void a2dp_decoder_update_base_time(struct a2dp_dec_hdl *dec)
{
int distance_time = a2dp_low_latency ? a2dp_delay_time : (a2dp_delay_time - a2dp_media_get_remain_play_time(1));
if (!a2dp_low_latency) {
distance_time = a2dp_delay_time;
} else if (distance_time < 20) {
distance_time = 20;
}
dec->base_time = bt_audio_sync_lat_time() + msecs_to_bt_time(distance_time);
}
#endif
static int a2dp_decoder_stream_is_available(struct a2dp_dec_hdl *dec)
{
int err = 0;
u8 *packet = NULL;
int len = 0;
int drop = 0;
#if AUDIO_CODEC_SUPPORT_SYNC
if (dec->sync_step) {
return 0;
}
packet = (u8 *)a2dp_media_fetch_packet(&len, NULL);
if (!packet) {
return -EINVAL;
}
dec->seqn = RB16(packet + 2);
if (dec->ts_handle) {
#if TCFG_USER_TWS_ENABLE
if (!tws_network_audio_was_started() && !a2dp_audio_timestamp_is_available(dec->ts_handle, dec->seqn, 0, &drop)) {
if (drop) {
local_irq_disable();
u8 *check_packet = (u8 *)a2dp_media_fetch_packet(&len, NULL);
if (check_packet && RB16(check_packet + 2) == dec->seqn) {
a2dp_media_free_packet(packet);
}
local_irq_enable();
a2dp_decoder_update_base_time(dec);
a2dp_audio_set_base_time(dec->ts_handle, dec->base_time);
}
return -EINVAL;
}
#endif
}
dec->sync_step = 2;
#endif
return 0;
}
static int a2dp_dec_probe_handler(struct audio_decoder *decoder)
{
struct a2dp_dec_hdl *dec = container_of(decoder, struct a2dp_dec_hdl, decoder);
int err = 0;
err = a2dp_decoder_stream_is_available(dec);
if (err) {
audio_decoder_suspend(decoder, 0);
return err;
}
err = a2dp_decoder_audio_sync_handler(decoder);
if (err) {
audio_decoder_suspend(decoder, 0);
return err;
}
dec->new_frame = 1;
a2dp_dec_set_output_channel(dec);
return err;
}
#if (SYS_VOL_TYPE == VOL_TYPE_DIGITAL)
void a2dp_digital_vol_set(u8 vol)
{
if (a2dp_dec) {
audio_digital_vol_set(a2dp_dec->dvol, vol);
}
}
#endif
static int a2dp_output_after_syncts_filter(void *priv, void *data, int len)
{
int wlen = 0;
int drop_len = 0;
struct a2dp_dec_hdl *dec = (struct a2dp_dec_hdl *)priv;
#if TCFG_EQ_ENABLE&&TCFG_BT_MUSIC_EQ_ENABLE
if (dec->eq_drc && dec->eq_drc->async) {
return eq_drc_run(dec->eq_drc, data, len);//异步eq
}
#endif//TCFG_BT_MUSIC_EQ_ENABLE
return audio_mixer_ch_write(&dec->mix_ch, data, len);
}
static void a2dp_output_before_syncts_handler(struct a2dp_dec_hdl *dec, void *data, int len)
{
#if AUDIO_CODEC_SUPPORT_SYNC
if (dec->ts_start == 1) {
u32 timestamp = dec->timestamp;
u32 current_time = ((bt_audio_sync_lat_time() + (30000 / 625)) & 0x7ffffff) * 625 * TIME_US_FACTOR;
#define time_after_timestamp(t1, t2) \
((t1 > t2 && ((t1 - t2) < (10000000L * TIME_US_FACTOR))) || (t1 < t2 && ((t2 - t1) > (10000000L * TIME_US_FACTOR))))
if (!time_after_timestamp(timestamp, current_time)) {
audio_syncts_resample_suspend(dec->syncts);
} else {
audio_syncts_resample_resume(dec->syncts);
dec->mix_ch_event_params[2] = timestamp;
dec->ts_start = 2;
}
}
#endif
}
static void audio_filter_resume_decoder(void *priv)
{
struct audio_decoder *decoder = (struct audio_decoder *)priv;
audio_decoder_resume(decoder);
}
static int a2dp_decoder_slience_plc_filter(struct a2dp_dec_hdl *dec, void *data, int len)
{
if (len == 0) {
a2dp_decoder_stream_free(dec, NULL);
if (!dec->stream_error) {
dec->stream_error = A2DP_STREAM_DECODE_ERR;
dec->repair = 1;
}
return 0;
}
if (dec->stream_error) {
memset(data, 0x0, len);
}
#if TCFG_USER_TWS_ENABLE
u8 tws_pairing = 0;
if (dec->preempt || tws_network_audio_was_started()) {
/*a2dp播放中副机加入声音淡入进去*/
tws_network_local_audio_start();
dec->preempt = 0;
tws_pairing = 1;
memset(data, 0x0, len);
dec->slience_frames = 30;
}
#endif
#if A2DP_AUDIO_PLC_ENABLE
if (dec->plc_ops) {
if (dec->slience_frames) {
dec->plc_ops->run(dec->plc_mem, data, data, len >> 1, 2);
} else if (dec->stream_error) {
dec->plc_ops->run(dec->plc_mem, data, data, len >> 1, dec->repair ? 1 : 2);
dec->repair = 0;
} else {
dec->plc_ops->run(dec->plc_mem, data, data, len >> 1, 0);
}
}
#endif
return len;
}
static int a2dp_dec_output_handler(struct audio_decoder *decoder, s16 *data, int len, void *priv)
{
int wlen = 0;
struct a2dp_dec_hdl *dec = container_of(decoder, struct a2dp_dec_hdl, decoder);
if (!dec->remain) {
wlen = a2dp_decoder_slience_plc_filter(dec, data, len);
if (wlen < len) {
return wlen;
}
#if (SYS_VOL_TYPE == VOL_TYPE_DIGITAL)
audio_digital_vol_run(dec->dvol, data, len);
#endif
#if TCFG_DIG_PHASE_INVERTER_EN
digital_phase_inverter_s16(data, len);
#endif/*TCFG_DIG_PHASE_INVERTER_EN*/
#if AUDIO_SURROUND_CONFIG
if (dec->sur && dec->sur->surround) {
audio_surround_run(dec->sur->surround, data, len);
}
#endif/*AUDIO_SURROUND_CONFIG*/
#if AUDIO_VBASS_CONFIG
if (dec->vbass) {
audio_vbass_run(dec->vbass, data, len);
}
#endif/*AUDIO_VBASS_CONFIG*/
#if TCFG_EQ_ENABLE&&TCFG_BT_MUSIC_EQ_ENABLE
if (dec->eq_drc && !dec->eq_drc->async) {
eq_drc_run(dec->eq_drc, data, len);//同步eq
}
#endif//TCFG_BT_MUSIC_EQ_ENABLE
a2dp_output_before_syncts_handler(dec, data, len);
}
#if AUDIO_CODEC_SUPPORT_SYNC
if (dec->syncts) {
int wlen = audio_syncts_frame_filter(dec->syncts, data, len);
if (wlen < len) {
audio_syncts_trigger_resume(dec->syncts, (void *)decoder, audio_filter_resume_decoder);
}
dec->remain = wlen < len ? 1 : 0;
return wlen;
}
#endif
wlen = a2dp_output_after_syncts_filter(dec, data, len);
dec->remain = wlen < len ? 1 : 0;
return wlen;
}
static int a2dp_dec_post_handler(struct audio_decoder *decoder)
{
return 0;
}
static const struct audio_dec_handler a2dp_dec_handler = {
.dec_probe = a2dp_dec_probe_handler,
.dec_output = a2dp_dec_output_handler,
.dec_post = a2dp_dec_post_handler,
};
void a2dp_dec_close();
static void a2dp_dec_release()
{
audio_decoder_task_del_wait(&decode_task, &a2dp_dec->wait);
a2dp_drop_frame_stop();
local_irq_disable();
free(a2dp_dec);
a2dp_dec = NULL;
local_irq_enable();
}
static void a2dp_dec_event_handler(struct audio_decoder *decoder, int argc, int *argv)
{
switch (argv[0]) {
case AUDIO_DEC_EVENT_END:
puts("AUDIO_DEC_EVENT_END\n");
a2dp_dec_close();
break;
}
}
#if ESCO_DRC_EN
struct drc_ch esco_drc_p = {0};
int esco_drc_get_filter_info(struct audio_drc_filter_info *info)
{
int th = 0;//db -60db~0db,限幅器阈值
int threshold = round(pow(10.0, th / 20.0) * 32768);
esco_drc_p.nband = 1;
esco_drc_p.type = 1;
esco_drc_p._p.limiter[0].attacktime = 5;
esco_drc_p._p.limiter[0].releasetime = 500;
esco_drc_p._p.limiter[0].threshold[0] = threshold;
esco_drc_p._p.limiter[0].threshold[1] = 32768;
info->R_pch = info->pch = &esco_drc_p;
return 0;
}
#endif
static void a2dp_decoder_delay_time_setup(struct a2dp_dec_hdl *dec)
{
#if TCFG_USER_TWS_ENABLE
int a2dp_low_latency = tws_api_get_low_latency_state();
#endif
if (a2dp_low_latency) {
a2dp_delay_time = a2dp_dec->coding_type == AUDIO_CODING_AAC ? CONFIG_A2DP_DELAY_TIME_LO : CONFIG_A2DP_SBC_DELAY_TIME_LO;
} else {
a2dp_delay_time = CONFIG_A2DP_DELAY_TIME;
}
a2dp_max_interval = 0;
dec->delay_time = a2dp_delay_time;
dec->detect_timer = sys_timer_add((void *)dec, a2dp_stream_stability_detect, A2DP_FLUENT_DETECT_INTERVAL);
}
static int a2dp_decoder_syncts_setup(struct a2dp_dec_hdl *dec)
{
int err = 0;
#if AUDIO_CODEC_SUPPORT_SYNC
struct audio_syncts_params params = {0};
params.nch = dec->ch;
#if defined(TCFG_AUDIO_OUTPUT_IIS) && TCFG_AUDIO_OUTPUT_IIS
params.pcm_device = PCM_OUTSIDE_DAC;
params.rout_sample_rate = TCFG_IIS_SAMPLE_RATE;
#elif defined(TCFG_AUDIO_MUSIC_SIDETONE_ENABLE) && TCFG_AUDIO_MUSIC_SIDETONE_ENABLE
params.pcm_device = PCM_INSIDE_DAC;
params.rout_sample_rate = FIXED_SAMPLE_RATE;
#else
params.pcm_device = PCM_INSIDE_DAC;
params.rout_sample_rate = dec->sample_rate;
#endif
params.network = AUDIO_NETWORK_BT2_1;
params.rin_sample_rate = dec->sample_rate;
params.priv = dec;
params.factor = TIME_US_FACTOR;
params.output = a2dp_output_after_syncts_filter;
bt_audio_sync_nettime_select(0);//0 - a2dp主机1 - tws, 2 - BLE
a2dp_decoder_update_base_time(dec);
dec->ts_handle = a2dp_audio_timestamp_create(dec->sample_rate, dec->base_time, TIME_US_FACTOR);
err = audio_syncts_open(&dec->syncts, &params);
if (!err) {
dec->mix_ch_event_params[0] = (u32)&dec->mix_ch;
dec->mix_ch_event_params[1] = (u32)dec->syncts;
dec->mix_ch_event_params[2] = dec->base_time * 625 * TIME_US_FACTOR;
audio_mixer_ch_set_event_handler(&dec->mix_ch, (void *)dec->mix_ch_event_params, audio_mix_ch_event_handler);
}
dec->sync_step = 0;
#endif
return err;
}
static void a2dp_decoder_syncts_free(struct a2dp_dec_hdl *dec)
{
#if AUDIO_CODEC_SUPPORT_SYNC
if (dec->ts_handle) {
a2dp_audio_timestamp_close(dec->ts_handle);
dec->ts_handle = NULL;
}
if (dec->syncts) {
audio_syncts_close(dec->syncts);
dec->syncts = NULL;
}
#endif
}
static int a2dp_decoder_plc_setup(struct a2dp_dec_hdl *dec)
{
#if A2DP_AUDIO_PLC_ENABLE
int plc_mem_size;
dec->plc_ops = get_lfaudioPLC_api();
plc_mem_size = dec->plc_ops->need_buf(dec->ch); // 3660bytes请衡量是否使用该空间换取PLC处理
dec->plc_mem = malloc(plc_mem_size);
if (!dec->plc_mem) {
dec->plc_ops = NULL;
return -ENOMEM;
}
dec->plc_ops->open(dec->plc_mem, dec->ch, a2dp_low_latency ? 0 : 4);
#endif
return 0;
}
static void a2dp_decoder_plc_free(struct a2dp_dec_hdl *dec)
{
#if A2DP_AUDIO_PLC_ENABLE
if (dec->plc_mem) {
free(dec->plc_mem);
dec->plc_mem = NULL;
}
#endif
}
static void a2dp_decoder_match_system_clock(struct a2dp_dec_hdl *dec)
{
#if 0
/*
* A2DP解码时钟设置
* 1、普通设置
* 开始解码: clk_set_sys_lock(xxx, 0);
* 退出解码: clk_set_sys_lock(xxx, 0);
* 2、特殊设置使用wav或其他提示音并带有操作开始/暂停 A2DP音频
* 开始解码: clk_set_sys_lock(xxx, 1);
* 退出解码: clk_set_sys_lock(xxx, 2);
*/
if (dec->coding_type == AUDIO_CODING_SBC) {
#if (TCFG_BT_MUSIC_EQ_ENABLE && ((EQ_SECTION_MAX >= 10) && AUDIO_OUT_EFFECT_ENABLE))
clk_set_sys_lock(SYS_64M, 0) ;
#elif (TCFG_BT_MUSIC_EQ_ENABLE && ((EQ_SECTION_MAX >= 10) || AUDIO_OUT_EFFECT_ENABLE))
clk_set_sys_lock(SYS_48M, 0) ;
#else
#if (!TCFG_AUDIO_ANC_ENABLE)
clk_set_sys_lock(SYS_24M, 0) ;
#endif
#endif
} else if (dec->coding_type == AUDIO_CODING_AAC) {
#if (TCFG_BT_MUSIC_EQ_ENABLE && ((EQ_SECTION_MAX >= 10) || AUDIO_OUT_EFFECT_ENABLE))
clk_set_sys_lock(SYS_64M, 0) ;
#else
clk_set_sys_lock(SYS_48M, 0) ;
#endif
}
#if (AUDIO_VBASS_CONFIG || AUDIO_SURROUND_CONFIG)
clk_set_sys_lock(SYS_64M, 0) ;
#endif
#else
#if TCFG_AUDIO_MUSIC_SIDETONE_ENABLE
audio_codec_clock_set(AUDIO_A2DP_MODE, dec->coding_type, 0); //开启mic监听功能时钟设置为解码叠加的状态
#else
audio_codec_clock_set(AUDIO_A2DP_MODE, dec->coding_type, dec->wait.preemption);
#endif /* TCFG_AUDIO_MUSIC_SIDETONE_ENABLE */
#endif
}
static void a2dp_decoder_eq_drc_filter_setup(struct a2dp_dec_hdl *dec, struct audio_fmt *fmt)
{
#if TCFG_EQ_ENABLE&&TCFG_BT_MUSIC_EQ_ENABLE
u8 drc_en = 0;
#if TCFG_DRC_ENABLE&&TCFG_BT_MUSIC_DRC_ENABLE
drc_en = 1;
#endif//TCFG_BT_MUSIC_DRC_ENABLE
#if defined(AUDIO_GAME_EFFECT_CONFIG) && AUDIO_GAME_EFFECT_CONFIG
if (a2dp_low_latency) {
drc_en |= BIT(1);
}
#endif /*AUDIO_GAME_EFFECT_CONFIG*/
dec->eq_drc = dec_eq_drc_setup(&dec->mix_ch, (eq_output_cb)audio_mixer_ch_write, fmt->sample_rate, dec->ch, a2dp_low_latency ? 0 : 1, drc_en);
#endif//TCFG_BT_MUSIC_EQ_ENABLE
}
void a2dp_decoder_sample_detect_setup(struct a2dp_dec_hdl *dec)
{
dec->sample_detect = a2dp_sample_detect_open(dec->sample_rate, dec->coding_type);
}
void a2dp_decoder_sample_detect_free(struct a2dp_dec_hdl *dec)
{
if (dec->sample_detect) {
a2dp_sample_detect_close(dec->sample_detect);
dec->sample_detect = NULL;
}
}
void audio_overlay_load_code(u32 type);
int a2dp_dec_start()
{
int err;
struct audio_fmt *fmt;
enum audio_channel channel;
struct a2dp_dec_hdl *dec = a2dp_dec;
if (!a2dp_dec) {
return -EINVAL;
}
a2dp_drop_frame_stop();
puts("a2dp_dec_start: in\n");
if (a2dp_dec->coding_type == AUDIO_CODING_AAC) {
audio_overlay_load_code(a2dp_dec->coding_type);
}
err = audio_decoder_open(&dec->decoder, &a2dp_input, &decode_task);
if (err) {
goto __err1;
}
dec->channel = AUDIO_CH_MAX;
audio_decoder_set_handler(&dec->decoder, &a2dp_dec_handler);
audio_decoder_set_event_handler(&dec->decoder, a2dp_dec_event_handler, 0);
if (a2dp_dec->coding_type != a2dp_input.coding_type) {
struct audio_fmt f = {0};
f.coding_type = a2dp_dec->coding_type;
err = audio_decoder_set_fmt(&dec->decoder, &f);
if (err) {
goto __err2;
}
}
err = audio_decoder_get_fmt(&dec->decoder, &fmt);
if (err) {
goto __err2;
}
if (fmt->sample_rate == 0) {
log_w("A2DP stream maybe error\n");
goto __err2;
}
//dac_hdl.dec_channel_num = fmt->channel;
dec->sample_rate = fmt->sample_rate;
a2dp_decoder_delay_time_setup(dec);
set_source_sample_rate(fmt->sample_rate);
a2dp_dec_set_output_channel(dec);
/*audio_dac_set_protect_time(&dac_hdl, 3, dec, NULL);//a2dp_stream_underrun_feedback);*/
audio_mixer_ch_open(&dec->mix_ch, &mixer);
#if defined(TCFG_AUDIO_OUTPUT_IIS) && TCFG_AUDIO_OUTPUT_IIS
audio_mixer_ch_set_sample_rate(&dec->mix_ch, TCFG_IIS_SAMPLE_RATE);
#elif defined(TCFG_AUDIO_MUSIC_SIDETONE_ENABLE) && TCFG_AUDIO_MUSIC_SIDETONE_ENABLE
audio_mixer_ch_set_sample_rate(&dec->mix_ch, FIXED_SAMPLE_RATE);
#else
audio_mixer_ch_set_sample_rate(&dec->mix_ch, fmt->sample_rate);
#endif
audio_mixer_ch_set_resume_handler(&dec->mix_ch, (void *)&dec->decoder, (void (*)(void *))audio_decoder_resume);
app_audio_state_switch(APP_AUDIO_STATE_MUSIC, get_max_sys_vol());
#if (SYS_VOL_TYPE == VOL_TYPE_DIGITAL)
a2dp_dec->dvol = audio_digital_vol_open(app_audio_get_volume(APP_AUDIO_STATE_MUSIC), SYS_MAX_VOL, 2);
#endif
a2dp_decoder_sample_detect_setup(dec);
a2dp_decoder_eq_drc_filter_setup(dec, fmt);
#if AUDIO_SURROUND_CONFIG
dec->sur = audio_surround_setup(dec->channel, a2dp_surround_eff);
#endif//AUDIO_SURROUND_CONFIG
#if AUDIO_VBASS_CONFIG
dec->vbass = audio_vbass_setup(fmt->sample_rate, dec->ch);
#endif//AUDIO_VBASS_CONFIG
a2dp_decoder_syncts_setup(dec);
a2dp_decoder_plc_setup(dec);
dec->remain = 0;
dec->stream_error = 0;
a2dp_decoder_match_system_clock(dec);
#if A2DP_KSR_AEC_ENABLE
extern int KSR_aec_open(u16 in_sr, u16 ref_sr);
KSR_aec_open(16000, A2DP_TO_PCM_DEVICE_FORMAT);
#endif/*A2DP_KSR_AEC_ENABLE*/
err = audio_decoder_start(&dec->decoder);
if (err) {
goto __err3;
}
dec->start = 1;
return 0;
__err3:
audio_mixer_ch_close(&a2dp_dec->mix_ch);
__err2:
audio_decoder_close(&dec->decoder);
__err1:
a2dp_dec_release();
return err;
}
static int __a2dp_audio_res_close(void)
{
a2dp_dec->start = 0;
if (a2dp_dec->detect_timer) {
sys_timer_del(a2dp_dec->detect_timer);
}
a2dp_decoder_sample_detect_free(a2dp_dec);
audio_decoder_close(&a2dp_dec->decoder);
audio_mixer_ch_close(&a2dp_dec->mix_ch);
a2dp_decoder_syncts_free(a2dp_dec);
a2dp_decoder_plc_free(a2dp_dec);
a2dp_decoder_stream_free(a2dp_dec, NULL);
#if TCFG_EQ_ENABLE&&TCFG_BT_MUSIC_EQ_ENABLE
if (a2dp_dec->eq_drc) {
dec_eq_drc_free(a2dp_dec->eq_drc);
a2dp_dec->eq_drc = NULL;
}
#endif//TCFG_BT_MUSIC_EQ_ENABLE
#if AUDIO_SURROUND_CONFIG
if (a2dp_dec->sur) {
audio_surround_free(a2dp_dec->sur);
a2dp_dec->sur = NULL;
}
#endif//AUDIO_SURROUND_CONFIG
#if AUDIO_VBASS_CONFIG
if (a2dp_dec->vbass) {
audio_vbass_free(a2dp_dec->vbass);
a2dp_dec->vbass = NULL;
}
#endif//AUDIO_VBASS_CONFIG
#if A2DP_KSR_AEC_ENABLE
extern void KSR_aec_close(void);
KSR_aec_close();
#endif/*A2DP_KSR_AEC_ENABLE*/
#if (SYS_VOL_TYPE == VOL_TYPE_DIGITAL)
audio_digital_vol_close(a2dp_dec->dvol);
a2dp_dec->dvol = NULL;
#endif
#if 0
clk_set_sys_lock(BT_NORMAL_HZ, 0);
#else
audio_codec_clock_del(AUDIO_A2DP_MODE);
#endif
a2dp_dec->preempt = 1;
app_audio_state_exit(APP_AUDIO_STATE_MUSIC);
return 0;
}
static int a2dp_wait_res_handler(struct audio_res_wait *wait, int event)
{
int err = 0;
printf("a2dp_wait_res_handler: %d\n", event);
if (event == AUDIO_RES_GET) {
err = a2dp_dec_start();
} else if (event == AUDIO_RES_PUT) {
if (a2dp_dec->start) {
__a2dp_audio_res_close();
a2dp_drop_frame_start();
}
}
return err;
}
#define A2DP_CODEC_SBC 0x00
#define A2DP_CODEC_MPEG12 0x01
#define A2DP_CODEC_MPEG24 0x02
int __a2dp_dec_open(int media_type, u8 resume)
{
struct a2dp_dec_hdl *dec;
if (strcmp(os_current_task(), "app_core") != 0) {
log_e("a2dp dec open in task : %s\n", os_current_task());
}
#if TCFG_AUDIO_ANC_ENABLE
#ifdef CONFIG_ANC_OVERLAY
if (anc_train_open_query()) {
printf("anc_train_open,suspend a2dp_dec\n");
if (drop_a2dp_timer == 0) {
drop_a2dp_timer = sys_timer_add(NULL, __a2dp_drop_frame, 50);
}
return 0;
}
#endif/*CONFIG_ANC_OVERLAY*/
#endif /*TCFG_AUDIO_ANC_ENABLE*/
if (a2dp_suspend) {
if (tws_api_get_role() == TWS_ROLE_MASTER) {
if (drop_a2dp_timer == 0) {
drop_a2dp_timer = sys_timer_add(NULL,
a2dp_media_clear_packet_before_seqn, 100);
}
}
return 0;
}
if (a2dp_dec) {
return 0;
}
media_type = a2dp_media_get_codec_type();
printf("a2dp_dec_open: %d\n", media_type);
dec = zalloc(sizeof(*dec));
if (!dec) {
return -ENOMEM;
}
switch (media_type) {
case A2DP_CODEC_SBC:
printf("a2dp_media_type:SBC");
dec->coding_type = AUDIO_CODING_SBC;
break;
case A2DP_CODEC_MPEG24:
printf("a2dp_media_type:AAC");
dec->coding_type = AUDIO_CODING_AAC;
break;
default:
printf("a2dp_media_type unsupoport:%d", media_type);
free(dec);
return -EINVAL;
}
#if TCFG_USER_TWS_ENABLE
if (CONFIG_LOW_LATENCY_ENABLE) {
a2dp_low_latency = tws_api_get_low_latency_state();
}
#endif
a2dp_dec = dec;
dec->preempt = resume ? 1 : 0;
dec->wait.priority = 1;
dec->wait.preemption = 1;
dec->wait.handler = a2dp_wait_res_handler;
audio_decoder_task_add_wait(&decode_task, &dec->wait);
if (a2dp_dec && (a2dp_dec->start == 0)) {
a2dp_drop_frame_start();
}
return 0;
}
int a2dp_dec_open(int media_type)
{
return __a2dp_dec_open(media_type, 0);
}
void a2dp_dec_close()
{
if (!a2dp_dec) {
if (CONFIG_LOW_LATENCY_ENABLE) {
a2dp_low_latency_seqn = 0;
}
if (drop_a2dp_timer) {
sys_timer_del(drop_a2dp_timer);
drop_a2dp_timer = 0;
}
return;
}
if (a2dp_dec->start) {
__a2dp_audio_res_close();
}
a2dp_dec_release();
puts("a2dp_dec_close: exit\n");
}
static void a2dp_low_latency_clear_a2dp_packet(u8 *data, int len, int rx)
{
if (rx) {
a2dp_low_latency_seqn = (data[0] << 8) | data[1];
}
}
REGISTER_TWS_FUNC_STUB(audio_dec_clear_a2dp_packet) = {
.func_id = 0x132A6578,
.func = a2dp_low_latency_clear_a2dp_packet,
};
static void low_latency_drop_a2dp_frame(void *p)
{
int len;
/*y_printf("low_latency_drop_a2dp_frame\n");*/
if (a2dp_low_latency_seqn == 0) {
a2dp_media_clear_packet_before_seqn(0);
return;
}
while (1) {
u8 *packet = a2dp_media_fetch_packet(&len, NULL);
if (!packet) {
return;
}
u16 seqn = (packet[2] << 8) | packet[3];
if (seqn_after(seqn, a2dp_low_latency_seqn)) {
printf("clear_end: %d\n", seqn);
break;
}
a2dp_media_free_packet(packet);
/*printf("clear: %d\n", seqn);*/
}
if (drop_a2dp_timer) {
sys_timer_del(drop_a2dp_timer);
drop_a2dp_timer = 0;
}
int type = a2dp_media_get_codec_type();
if (type >= 0) {
/*a2dp_dec_open(type);*/
__a2dp_dec_open(type, 1);
}
if (a2dp_low_latency == 0) {
tws_api_auto_role_switch_enable();
}
printf("a2dp_delay: %d\n", a2dp_media_get_remain_play_time(1));
}
int earphone_a2dp_codec_set_low_latency_mode(int enable, int msec)
{
int ret = 0;
int len, err;
if (CONFIG_LOW_LATENCY_ENABLE == 0) {
return -EINVAL;
}
if (esco_dec) {
return -EINVAL;
}
if (drop_a2dp_timer) {
return -EINVAL;
}
if (a2dp_suspend) {
return -EINVAL;
}
a2dp_low_latency = enable;
a2dp_low_latency_seqn = 0;
r_printf("a2dp_low_latency: %d, %d, %d\n", a2dp_dec->seqn, a2dp_delay_time, enable);
if (!a2dp_dec || a2dp_dec->start == 0) {
#if TCFG_USER_TWS_ENABLE
tws_api_low_latency_enable(enable);
#endif
return 0;
}
if (a2dp_dec->coding_type == AUDIO_CODING_SBC) {
a2dp_low_latency_seqn = a2dp_dec->seqn + (msec + a2dp_delay_time) / 15;
} else {
a2dp_low_latency_seqn = a2dp_dec->seqn + (msec + a2dp_delay_time) / 20;
}
#if TCFG_USER_TWS_ENABLE
u8 data[2];
data[0] = a2dp_low_latency_seqn >> 8;
data[1] = a2dp_low_latency_seqn;
err = tws_api_send_data_to_slave(data, 2, 0x132A6578);
if (err == -ENOMEM) {
return -EINVAL;
}
#endif
a2dp_dec_close();
a2dp_media_clear_packet_before_seqn(0);
#if TCFG_USER_TWS_ENABLE
if (enable) {
tws_api_auto_role_switch_disable();
}
tws_api_low_latency_enable(enable);
#endif
drop_a2dp_timer = sys_timer_add(NULL, low_latency_drop_a2dp_frame, 40);
/*r_printf("clear_to_seqn: %d\n", a2dp_low_latency_seqn);*/
return 0;
}
int earphone_a2dp_codec_get_low_latency_mode()
{
#if TCFG_USER_TWS_ENABLE
return tws_api_get_low_latency_state();
#endif
return a2dp_low_latency;
}
int a2dp_tws_dec_suspend(void *p)
{
r_printf("a2dp_tws_dec_suspend\n");
/*mem_stats();*/
if (a2dp_suspend) {
return -EINVAL;
}
a2dp_suspend = 1;
if (a2dp_dec) {
a2dp_dec_close();
a2dp_media_clear_packet_before_seqn(0);
if (tws_api_get_role() == 0) {
drop_a2dp_timer = sys_timer_add(NULL, a2dp_media_clear_packet_before_seqn, 100);
}
}
int err = audio_decoder_fmt_lock(&decode_task, AUDIO_CODING_AAC);
if (err) {
log_e("AAC_dec_lock_faild\n");
}
return err;
}
void a2dp_tws_dec_resume(void)
{
r_printf("a2dp_tws_dec_resume\n");
if (a2dp_suspend) {
a2dp_suspend = 0;
if (drop_a2dp_timer) {
sys_timer_del(drop_a2dp_timer);
drop_a2dp_timer = 0;
}
audio_decoder_fmt_unlock(&decode_task, AUDIO_CODING_AAC);
int type = a2dp_media_get_codec_type();
printf("codec_type: %d\n", type);
if (type >= 0) {
if (tws_api_get_role() == 0) {
a2dp_media_clear_packet_before_seqn(0);
}
a2dp_resume_time = jiffies + msecs_to_jiffies(80);
/*a2dp_dec_open(type);*/
__a2dp_dec_open(type, 1);
}
}
}
static const u8 msbc_mute_data[] = {
0xAD, 0x00, 0x00, 0xC5, 0x00, 0x00, 0x00, 0x00, 0x77, 0x6D, 0xB6, 0xDD, 0xDB, 0x6D, 0xB7, 0x76,
0xDB, 0x6D, 0xDD, 0xB6, 0xDB, 0x77, 0x6D, 0xB6, 0xDD, 0xDB, 0x6D, 0xB7, 0x76, 0xDB, 0x6D, 0xDD,
0xB6, 0xDB, 0x77, 0x6D, 0xB6, 0xDD, 0xDB, 0x6D, 0xB7, 0x76, 0xDB, 0x6D, 0xDD, 0xB6, 0xDB, 0x77,
0x6D, 0xB6, 0xDD, 0xDB, 0x6D, 0xB7, 0x76, 0xDB, 0x6C, 0x00,
};
static int headcheck(u8 *buf)
{
int sync_word = buf[0] | ((buf[1] & 0x0f) << 8);
return (sync_word == 0x801) && (buf[2] == 0xAD);
}
static int esco_dump_rts_info(struct rt_stream_info *pkt)
{
u32 hash = 0xffffffff;
int read_len = 0;
pkt->baddr = lmp_private_get_esco_packet(&read_len, &hash);
pkt->seqn = hash;
/* printf("hash0=%d,%d ",hash,pkt->baddr ); */
if (pkt->baddr && read_len) {
pkt->remain_len = lmp_private_get_esco_remain_buffer_size();
pkt->data_len = lmp_private_get_esco_data_len();
return 0;
}
if (read_len == -EINVAL) {
//puts("----esco close\n");
return -EINVAL;
}
if (read_len < 0) {
return -ENOMEM;
}
return ENOMEM;
}
static int esco_dec_get_frame(struct audio_decoder *decoder, u8 **frame)
{
int len = 0;
u32 hash = 0;
struct esco_dec_hdl *dec = container_of(decoder, struct esco_dec_hdl, decoder);
__again:
if (dec->frame) {
int len = dec->frame_len - dec->offset;
if (len > dec->esco_len - dec->data_len) {
len = dec->esco_len - dec->data_len;
}
/*memcpy((u8 *)dec->data + dec->data_len, msbc_mute_data, sizeof(msbc_mute_data));*/
memcpy((u8 *)dec->data + dec->data_len, dec->frame + dec->offset, len);
dec->offset += len;
dec->data_len += len;
if (dec->offset == dec->frame_len) {
lmp_private_free_esco_packet(dec->frame);
dec->frame = NULL;
}
}
if (dec->data_len < dec->esco_len) {
dec->frame = lmp_private_get_esco_packet(&len, &hash);
/* printf("hash1=%d,%d ",hash,dec->frame ); */
if (len <= 0) {
printf("rlen=%d ", len);
return -EIO;
}
#if AUDIO_CODEC_SUPPORT_SYNC
u32 timestamp;
if (dec->ts_handle) {
timestamp = esco_audio_timestamp_update(dec->ts_handle, hash);
if (dec->syncts && (((hash - dec->hash) & 0x7ffffff) == dec->frame_time)) {
audio_syncts_next_pts(dec->syncts, timestamp);
}
dec->hash = hash;
if (!dec->ts_start) {
dec->ts_start = 1;
dec->mix_ch_event_params[2] = timestamp;
}
}
#endif
#if (defined(TCFG_PHONE_MESSAGE_ENABLE) && (TCFG_PHONE_MESSAGE_ENABLE))
phone_message_enc_write(dec->frame + 2, len - 2);
#endif
dec->offset = 0;
dec->frame_len = len;
goto __again;
}
*frame = (u8 *)dec->data;
return dec->esco_len;
}
static void esco_dec_put_frame(struct audio_decoder *decoder, u8 *frame)
{
struct esco_dec_hdl *dec = container_of(decoder, struct esco_dec_hdl, decoder);
dec->data_len = 0;
/*lmp_private_free_esco_packet((void *)frame);*/
}
static const struct audio_dec_input esco_input = {
.coding_type = AUDIO_CODING_MSBC,
.data_type = AUDIO_INPUT_FRAME,
.ops = {
.frame = {
.fget = esco_dec_get_frame,
.fput = esco_dec_put_frame,
}
}
};
u32 lmp_private_clear_sco_packet(u8 clear_num);
static void esco_dec_clear_all_packet(struct esco_dec_hdl *dec)
{
lmp_private_clear_sco_packet(0xff);
}
static int esco_dec_rx_delay_monitor(struct audio_decoder *decoder, struct rt_stream_info *info)
{
struct esco_dec_hdl *dec = container_of(decoder, struct esco_dec_hdl, decoder);
#if 0
if (!dec->sync_step) {
if (info->data_len <= 0) {
return -EAGAIN;
}
#if TCFG_USER_TWS_ENABLE
int state = tws_api_get_tws_state();
if (state & TWS_STA_SIBLING_CONNECTED) {
if (tws_api_get_role() == TWS_ROLE_SLAVE) {
audio_dac_sound_reset(&dac_hdl, 150);
}
}
#endif/*TCFG_USER_TWS_ENABLE*/
dec->sync_step = 2;
}
if (info->data_len <= 120) {
info->distance_time = -15;
} else if (info->data_len > 240) {
info->distance_time = 15;
}
#endif
/*printf("%d - %d\n", info->data_len, info->remain_len);*/
return 0;
}
static int esco_dec_probe_handler(struct audio_decoder *decoder)
{
struct esco_dec_hdl *dec = container_of(decoder, struct esco_dec_hdl, decoder);
int err = 0;
int find_packet = 0;
struct rt_stream_info rts_info = {0};
err = esco_dump_rts_info(&rts_info);
if (err == -EINVAL) {
return err;
}
if (err || !dec->enc_start) {
audio_decoder_suspend(decoder, 0);
return -EAGAIN;
}
#if TCFG_USER_TWS_ENABLE
if (tws_network_audio_was_started()) {
/*清除从机声音加入标志*/
dec->slience_frames = 20;
tws_network_local_audio_start();
}
#endif
if (dec->preempt) {
dec->preempt = 0;
dec->slience_frames = 20;
}
return err;
}
static int audio_esco_int2short_convert_output(void *priv, s16 *data, int len)
{
/* put_buf(data,len); */
return audio_dac_write(&dac_hdl, data, len);
}
static int audio_esco_short2int_convert_output(void *priv, void *data, int len)
{
#if 0//AUDIO_CODEC_SUPPORT_SYNC
if (audio_sync) {
audio_decoder_sync_run(audio_sync, data, len);
#if TCFG_PHONE_EQ_ENABLE
} else if (esco_eq) {
return audio_eq_run(esco_eq, data, len);
#endif
} else if (int2short_convert) {
/*return int2short_convert_run(int2short_convert, data, len);*/
}
#endif
return len;
}
/*level:0~15*/
static const u16 esco_dvol_tab[] = {
0, //0
111,//1
161,//2
234,//3
338,//4
490,//5
708,//6
1024,//7
1481,//8
2142,//9
3098,//10
4479,//11
6477,//12
9366,//13
14955,//14
16384 //15
};
#if TCFG_ESCO_DL_NS_ENABLE
#include "commproc_ns.h"
#define NS_FRAME_POINTS 160
#define NS_FRAME_SIZE (NS_FRAME_POINTS << 1)
typedef struct {
s16 out[NS_FRAME_POINTS];
s16 in[512];
cbuffer_t cbuf;
u16 offset;
} dl_ns_t;
dl_ns_t *dl_ns = NULL;
int esco_dl_ns_run(short *data, u16 len)
{
int wlen = cbuf_write(&dl_ns->cbuf, data, len);
if (wlen != len) {
printf("dl_cbuf full\n");
}
if (dl_ns->cbuf.data_len >= NS_FRAME_SIZE) {
cbuf_read(&dl_ns->cbuf, dl_ns->out, NS_FRAME_SIZE);
/*接通的时候再开始做降噪*/
if (get_call_status() == BT_CALL_ACTIVE) {
noise_suppress_run(dl_ns->out, dl_ns->out, NS_FRAME_POINTS);
}
return NS_FRAME_SIZE;
} else {
return 0;
}
}
static noise_suppress_param ns_para = {
.wideband = 1,
.mode = 0,
.NoiseLevel = 1.0e2f,
.AggressFactor = 1.25f,
.MinSuppress = 0.04f,
};
int esco_dl_ns_open(u16 sr)
{
dl_ns = zalloc(sizeof(dl_ns_t));
cbuf_init(&dl_ns->cbuf, dl_ns->in, sizeof(dl_ns->in));
if (sr == 8000) {
ns_para.wideband = 1;
}
noise_suppress_open(&ns_para);
float lowcut = -60.f;
noise_suppress_config(NS_CMD_LOWCUTTHR, 0, &lowcut);
printf("esco_dl_ns_open ok\n");
return 0;
}
int esco_dl_ns_close(void)
{
noise_suppress_close();
if (dl_ns) {
free(dl_ns);
dl_ns = NULL;
}
printf("esco_dl_ns_close ok\n");
return 0;
}
#endif/*TCFG_ESCO_DL_NS_ENABLE*/
#define MONO_TO_DUAL_POINTS 30
//////////////////////////////////////////////////////////////////////////////
static inline void audio_pcm_mono_to_dual(s16 *dual_pcm, s16 *mono_pcm, int points)
{
s16 *mono = mono_pcm;
int i = 0;
u8 j = 0;
for (i = 0; i < points; i++, mono++) {
*dual_pcm++ = *mono;
*dual_pcm++ = *mono;
}
}
static int esco_output_after_syncts_filter(void *priv, s16 *data, int len)
{
struct esco_dec_hdl *dec = (struct esco_dec_hdl *)priv;
int wlen = 0;
#if TCFG_AUDIO_OUTPUT_IIS
wlen = audio_mixer_ch_write(&dec->mix_ch, data, len);
#else
s16 two_ch_data[MONO_TO_DUAL_POINTS * 2];
s16 point_num = 0;
u8 mono_to_dual = 0;
s16 *mono_data = (s16 *)data;
u16 remain_points = (len >> 1);
/*
*如果dac输出是双声道因为esco解码出来时单声道
*所以这里要根据dac通道确定是否做单变双
*/
#if (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_LR)
mono_to_dual = 1;
#endif
if (mono_to_dual) {
do {
point_num = MONO_TO_DUAL_POINTS;
if (point_num >= remain_points) {
point_num = remain_points;
}
audio_pcm_mono_to_dual(two_ch_data, mono_data, point_num);
int tmp_len = audio_mixer_ch_write(&dec->mix_ch, two_ch_data, point_num << 2);
wlen += tmp_len;
remain_points -= (tmp_len >> 2);
if (tmp_len < (point_num << 2)) {
break;
}
mono_data += point_num;
} while (remain_points);
wlen >>= 1;
} else {
wlen = audio_mixer_ch_write(&dec->mix_ch, data, len);
}
#endif
return wlen;
}
static int esco_dec_output_handler(struct audio_decoder *decoder, s16 *buf, int size, void *priv)
{
int wlen = 0;
struct esco_dec_hdl *dec = container_of(decoder, struct esco_dec_hdl, decoder);
int ret_len = size;
int len = size;
short *data = buf;
#if TCFG_ESCO_DL_NS_ENABLE
if (dec->remain == 0) {
wlen = esco_dl_ns_run(data, size);
//输入消耗完毕,没有输出
if (wlen == 0) {
return ret_len;
}
data = dl_ns->out;
len = wlen;
dl_ns->offset = 0;
ret_len = size;
} else {
data = dl_ns->out + (dl_ns->offset / 2);
len = dec->remain;
ret_len = 0;
}
#endif/*TCFG_ESCO_DL_NS_ENABLE*/
/*非上次残留数据,进行后处理*/
if (!dec->remain) {
if (dec->slience_frames) {
memset(data, 0x0, len);
dec->slience_frames--;
}
#if (defined(TCFG_PHONE_MESSAGE_ENABLE) && (TCFG_PHONE_MESSAGE_ENABLE))
phone_message_call_api_esco_out_data(data, len);
#endif/*TCFG_PHONE_MESSAGE_ENABLE*/
if (priv) {
audio_plc_run(data, len, *(u8 *)priv);
}
#if TCFG_DIG_PHASE_INVERTER_EN
digital_phase_inverter_s16(data, len);
#endif/*TCFG_DIG_PHASE_INVERTER_EN*/
#if (SYS_VOL_TYPE == VOL_TYPE_DIGITAL)
audio_digital_vol_run(esco_dec->dvol, data, len);
u16 dvol_val = esco_dvol_tab[app_var.aec_dac_gain];
for (u16 i = 0; i < len / 2; i++) {
s32 tmp_data = data[i];
if (tmp_data < 0) {
tmp_data = -tmp_data;
tmp_data = (tmp_data * dvol_val) >> 14;
tmp_data = -tmp_data;
} else {
tmp_data = (tmp_data * dvol_val) >> 14;
}
data[i] = tmp_data;
}
#endif/*VOL_TYPE_DIGITAL*/
#if TCFG_AUDIO_NOISE_GATE
/*来电去电铃声不做处理*/
if (get_call_status() == BT_CALL_ACTIVE) {
audio_noise_gate_run(data, data, len);
}
#endif/*TCFG_AUDIO_NOISE_GATE*/
#if TCFG_EQ_ENABLE&&TCFG_PHONE_EQ_ENABLE
eq_drc_run(dec->eq_drc, data, len);
#endif//TCFG_PHONE_EQ_ENABLE
}
#if AUDIO_CODEC_SUPPORT_SYNC
if (dec->syncts) {
wlen = audio_syncts_frame_filter(dec->syncts, data, len);
if (wlen < len) {
audio_syncts_trigger_resume(dec->syncts, (void *)decoder, audio_filter_resume_decoder);
}
goto ret_handle;
}
#endif
wlen = esco_output_after_syncts_filter(dec, data, len);
ret_handle:
int remain_len = len - wlen;
dec->remain = remain_len;
#if TCFG_ESCO_DL_NS_ENABLE
if (remain_len == 0) {
dl_ns->offset = 0;
} else {
dl_ns->offset += wlen;
}
#else
ret_len = wlen;
#endif/*TCFG_ESCO_DL_NS_ENABLE*/
return ret_len;
}
static int esco_dec_post_handler(struct audio_decoder *decoder)
{
return 0;
}
static const struct audio_dec_handler esco_dec_handler = {
.dec_probe = esco_dec_probe_handler,
.dec_output = esco_dec_output_handler,
.dec_post = esco_dec_post_handler,
};
void esco_dec_release()
{
audio_decoder_task_del_wait(&decode_task, &esco_dec->wait);
free(esco_dec);
esco_dec = NULL;
}
void esco_dec_close();
static void esco_dec_event_handler(struct audio_decoder *decoder, int argc, int *argv)
{
switch (argv[0]) {
case AUDIO_DEC_EVENT_END:
puts("AUDIO_DEC_EVENT_END\n");
esco_dec_close();
break;
}
}
static void esco_dec_set_output_channel(struct esco_dec_hdl *dec)
{
u8 dac_connect_mode = audio_dac_get_channel(&dac_hdl);
}
u16 source_sr;
void set_source_sample_rate(u16 sample_rate)
{
source_sr = sample_rate;
}
u16 get_source_sample_rate()
{
if (bt_audio_is_running()) {
return source_sr;
}
return 0;
}
#if (SYS_VOL_TYPE == VOL_TYPE_DIGITAL)
void esco_digital_vol_set(u8 vol)
{
if (esco_dec) {
audio_digital_vol_set(esco_dec->dvol, vol);
}
}
#endif/*VOL_TYPE_DIGITAL*/
int esco_dec_dac_gain_set(u8 gain)
{
app_var.aec_dac_gain = gain;
if (esco_dec) {
audio_dac_set_analog_vol(&dac_hdl, gain);
}
return 0;
}
static int esco_decoder_syncts_setup(struct esco_dec_hdl *dec)
{
int err = 0;
#if AUDIO_CODEC_SUPPORT_SYNC
#define ESCO_DELAY_TIME 60
struct audio_syncts_params params = {0};
int sample_rate = dec->decoder.fmt.sample_rate;
params.nch = dec->decoder.fmt.channel;
#if defined(TCFG_AUDIO_OUTPUT_IIS) && TCFG_AUDIO_OUTPUT_IIS
params.pcm_device = PCM_OUTSIDE_DAC;
params.rout_sample_rate = TCFG_IIS_SAMPLE_RATE;
#else
params.pcm_device = PCM_INSIDE_DAC;
params.rout_sample_rate = sample_rate;
#endif
params.network = AUDIO_NETWORK_BT2_1;
params.rin_sample_rate = sample_rate;
params.priv = dec;
params.factor = TIME_US_FACTOR;
params.output = (int (*)(void *, void *, int))esco_output_after_syncts_filter;
bt_audio_sync_nettime_select(0);//0 - 主机1 - tws, 2 - BLE
u8 frame_clkn = dec->esco_len >= 60 ? 12 : 6;
dec->ts_handle = esco_audio_timestamp_create(frame_clkn, ESCO_DELAY_TIME, TIME_US_FACTOR);
dec->frame_time = frame_clkn;
audio_syncts_open(&dec->syncts, &params);
if (!err) {
dec->mix_ch_event_params[0] = (u32)&dec->mix_ch;
dec->mix_ch_event_params[1] = (u32)dec->syncts;
audio_mixer_ch_set_event_handler(&dec->mix_ch, (void *)dec->mix_ch_event_params, audio_mix_ch_event_handler);
}
dec->ts_start = 0;
#endif
return err;
}
static void esco_decoder_syncts_free(struct esco_dec_hdl *dec)
{
#if AUDIO_CODEC_SUPPORT_SYNC
if (dec->ts_handle) {
esco_audio_timestamp_close(dec->ts_handle);
dec->ts_handle = NULL;
}
if (dec->syncts) {
audio_syncts_close(dec->syncts);
dec->syncts = NULL;
}
#endif
}
int esco_dec_start()
{
int err;
struct audio_fmt f;
enum audio_channel channel;
struct esco_dec_hdl *dec = esco_dec;
u16 mix_buf_len_fix = 240;
if (!esco_dec) {
return -EINVAL;
}
err = audio_decoder_open(&dec->decoder, &esco_input, &decode_task);
if (err) {
goto __err1;
}
audio_decoder_set_handler(&dec->decoder, &esco_dec_handler);
audio_decoder_set_event_handler(&dec->decoder, esco_dec_event_handler, 0);
if (dec->coding_type == AUDIO_CODING_MSBC) {
f.coding_type = AUDIO_CODING_MSBC;
f.sample_rate = 16000;
f.channel = 1;
} else if (dec->coding_type == AUDIO_CODING_CVSD) {
f.coding_type = AUDIO_CODING_CVSD;
f.sample_rate = 8000;
f.channel = 1;
mix_buf_len_fix = 120;
}
set_source_sample_rate(f.sample_rate);
esco_dec_set_output_channel(esco_dec);
err = audio_decoder_set_fmt(&dec->decoder, &f);
if (err) {
goto __err2;
}
/*
*虽然mix有直通的处理但是如果混合第二种声音进来的时候就会按照mix_buff
*的大小来混合输出该buff太大回导致dac没有连续的数据播放
*/
/*audio_mixer_set_output_buf(&mixer, mix_buff, sizeof(mix_buff) / 8);*/
audio_mixer_set_output_buf(&mixer, mix_buff, mix_buf_len_fix);
audio_mixer_ch_open(&dec->mix_ch, &mixer);
#if defined(TCFG_AUDIO_OUTPUT_IIS) && TCFG_AUDIO_OUTPUT_IIS
audio_mixer_ch_set_sample_rate(&dec->mix_ch, TCFG_IIS_SAMPLE_RATE);
#else
audio_mixer_ch_set_sample_rate(&dec->mix_ch, f.sample_rate);
#endif
audio_mixer_ch_set_resume_handler(&dec->mix_ch, (void *)&dec->decoder, (void (*)(void *))audio_decoder_resume);
app_audio_state_switch(APP_AUDIO_STATE_CALL, app_var.aec_dac_gain);
#if (SYS_VOL_TYPE == VOL_TYPE_DIGITAL)
esco_dec->dvol = audio_digital_vol_open(app_audio_get_volume(APP_AUDIO_STATE_CALL), 15, 4);
#endif/*VOL_TYPE_DIGITAL*/
printf("max_vol:%d,call_vol:%d", app_var.aec_dac_gain, app_audio_get_volume(APP_AUDIO_STATE_CALL));
app_audio_set_volume(APP_AUDIO_STATE_CALL, app_var.call_volume, 1);
audio_plc_open(f.sample_rate);
#if TCFG_AUDIO_NOISE_GATE
/*限幅器上限*/
#define LIMITER_THR -10000 /*-12000 = -12dB,放大1000倍,(-10000参考)*/
/*小于CONST_NOISE_GATE的当成噪声处理,防止清0近端声音*/
#define LIMITER_NOISE_GATE -40000 /*-12000 = -12dB,放大1000倍,(-30000参考)*/
/*低于噪声门限阈值的增益 */
#define LIMITER_NOISE_GAIN (0 << 30) /*(0~1)*2^30*/
audio_noise_gate_open(f.sample_rate, LIMITER_THR, LIMITER_NOISE_GATE, LIMITER_NOISE_GAIN);
#endif/*TCFG_AUDIO_NOISE_GATE*/
#if TCFG_EQ_ENABLE&&TCFG_PHONE_EQ_ENABLE
u8 drc_en = 0;
#if TCFG_DRC_ENABLE&&ESCO_DRC_EN
drc_en = 1;
#endif//ESCO_DRC_EN
dec->eq_drc = esco_eq_drc_setup(&dec->mix_ch, (eq_output_cb)audio_mixer_ch_write, f.sample_rate, f.channel, 0, drc_en);
#endif//TCFG_PHONE_EQ_ENABLE
#if AUDIO_CODEC_SUPPORT_SYNC
esco_decoder_syncts_setup(dec);
#endif/*AUDIO_CODEC_SUPPORT_SYNC*/
audio_dac_set_delay_time(&dac_hdl, 30, 50);
lmp_private_esco_suspend_resume(2);
err = audio_decoder_start(&dec->decoder);
if (err) {
goto __err3;
}
audio_out_effect_dis = 1;//通话模式关闭高低音
dec->start = 1;
dec->remain = 0;
err = audio_aec_init(f.sample_rate);
if (err) {
printf("audio_aec_init failed:%d", err);
//goto __err3;
}
#if TCFG_ESCO_DL_NS_ENABLE
esco_dl_ns_open(f.sample_rate);
#endif/*TCFG_ESCO_DL_NS_ENABLE*/
err = esco_enc_open(dec->coding_type, dec->esco_len);
if (err) {
printf("audio_enc_open failed:%d", err);
goto __err3;
}
#if TCFG_DRC_ENABLE&&ESCO_DRC_EN
clk_set_sys_lock(96 * (1000000L), 0);
#endif//ESCO_DRC_EN
audio_codec_clock_set(AUDIO_ESCO_MODE, dec->coding_type, dec->wait.preemption);
dec->enc_start = 1; //该函数所在任务优先级低可能未open编码就开始解码加入enc开始的标志防止解码过快输出
printf("esco_dec_start ok\n");
return 0;
__err3:
audio_mixer_ch_close(&dec->mix_ch);
__err2:
audio_decoder_close(&dec->decoder);
__err1:
esco_dec_release();
return err;
}
static int __esco_dec_res_close(void)
{
if (!esco_dec->start) {
return 0;
}
esco_dec->start = 0;
esco_dec->enc_start = 0;
esco_dec->preempt = 1;
audio_aec_close();
esco_enc_close();
app_audio_state_exit(APP_AUDIO_STATE_CALL);
audio_decoder_close(&esco_dec->decoder);
audio_mixer_ch_close(&esco_dec->mix_ch);
#if A2DP_RX_AND_AUDIO_DELAY
audio_dac_set_delay_time(&dac_hdl, 20, AUDIO_DAC_DELAY_TIME);
#else
audio_dac_set_delay_time(&dac_hdl, 30, AUDIO_DAC_DELAY_TIME);
#endif
#if AUDIO_CODEC_SUPPORT_SYNC
esco_decoder_syncts_free(esco_dec);
esco_dec->sync_step = 0;
esco_dec->preempt_state = DEC_PREEMTED_BY_PRIORITY;
#endif
#if TCFG_EQ_ENABLE&&TCFG_PHONE_EQ_ENABLE
if (esco_dec->eq_drc) {
esco_eq_drc_free(esco_dec->eq_drc);
esco_dec->eq_drc = NULL;
}
#endif//TCFG_PHONE_EQ_ENABLE
audio_out_effect_dis = 0;
#if (SYS_VOL_TYPE == VOL_TYPE_DIGITAL)
audio_digital_vol_close(esco_dec->dvol);
esco_dec->dvol = NULL;
#endif
#if TCFG_ESCO_DL_NS_ENABLE
esco_dl_ns_close();
#endif/*TCFG_ESCO_DL_NS_ENABLE*/
audio_plc_close();
#if TCFG_AUDIO_NOISE_GATE
audio_noise_gate_close();
#endif/*TCFG_AUDIO_NOISE_GATE*/
audio_codec_clock_del(AUDIO_ESCO_MODE);
return 0;
}
static int esco_wait_res_handler(struct audio_res_wait *wait, int event)
{
int err = 0;
printf("esco_wait_res_handler:%d", event);
if (event == AUDIO_RES_GET) {
err = esco_dec_start();
} else if (event == AUDIO_RES_PUT) {
err = __esco_dec_res_close();
lmp_private_esco_suspend_resume(1);
}
return err;
}
int esco_dec_open(void *param, u8 mute)
{
int err;
struct esco_dec_hdl *dec;
u32 esco_param = *(u32 *)param;
int esco_len = esco_param >> 16;
int codec_type = esco_param & 0x000000ff;
#if TCFG_AUDIO_MUSIC_SIDETONE_ENABLE
if (mic2pcm_dec_is_running) {
mic2pcm_dec_close(); //在来电和通话的时候 需要将mic监听功能关闭
}
#endif
#if TCFG_AUDIO_ANC_ENABLE
#ifdef CONFIG_ANC_OVERLAY
if (anc_train_open_query()) {
printf("anc_train_open,suspend esco_dec\n");
lmp_private_esco_suspend_resume(1);
return 0;
}
#endif/*CONFIG_ANC_OVERLAY*/
#endif /*TCFG_AUDIO_ANC_ENABLE*/
printf("esco_dec_open, type=%d,len=%d\n", codec_type, esco_len);
dec = zalloc(sizeof(*dec));
if (!dec) {
return -ENOMEM;
}
esco_dec = dec;
dec->esco_len = esco_len;
if (codec_type == 3) {
dec->coding_type = AUDIO_CODING_MSBC;
} else if (codec_type == 2) {
dec->coding_type = AUDIO_CODING_CVSD;
}
dec->tws_mute_en = mute;
dec->wait.priority = 2;
dec->wait.preemption = 1;
dec->wait.handler = esco_wait_res_handler;
err = audio_decoder_task_add_wait(&decode_task, &dec->wait);
if (esco_dec && esco_dec->start == 0) {
lmp_private_esco_suspend_resume(1);
}
#if AUDIO_OUTPUT_AUTOMUTE
mix_out_automute_skip(1);
#endif
return err;
}
void esco_dec_close()
{
if (!esco_dec) {
return;
}
__esco_dec_res_close();
esco_dec_release();
#if AUDIO_OUTPUT_AUTOMUTE
mix_out_automute_skip(0);
#endif
#if (defined(TCFG_PHONE_MESSAGE_ENABLE) && (TCFG_PHONE_MESSAGE_ENABLE))
phone_message_call_api_stop();
#endif
audio_mixer_set_output_buf(&mixer, mix_buff, sizeof(mix_buff));
puts("esco_dec_close: exit\n");
}
//////////////////////////////////////////////////////////////////////////////
u8 bt_audio_is_running(void)
{
return (a2dp_dec || esco_dec);
}
u8 bt_media_is_running(void)
{
return a2dp_dec != NULL;
}
u8 bt_phone_dec_is_running()
{
return esco_dec != NULL;
}
static void audio_dac_trim_init(int arg)
{
struct audio_dac_trim dac_trim;
audio_dac_do_trim(&dac_hdl, &dac_trim, 0);
syscfg_write(CFG_DAC_TRIM_INFO, (void *)&dac_trim, sizeof(dac_trim));
audio_dac_set_trim_value(&dac_hdl, &dac_trim);
}
extern u32 read_capless_DTB(void);
static u8 audio_dec_inited = 0;
//////////////////////////////////////////////////////////////////////////////
int audio_dec_init()
{
int err;
printf("audio_dec_init\n");
#if TCFG_WAV_TONE_MIX_ENABLE
wav_decoder_init();
#endif/*TCFG_WAV_TONE_MIX_ENABLE*/
tone_play_init();
#if TCFG_KEY_TONE_EN
// 按键音初始化
audio_key_tone_init();
#endif
/*os_sem_create(&dac_sem, 0);*/
err = audio_decoder_task_create(&decode_task, "audio_dec");
#if (SYS_VOL_TYPE == VOL_TYPE_DIGITAL)
audio_digital_vol_init(NULL, 0);
#endif/*VOL_TYPE_DIGITAL*/
audio_dac_init(&dac_hdl, &dac_data);
#if TCFG_AUDIO_ANC_ENABLE
audio_dac_anc_set(&dac_hdl, 1);
#endif/*TCFG_AUDIO_ANC_ENABLE*/
u32 dacr32 = read_capless_DTB();
audio_dac_set_capless_DTB(&dac_hdl, dacr32);
audio_dac_set_buff(&dac_hdl, dac_buff, sizeof(dac_buff));
#if A2DP_RX_AND_AUDIO_DELAY
audio_dac_set_delay_time(&dac_hdl, 10, AUDIO_DAC_DELAY_TIME);
#else
audio_dac_set_delay_time(&dac_hdl, 10, AUDIO_DAC_DELAY_TIME);
#endif/*A2DP_RX_AND_AUDIO_DELAY*/
audio_dac_set_analog_vol(&dac_hdl, 0);
request_irq(IRQ_AUDIO_IDX, 2, audio_irq_handler, 0);
struct audio_dac_trim dac_trim;
int len = syscfg_read(CFG_DAC_TRIM_INFO, (void *)&dac_trim, sizeof(dac_trim));
if (len != sizeof(dac_trim)) {
#if 0 //DAC 异步trim
int argv[8];
argv[0] = (int)audio_dac_trim_init;
argv[1] = 2;
do {
int err = os_taskq_post_type("audio_dec", Q_CALLBACK, 4, argv);
if (err == OS_ERR_NONE) {
break;
}
if (err != OS_Q_FULL) {
break;
}
os_time_dly(2);
} while (1);
#else
audio_dac_trim_init(0);
#endif
} else {
audio_dac_set_trim_value(&dac_hdl, &dac_trim);
}
#if TCFG_MC_BIAS_AUTO_ADJUST
mic_trim_run();
#endif/*TCFG_MC_BIAS_AUTO_ADJUST*/
audio_dac_set_fade_handler(&dac_hdl, NULL, audio_fade_in_fade_out);
#if AUDIO_CODEC_SUPPORT_SYNC
audio_sync_resample_set_filt(dac_sync_filt, sizeof(dac_sync_filt));
#endif
/*硬件SRC模块滤波器buffer设置可根据最大使用数量设置整体buffer*/
audio_src_base_filt_init(audio_src_hw_filt, sizeof(audio_src_hw_filt));
audio_mixer_open(&mixer);
audio_mixer_set_handler(&mixer, &mix_handler);
audio_mixer_set_event_handler(&mixer, mixer_event_handler);
audio_mixer_set_output_buf(&mixer, mix_buff, sizeof(mix_buff));
#if AUDIO_OUTPUT_AUTOMUTE
mix_out_automute_open();
#endif //#if AUDIO_OUTPUT_AUTOMUTE
audio_dec_inited = 1;
return err;
}
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_OUT_EFFECT_ENABLE
int audio_out_effect_stream_clear()
{
if (!audio_out_effect) {
return 0;
}
if (audio_out_effect->eq && audio_out_effect->async) {
audio_eq_async_data_clear(audio_out_effect->eq);
}
return 0;
}
void audio_out_effect_close(void)
{
if (!audio_out_effect) {
return ;
}
audio_out_eq_drc_free(audio_out_effect);
audio_out_effect = NULL;
}
int audio_out_effect_open(void *priv, u16 sample_rate)
{
audio_out_effect_close();
u8 ch_num;
#if TCFG_APP_FM_EMITTER_EN
ch_num = 2;
#else
u8 dac_connect_mode = audio_dac_get_channel(&dac_hdl);
if (dac_connect_mode == DAC_OUTPUT_LR) {
ch_num = 2;
} else {
ch_num = 1;
}
#endif//TCFG_APP_FM_EMITTER_EN
audio_out_effect = audio_out_eq_drc_setup(priv, (eq_output_cb)mix_output_handler, sample_rate, ch_num, 1, 0);
return 0;
}
int audio_out_eq_spec_set_gain(u8 idx, int gain)
{
if (!audio_out_effect) {
return -1;
}
audio_out_eq_set_gain(audio_out_effect, idx, gain);
return 0;
}
#endif//AUDIO_OUT_EFFECT_ENABLE
/*----------------------------------------------------------------------------*/
/**@brief 获取输出默认采样率
@param
@return 0: 采样率可变
@return 非0: 固定采样率
@note
*/
/*----------------------------------------------------------------------------*/
u32 audio_output_nor_rate(void)
{
#if (TCFG_IIS_ENABLE && TCFG_AUDIO_OUTPUT_IIS)
return TCFG_IIS_SAMPLE_RATE;
#endif
#if AUDIO_OUTPUT_INCLUDE_DAC
#if (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_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;
}
/*******************************************************
* Function name : app_audio_output_samplerate_select
* Description : 将输入采样率与输出采样率进行匹配对比
* Parameter :
* @sample_rate 输入采样率
* @high: 0 - 低一级采样率1 - 高一级采样率
* Return : 匹配后的采样率
********************* -HB ******************************/
int app_audio_output_samplerate_select(u32 sample_rate, u8 high)
{
return audio_dac_sample_rate_select(&dac_hdl, sample_rate, high);
}
/*----------------------------------------------------------------------------*/
/**@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 (TCFG_REVERB_ENABLE || TCFG_MIC_EFFECT_ENABLE)
if (input_rate > 48000) {
return 48000;
}
#endif
return app_audio_output_samplerate_select(input_rate, 1);
}
#if TCFG_USER_TWS_ENABLE
#if AUDIO_SURROUND_CONFIG
#define TWS_FUNC_ID_A2DP_EFF \
((int)(('A' + '2' + 'D' + 'P') << (2 * 8)) | \
(int)(('E' + 'F' + 'F') << (1 * 8)) | \
(int)(('S' + 'Y' + 'N' + 'C') << (0 * 8)))
/*
*发环绕左右耳效果同步
* */
void audio_surround_voice_ctrl()
{
int state = tws_api_get_tws_state();
if (state & TWS_STA_SIBLING_CONNECTED) {
if (a2dp_dec && a2dp_dec->sur && a2dp_dec->sur->surround) {
if (!a2dp_dec->sur->surround_eff) {
a2dp_dec->sur->surround_eff = 1;
} else {
a2dp_dec->sur->surround_eff = 0;
}
int a2dp_eff = a2dp_dec->sur->surround_eff;
tws_api_send_data_to_sibling((u8 *)&a2dp_eff, sizeof(int), TWS_FUNC_ID_A2DP_EFF);
}
}
}
/*
*左右耳环绕效果同步回调
* */
static void tws_a2dp_eff_align(void *data, u16 len, bool rx)
{
if (a2dp_dec && a2dp_dec->sur && a2dp_dec->sur->surround) {
int a2dp_eff;
memcpy(&a2dp_eff, data, sizeof(int));
a2dp_dec->sur->surround_eff = a2dp_eff;
a2dp_surround_set(a2dp_eff);
audio_surround_voice(a2dp_dec->sur, a2dp_dec->sur->surround_eff);
}
}
REGISTER_TWS_FUNC_STUB(a2dp_align_eff) = {
.func_id = TWS_FUNC_ID_A2DP_EFF,
.func = tws_a2dp_eff_align,
};
#endif//AUDIO_SURROUND_CONFIG
#endif /* TCFG_USER_TWS_ENABLE */