KT24-1110_65E-HA-651B/cpu/br25/audio_dec/audio_dec_linein.c
2024-11-10 18:44:17 +08:00

819 lines
25 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.

/*
****************************************************************
*File : audio_dc_linein.c
*Note :
*
****************************************************************
*/
#include "asm/includes.h"
#include "media/includes.h"
#include "media/pcm_decoder.h"
#include "system/includes.h"
#include "effectrs_sync.h"
#include "app_config.h"
#include "audio_config.h"
#include "audio_dec.h"
#include "app_config.h"
#include "app_main.h"
#include "audio_enc.h"
#include "clock_cfg.h"
#include "dev_manager.h"
#include "media/convert_data.h"
#include "audio_effect/audio_dynamic_eq_demo.h"
#include "media/effects_adj.h"
#include "audio_effect/audio_eff_default_parm.h"
#if TCFG_PCM_ENC2TWS_ENABLE
#include "bt_tws.h"
#endif
#if (TCFG_LINEIN_ENABLE || TCFG_FM_ENABLE)//外部收音走linein
//////////////////////////////////////////////////////////////////////////////
struct linein_dec_hdl {
struct audio_stream *stream; // 音频流
struct pcm_decoder pcm_dec; // pcm解码句柄
struct audio_res_wait wait; // 资源等待句柄
struct audio_mixer_ch mix_ch; // 叠加句柄
#if AUDIO_SURROUND_CONFIG
surround_hdl *surround; //环绕音效句柄
#endif
#if AUDIO_VBASS_CONFIG
struct aud_gain_process *vbass_prev_gain;
NOISEGATE_API_STRUCT *ns_gate;
vbass_hdl *vbass; //虚拟低音句柄
#endif
#if TCFG_EQ_ENABLE && TCFG_AUDIO_OUT_EQ_ENABLE
struct audio_eq *high_bass;
struct audio_drc *hb_drc;//高低音后的drc
#if defined(TCFG_DRC_ENABLE) && TCFG_DRC_ENABLE
struct convert_data *hb_convert;
#endif
#endif
struct audio_eq *eq; //eq drc句柄
struct audio_drc *drc; // drc句柄
#if defined(TCFG_DRC_ENABLE) && TCFG_DRC_ENABLE
struct convert_data *convert;
#endif
#if defined(MUSIC_EXT_EQ_AFTER_DRC) && MUSIC_EXT_EQ_AFTER_DRC
struct audio_eq *ext_eq; //eq drc句柄 扩展eq
#endif
#if defined(TCFG_DYNAMIC_EQ_ENABLE) && TCFG_DYNAMIC_EQ_ENABLE
struct audio_eq *eq2; //eq drc句柄
struct dynamic_eq_hdl *dy_eq;
struct convert_data *convert2;
#endif
#if defined(TCFG_PHASER_GAIN_AND_CH_SWAP_ENABLE) && TCFG_PHASER_GAIN_AND_CH_SWAP_ENABLE
struct aud_gain_process *gain;
#endif
u32 id; // 唯一标识符,随机值
u32 start : 1; // 正在解码
u32 source : 8; // linein音频源
void *linein; // 底层驱动句柄
};
//////////////////////////////////////////////////////////////////////////////
struct linein_dec_hdl *linein_dec = NULL; // linein解码句柄
//////////////////////////////////////////////////////////////////////////////
int linein_sample_size(void *hdl);
int linein_sample_total(void *hdl);
//////////////////////////////////////////////////////////////////////////////
/*----------------------------------------------------------------------------*/
/**@brief linein解码释放
@param
@return
@note
*/
/*----------------------------------------------------------------------------*/
void linein_dec_relaese()
{
if (linein_dec) {
audio_decoder_task_del_wait(&decode_task, &linein_dec->wait);
clock_remove(AUDIO_CODING_PCM);
local_irq_disable();
free(linein_dec);
linein_dec = NULL;
local_irq_enable();
}
}
/*----------------------------------------------------------------------------*/
/**@brief linein解码事件处理
@param *decoder: 解码器句柄
@param argc: 参数个数
@param *argv: 参数
@return
@note
*/
/*----------------------------------------------------------------------------*/
static void linein_dec_event_handler(struct audio_decoder *decoder, int argc, int *argv)
{
switch (argv[0]) {
case AUDIO_DEC_EVENT_END:
if (!linein_dec) {
log_i("linein_dec handle err ");
break;
}
if (linein_dec->id != argv[1]) {
log_w("linein_dec id err : 0x%x, 0x%x \n", linein_dec->id, argv[1]);
break;
}
linein_dec_close();
//audio_decoder_resume_all(&decode_task);
break;
}
}
/*----------------------------------------------------------------------------*/
/**@brief linein解码数据输出
@param *entry: 音频流句柄
@param *in: 输入信息
@param *out: 输出信息
@return 输出长度
@note *out未使用
*/
/*----------------------------------------------------------------------------*/
static int linein_dec_data_handler(struct audio_stream_entry *entry,
struct audio_data_frame *in,
struct audio_data_frame *out)
{
struct audio_decoder *decoder = container_of(entry, struct audio_decoder, entry);
struct pcm_decoder *pcm_dec = container_of(decoder, struct pcm_decoder, decoder);
struct linein_dec_hdl *dec = container_of(pcm_dec, struct linein_dec_hdl, pcm_dec);
if (!dec->start) {
return 0;
}
audio_stream_run(&decoder->entry, in);
return decoder->process_len;
}
/*----------------------------------------------------------------------------*/
/**@brief linein解码数据流激活
@param *p: 私有句柄
@return
@note
*/
/*----------------------------------------------------------------------------*/
static void linein_dec_out_stream_resume(void *p)
{
struct linein_dec_hdl *dec = p;
audio_decoder_resume(&dec->pcm_dec.decoder);
}
/*----------------------------------------------------------------------------*/
/**@brief linein解码激活
@param
@return
@note
*/
/*----------------------------------------------------------------------------*/
static void linein_dec_resume(void)
{
if (linein_dec) {
audio_decoder_resume(&linein_dec->pcm_dec.decoder);
}
}
/*----------------------------------------------------------------------------*/
/**@brief 计算linein输入采样率
@param
@return 采样率
@note
*/
/*----------------------------------------------------------------------------*/
static int audio_linein_input_sample_rate(void *priv)
{
struct linein_dec_hdl *dec = (struct linein_dec_hdl *)priv;
int sample_rate = linein_stream_sample_rate(dec->linein);
int buf_size = linein_sample_size(dec->linein);
#if TCFG_PCM_ENC2TWS_ENABLE
if (dec->pcm_dec.dec_no_out_sound) {
/*TWS的上限在linein输入buffer下限在tws push buffer*/
if (buf_size >= linein_sample_total(dec->linein) / 2) {
sample_rate += (sample_rate * 1 / 10000);
} else if (tws_api_local_media_trans_check_ready_total() < 1024) {
sample_rate -= (sample_rate * 1 / 10000);
}
return sample_rate;
}
#endif
/* if (dec->pcm_dec.sample_rate == 44100 && audio_mixer_get_sample_rate(&mixer) == 44100) { */
if ((dec->pcm_dec.sample_rate == 44100) && (audio_mixer_get_original_sample_rate_by_type(&mixer, MIXER_SR_SPEC) == 44100)) {
sample_rate = 44100 + (sample_rate - 44118);
}
if (buf_size >= (linein_sample_total(dec->linein) * 3 / 4)) {
sample_rate += (sample_rate * 1 / 10000);
}
if (buf_size <= (linein_sample_total(dec->linein) / 2)) {
sample_rate -= (sample_rate * 1 / 10000);
}
return sample_rate;
}
/*----------------------------------------------------------------------------*/
/**@brief linein解码开始
@param
@return 0成功
@return 非0失败
@note
*/
/*----------------------------------------------------------------------------*/
int linein_dec_start()
{
int err;
struct linein_dec_hdl *dec = linein_dec;
struct audio_mixer *p_mixer = &mixer;
if (!linein_dec) {
return -EINVAL;
}
err = pcm_decoder_open(&dec->pcm_dec, &decode_task);
if (err) {
goto __err1;
}
// 打开linein驱动
dec->linein = linein_sample_open(dec->source, dec->pcm_dec.sample_rate);
linein_sample_set_resume_handler(dec->linein, linein_dec_resume);
pcm_decoder_set_event_handler(&dec->pcm_dec, linein_dec_event_handler, dec->id);
pcm_decoder_set_read_data(&dec->pcm_dec, linein_sample_read, dec->linein);
pcm_decoder_set_data_handler(&dec->pcm_dec, linein_dec_data_handler);
#if TCFG_PCM_ENC2TWS_ENABLE
{
// localtws使用sbc等编码转发
struct audio_fmt enc_f;
memcpy(&enc_f, &dec->pcm_dec.decoder.fmt, sizeof(struct audio_fmt));
enc_f.coding_type = AUDIO_CODING_SBC;
if (dec->pcm_dec.ch_num == 2) { // 如果是双声道数据localtws在解码时才变成对应声道
enc_f.channel = 2;
}
int ret = localtws_enc_api_open(&enc_f, LOCALTWS_ENC_FLAG_STREAM);
if (ret == true) {
dec->pcm_dec.dec_no_out_sound = 1;
// 重定向mixer
p_mixer = &g_localtws.mixer;
// 关闭资源等待。最终会在localtws解码处等待
audio_decoder_task_del_wait(&decode_task, &dec->wait);
if (dec->pcm_dec.output_ch_num != enc_f.channel) {
dec->pcm_dec.output_ch_num = dec->pcm_dec.decoder.fmt.channel = enc_f.channel;
if (enc_f.channel == 2) {
dec->pcm_dec.output_ch_type = AUDIO_CH_LR;
} else {
dec->pcm_dec.output_ch_type = AUDIO_CH_DIFF;
}
}
}
}
#endif
if (!dec->pcm_dec.dec_no_out_sound) {
audio_mode_main_dec_open(AUDIO_MODE_MAIN_STATE_DEC_LINEIN);
}
// 设置叠加功能
audio_mixer_ch_open_head(&dec->mix_ch, p_mixer);
audio_mixer_ch_set_no_wait(&dec->mix_ch, 1, 10); // 超时自动丢数
audio_mixer_ch_set_sample_rate(&dec->mix_ch, dec->pcm_dec.sample_rate);
if ((dec->pcm_dec.sample_rate == audio_mixer_get_sample_rate(p_mixer)) && (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_DAC)) {
} else {
audio_mixer_ch_follow_resample_enable(&dec->mix_ch, dec, audio_linein_input_sample_rate);
}
#if AUDIO_SURROUND_CONFIG
//环绕音效
#if defined(LINEIN_MODE_SOLE_EQ_EN) && LINEIN_MODE_SOLE_EQ_EN
dec->surround = surround_open_demo(AEID_AUX_SURROUND, dec->pcm_dec.output_ch_type);
#else
dec->surround = surround_open_demo(AEID_MUSIC_SURROUND, dec->pcm_dec.output_ch_type);
#endif
#endif
#if AUDIO_VBASS_CONFIG
#if defined(LINEIN_MODE_SOLE_EQ_EN) && LINEIN_MODE_SOLE_EQ_EN
dec->vbass_prev_gain = audio_gain_open_demo(AEID_AUX_VBASS_PREV_GAIN, dec->pcm_dec.output_ch_num);
dec->ns_gate = audio_noisegate_open_demo(AEID_AUX_NS_GATE, dec->pcm_dec.sample_rate, dec->pcm_dec.output_ch_num);
//虚拟低音
dec->vbass = audio_vbass_open_demo(AEID_AUX_VBASS, dec->pcm_dec.sample_rate, dec->pcm_dec.output_ch_num);
#else
dec->vbass_prev_gain = audio_gain_open_demo(AEID_MUSIC_VBASS_PREV_GAIN, dec->pcm_dec.output_ch_num);
dec->ns_gate = audio_noisegate_open_demo(AEID_MUSIC_NS_GATE, dec->pcm_dec.sample_rate, dec->pcm_dec.output_ch_num);
//虚拟低音
dec->vbass = audio_vbass_open_demo(AEID_MUSIC_VBASS, dec->pcm_dec.sample_rate, dec->pcm_dec.output_ch_num);
#endif
#endif
#if TCFG_EQ_ENABLE && TCFG_AUDIO_OUT_EQ_ENABLE
#if defined(LINEIN_MODE_SOLE_EQ_EN) && LINEIN_MODE_SOLE_EQ_EN
dec->high_bass = high_bass_aux_eq_open(dec->pcm_dec.sample_rate, dec->pcm_dec.output_ch_num);
dec->hb_drc = high_bass_aux_drc_open(dec->pcm_dec.sample_rate, dec->pcm_dec.output_ch_num);
#else
dec->high_bass = high_bass_eq_open(dec->pcm_dec.sample_rate, dec->pcm_dec.output_ch_num);
dec->hb_drc = high_bass_drc_open(dec->pcm_dec.sample_rate, dec->pcm_dec.output_ch_num);
#endif
#if defined(TCFG_DRC_ENABLE) && TCFG_DRC_ENABLE
if (dec->hb_drc && dec->hb_drc->run32bit) {
dec->hb_convert = convet_data_open(0, 512);
}
#endif
#endif
#if TCFG_EQ_ENABLE && TCFG_LINEIN_MODE_EQ_ENABLE
#if defined(LINEIN_MODE_SOLE_EQ_EN) && LINEIN_MODE_SOLE_EQ_EN
dec->eq = linein_eq_open(dec->pcm_dec.sample_rate, dec->pcm_dec.output_ch_num);// eq
#else
dec->eq = music_eq_open(dec->pcm_dec.sample_rate, dec->pcm_dec.output_ch_num);// eq
#endif
#if TCFG_DRC_ENABLE && TCFG_LINEIN_MODE_DRC_ENABLE
#if defined(LINEIN_MODE_SOLE_EQ_EN) && LINEIN_MODE_SOLE_EQ_EN
dec->drc = linein_drc_open(dec->pcm_dec.sample_rate, dec->pcm_dec.output_ch_num);//drc
#else
dec->drc = music_drc_open(dec->pcm_dec.sample_rate, dec->pcm_dec.output_ch_num);//drc
#endif
#endif/*TCFG_LINEIN_MODE_DRC_ENABLE*/
#if defined(TCFG_DRC_ENABLE) && TCFG_DRC_ENABLE
if (dec->eq && dec->eq->out_32bit) {
dec->convert = convet_data_open(0, 512);
}
#endif
#if defined(MUSIC_EXT_EQ_AFTER_DRC) && MUSIC_EXT_EQ_AFTER_DRC
#if defined(LINEIN_MODE_SOLE_EQ_EN) && LINEIN_MODE_SOLE_EQ_EN
dec->ext_eq = aux_ext_eq_open(dec->pcm_dec.sample_rate, dec->pcm_dec.output_ch_num);
#else
dec->ext_eq = music_ext_eq_open(dec->pcm_dec.sample_rate, dec->pcm_dec.output_ch_num);
#endif
#endif
#if defined(TCFG_DYNAMIC_EQ_ENABLE) && TCFG_DYNAMIC_EQ_ENABLE
#if defined(LINEIN_MODE_SOLE_EQ_EN) && LINEIN_MODE_SOLE_EQ_EN
dec->eq2 = linein_eq2_open(dec->pcm_dec.sample_rate, dec->pcm_dec.output_ch_num);// eq
dec->dy_eq = audio_dynamic_eq_ctrl_open(AEID_AUX_DYNAMIC_EQ, dec->pcm_dec.sample_rate, dec->pcm_dec.output_ch_num);//动态eq
#else
dec->eq2 = music_eq2_open(dec->pcm_dec.sample_rate, dec->pcm_dec.output_ch_num);// eq
dec->dy_eq = audio_dynamic_eq_ctrl_open(AEID_MUSIC_DYNAMIC_EQ, dec->pcm_dec.sample_rate, dec->pcm_dec.output_ch_num);//动态eq
#endif
dec->convert2 = convet_data_open(0, 512);
#endif/*TCFG_DYNAMIC_EQ_ENABLE*/
u16 gain_name = AEID_MUSIC_GAIN;
u16 swap_name = AEID_MUSIC_CH_SWAP;
#if defined(LINEIN_MODE_SOLE_EQ_EN) && LINEIN_MODE_SOLE_EQ_EN
gain_name = AEID_AUX_GAIN;
swap_name = AEID_AUX_CH_SWAP;
#endif
#if defined(TCFG_PHASER_GAIN_AND_CH_SWAP_ENABLE) && TCFG_PHASER_GAIN_AND_CH_SWAP_ENABLE
dec->gain = audio_gain_open_demo(gain_name, dec->pcm_dec.output_ch_num);
#endif
#endif/*TCFG_LINEIN_MODE_EQ_ENABLE*/
struct audio_stream_entry *entries[16] = {NULL};
u8 entry_cnt = 0;
u8 rl_rr_entry_start = 0;
entries[entry_cnt++] = &dec->pcm_dec.decoder.entry;
#if SYS_DIGVOL_GROUP_EN
void *dvol_entry = sys_digvol_group_ch_open("music_linein", -1, NULL);
entries[entry_cnt++] = dvol_entry;
#endif // SYS_DIGVOL_GROUP_EN
#if AUDIO_VBASS_CONFIG
if (dec->vbass_prev_gain) {
entries[entry_cnt++] = &dec->vbass_prev_gain->entry;
}
if (dec->ns_gate) {
entries[entry_cnt++] = &dec->ns_gate->entry;
}
if (dec->vbass) {
entries[entry_cnt++] = &dec->vbass->entry;
}
#endif
#if TCFG_EQ_ENABLE && TCFG_AUDIO_OUT_EQ_ENABLE
if (dec->high_bass) { //高低音
entries[entry_cnt++] = &dec->high_bass->entry;
}
if (dec->hb_drc) { //高低音后drc
entries[entry_cnt++] = &dec->hb_drc->entry;
#if defined(TCFG_DRC_ENABLE) && TCFG_DRC_ENABLE
if (dec->hb_convert) {
entries[entry_cnt++] = &dec->hb_convert->entry;
}
#endif
}
#endif
rl_rr_entry_start = entry_cnt - 1;//记录eq的上一个节点
#if defined(TCFG_PHASER_GAIN_AND_CH_SWAP_ENABLE) && TCFG_PHASER_GAIN_AND_CH_SWAP_ENABLE
if (dec->gain) {
entries[entry_cnt++] = &dec->gain->entry;
}
#endif
#if AUDIO_SURROUND_CONFIG
if (dec->surround) {
entries[entry_cnt++] = &dec->surround->entry;
}
#endif
#if TCFG_EQ_ENABLE && TCFG_LINEIN_MODE_EQ_ENABLE
if (dec->eq) {
entries[entry_cnt++] = &dec->eq->entry;
if (dec->drc) {
entries[entry_cnt++] = &dec->drc->entry;
}
#if defined(TCFG_DRC_ENABLE) && TCFG_DRC_ENABLE
if (dec->convert) {
entries[entry_cnt++] = &dec->convert->entry;
}
#endif
#if defined(MUSIC_EXT_EQ_AFTER_DRC) && MUSIC_EXT_EQ_AFTER_DRC
if (dec->ext_eq) {
entries[entry_cnt++] = &dec->ext_eq->entry;
}
#endif
#if defined(TCFG_DYNAMIC_EQ_ENABLE) && TCFG_DYNAMIC_EQ_ENABLE
if (dec->eq2) {
entries[entry_cnt++] = &dec->eq2->entry;
}
if (dec->dy_eq && dec->dy_eq->dy_eq) {
entries[entry_cnt++] = &dec->dy_eq->dy_eq->entry;
}
if (dec->convert2) {
entries[entry_cnt++] = &dec->convert2->entry;
}
#endif
}
#endif
entries[entry_cnt++] = &dec->mix_ch.entry;
// 创建数据流,把所有节点连接起来
dec->stream = audio_stream_open(dec, linein_dec_out_stream_resume);
audio_stream_add_list(dec->stream, entries, entry_cnt);
// 设置音频输出音量
audio_output_set_start_volume(APP_AUDIO_STATE_MUSIC);
// 开始解码
dec->start = 1;
err = audio_decoder_start(&dec->pcm_dec.decoder);
if (err) {
goto __err3;
}
clock_set_cur();
return 0;
__err3:
dec->start = 0;
#if AUDIO_SURROUND_CONFIG
surround_close_demo(dec->surround);
#endif
#if AUDIO_VBASS_CONFIG
audio_gain_close_demo(dec->vbass_prev_gain);
audio_noisegate_close_demo(dec->ns_gate);
audio_vbass_close_demo(dec->vbass);
#endif
#if TCFG_EQ_ENABLE && TCFG_AUDIO_OUT_EQ_ENABLE
high_bass_eq_close(dec->high_bass);
high_bass_drc_close(dec->hb_drc);
#if defined(TCFG_DRC_ENABLE) && TCFG_DRC_ENABLE
convet_data_close(dec->hb_convert);
#endif
#endif
#if TCFG_EQ_ENABLE && TCFG_LINEIN_MODE_EQ_ENABLE
#if defined(LINEIN_MODE_SOLE_EQ_EN) && LINEIN_MODE_SOLE_EQ_EN
linein_eq_close(dec->eq);
#else
music_eq_close(dec->eq);
#endif
#if TCFG_DRC_ENABLE && TCFG_LINEIN_MODE_DRC_ENABLE
#if defined(LINEIN_MODE_SOLE_EQ_EN) && LINEIN_MODE_SOLE_EQ_EN
linein_drc_close(dec->drc);
#else
music_drc_close(dec->drc);
#endif
#endif
#if defined(TCFG_DRC_ENABLE) && TCFG_DRC_ENABLE
convet_data_close(dec->convert);
#endif
#if defined(MUSIC_EXT_EQ_AFTER_DRC) && MUSIC_EXT_EQ_AFTER_DRC
#if defined(LINEIN_MODE_SOLE_EQ_EN) && LINEIN_MODE_SOLE_EQ_EN
aux_ext_eq_close(dec->ext_eq);
#else
music_ext_eq_close(dec->ext_eq);
#endif
#endif
#if defined(TCFG_DYNAMIC_EQ_ENABLE) && TCFG_DYNAMIC_EQ_ENABLE
music_eq2_close(dec->eq2);
audio_dynamic_eq_ctrl_close(dec->dy_eq);
convet_data_close(dec->convert2);
#endif
#if defined(TCFG_PHASER_GAIN_AND_CH_SWAP_ENABLE) && TCFG_PHASER_GAIN_AND_CH_SWAP_ENABLE
audio_gain_close_demo(dec->gain);
#endif
#endif
if (dec->linein) {
linein_sample_close(dec->linein);
dec->linein = NULL;
}
audio_mixer_ch_close(&dec->mix_ch);
#if TCFG_PCM_ENC2TWS_ENABLE
if (linein_dec->pcm_dec.dec_no_out_sound) {
linein_dec->pcm_dec.dec_no_out_sound = 0;
localtws_enc_api_close();
}
#endif
#if SYS_DIGVOL_GROUP_EN
sys_digvol_group_ch_close("music_linein");
#endif // SYS_DIGVOL_GROUP_EN
if (dec->stream) {
audio_stream_close(dec->stream);
dec->stream = NULL;
}
pcm_decoder_close(&dec->pcm_dec);
__err1:
linein_dec_relaese();
return err;
}
/*----------------------------------------------------------------------------*/
/**@brief fm解码关闭
@param
@return
@note
*/
/*----------------------------------------------------------------------------*/
static void __linein_dec_close(void)
{
if (linein_dec && linein_dec->start) {
linein_dec->start = 0;
pcm_decoder_close(&linein_dec->pcm_dec);
linein_sample_close(linein_dec->linein);
linein_dec->linein = NULL;
#if AUDIO_SURROUND_CONFIG
surround_close_demo(linein_dec->surround);
#endif
#if AUDIO_VBASS_CONFIG
audio_gain_close_demo(linein_dec->vbass_prev_gain);
audio_noisegate_close_demo(linein_dec->ns_gate);
audio_vbass_close_demo(linein_dec->vbass);
#endif
#if TCFG_EQ_ENABLE && TCFG_AUDIO_OUT_EQ_ENABLE
high_bass_eq_close(linein_dec->high_bass);
high_bass_drc_close(linein_dec->hb_drc);
#if defined(TCFG_DRC_ENABLE) && TCFG_DRC_ENABLE
convet_data_close(linein_dec->hb_convert);
#endif
#endif
#if TCFG_EQ_ENABLE && TCFG_LINEIN_MODE_EQ_ENABLE
#if defined(LINEIN_MODE_SOLE_EQ_EN) && LINEIN_MODE_SOLE_EQ_EN
linein_eq_close(linein_dec->eq);
#else
music_eq_close(linein_dec->eq);
#endif
#if TCFG_DRC_ENABLE && TCFG_LINEIN_MODE_DRC_ENABLE
#if defined(LINEIN_MODE_SOLE_EQ_EN) && LINEIN_MODE_SOLE_EQ_EN
linein_drc_close(linein_dec->drc);
#else
music_drc_close(linein_dec->drc);
#endif
#endif
#if defined(TCFG_DRC_ENABLE) && TCFG_DRC_ENABLE
convet_data_close(linein_dec->convert);
#endif
#if defined(MUSIC_EXT_EQ_AFTER_DRC) && MUSIC_EXT_EQ_AFTER_DRC
#if defined(LINEIN_MODE_SOLE_EQ_EN) && LINEIN_MODE_SOLE_EQ_EN
aux_ext_eq_close(linein_dec->ext_eq);
#else
music_ext_eq_close(linein_dec->ext_eq);
#endif
#endif
#if defined(TCFG_DYNAMIC_EQ_ENABLE) && TCFG_DYNAMIC_EQ_ENABLE
music_eq2_close(linein_dec->eq2);
audio_dynamic_eq_ctrl_close(linein_dec->dy_eq);
convet_data_close(linein_dec->convert2);
#endif
#if defined(TCFG_PHASER_GAIN_AND_CH_SWAP_ENABLE) && TCFG_PHASER_GAIN_AND_CH_SWAP_ENABLE
audio_gain_close_demo(linein_dec->gain);
#endif
#endif
audio_mixer_ch_close(&linein_dec->mix_ch);
#if TCFG_PCM_ENC2TWS_ENABLE
if (linein_dec->pcm_dec.dec_no_out_sound) {
linein_dec->pcm_dec.dec_no_out_sound = 0;
localtws_enc_api_close();
}
#endif
#if SYS_DIGVOL_GROUP_EN
sys_digvol_group_ch_close("music_linein");
#endif // SYS_DIGVOL_GROUP_EN
// 先关闭各个节点最后才close数据流
if (linein_dec->stream) {
audio_stream_close(linein_dec->stream);
linein_dec->stream = NULL;
}
}
}
/*----------------------------------------------------------------------------*/
/**@brief linein解码资源等待
@param *wait: 句柄
@param event: 事件
@return 0成功
@note 用于多解码打断处理
*/
/*----------------------------------------------------------------------------*/
static int linein_wait_res_handler(struct audio_res_wait *wait, int event)
{
int err = 0;
log_i("linein_wait_res_handler, event:%d\n", event);
if (event == AUDIO_RES_GET) {
// 启动解码
err = linein_dec_start();
} else if (event == AUDIO_RES_PUT) {
// 被打断
__linein_dec_close();
}
return err;
}
/*----------------------------------------------------------------------------*/
/**@brief 打开linein解码
@param source: 音频源
@param sample_rate: 采样率
@return 0成功
@return 非0失败
@note
*/
/*----------------------------------------------------------------------------*/
int linein_dec_open(u8 source, u32 sample_rate)
{
int err;
struct linein_dec_hdl *dec;
dec = zalloc(sizeof(*dec));
if (!dec) {
return -ENOMEM;
}
linein_dec = dec;
dec->id = rand32();
switch (source) {
case BIT(0):
case BIT(1):
dec->pcm_dec.ch_num = 1;
break;
case BIT(2):
case BIT(3):
dec->pcm_dec.ch_num = 1;
break;
default:
if (audio_adc_support_linein_combined()) {
/*F版支持一路adc采样linein左右声道混合输入*/
dec->pcm_dec.ch_num = 1;
} else {
log_e("Linein can only select a single channel\n");
ASSERT(0, "err\n");
}
break;
}
dec->source = source;
dec->pcm_dec.output_ch_num = audio_output_channel_num();
dec->pcm_dec.output_ch_type = audio_output_channel_type();
#if TCFG_MIC_EFFECT_ENABLE
dec->pcm_dec.sample_rate = MIC_EFFECT_SAMPLERATE;
#else
dec->pcm_dec.sample_rate = sample_rate;
#endif
dec->wait.priority = 2;
dec->wait.preemption = 0;
dec->wait.snatch_same_prio = 1;
dec->wait.handler = linein_wait_res_handler;
clock_add(AUDIO_CODING_PCM);
#if TCFG_DEC2TWS_ENABLE
// 设置localtws重播接口
localtws_globle_set_dec_restart(linein_dec_push_restart);
#endif
err = audio_decoder_task_add_wait(&decode_task, &dec->wait);
return err;
}
/*----------------------------------------------------------------------------*/
/**@brief 关闭linein解码
@param
@return
@note
*/
/*----------------------------------------------------------------------------*/
void linein_dec_close(void)
{
if (!linein_dec) {
return;
}
__linein_dec_close();
linein_dec_relaese();
clock_set_cur();
log_i("linein dec close \n\n ");
}
/*----------------------------------------------------------------------------*/
/**@brief linein解码重新开始
@param id: 文件解码id
@return 0成功
@return 非0失败
@note
*/
/*----------------------------------------------------------------------------*/
int linein_dec_restart(int id)
{
if ((!linein_dec) || (id != linein_dec->id)) {
return -1;
}
u8 source = linein_dec->source;
u32 sample_rate = linein_dec->pcm_dec.sample_rate;
linein_dec_close();
int err = linein_dec_open(source, sample_rate);
return err;
}
/*----------------------------------------------------------------------------*/
/**@brief 推送linein解码重新开始命令
@param
@return true成功
@return false失败
@note
*/
/*----------------------------------------------------------------------------*/
int linein_dec_push_restart(void)
{
if (!linein_dec) {
return false;
}
int argv[3];
argv[0] = (int)linein_dec_restart;
argv[1] = 1;
argv[2] = (int)linein_dec->id;
os_taskq_post_type(os_current_task(), Q_CALLBACK, ARRAY_SIZE(argv), argv);
return true;
}
#endif