1306 lines
35 KiB
C
1306 lines
35 KiB
C
/*
|
||
****************************************************************
|
||
*File : audio_dec_file.c
|
||
*Note :
|
||
*
|
||
****************************************************************
|
||
*/
|
||
//////////////////////////////////////////////////////////////////////////////
|
||
#include "asm/includes.h"
|
||
#include "media/includes.h"
|
||
#include "media/file_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 "classic/tws_api.h"
|
||
#include "audio_dec/audio_dec_file.h"
|
||
#include "media/audio_stream.h"
|
||
#include "music/music_decrypt.h"
|
||
#include "music/music_id3.h"
|
||
#include "application/eq_config.h"
|
||
#include "audio_dec_eff.h"
|
||
#include "bt_tws.h"
|
||
#include "media/bt_audio_timestamp.h"
|
||
#include "media/audio_syncts.h"
|
||
#include "audio_codec_clock.h"
|
||
#include "sound_device.h"
|
||
#if (SYS_VOL_TYPE == VOL_TYPE_DIGITAL)
|
||
#include "audio_dvol.h"
|
||
#endif/*SYS_VOL_TYPE == VOL_TYPE_DIGITAL*/
|
||
|
||
#if TCFG_APP_MUSIC_EN
|
||
#define FILE_DEC_PICK_EN 0 // 本地解码拆包转发
|
||
|
||
#define FILE_DEC_ALIGN 0
|
||
#define FILE_DEC_START 1
|
||
#define FILE_DEC_INVITE 2
|
||
|
||
#if (!TCFG_DEC2TWS_ENABLE)
|
||
#undef FILE_DEC_PICK_EN
|
||
#define FILE_DEC_PICK_EN 0
|
||
#endif
|
||
|
||
#ifndef BREAKPOINT_DATA_LEN
|
||
#define BREAKPOINT_DATA_LEN 32
|
||
#endif
|
||
|
||
const int FILE_DEC_ONCE_OUT_NUM = ((512 * 4) * 2); // 一次最多输出长度。避免多解码叠加时卡住其他解码太长时间
|
||
|
||
const int FILE_DEC_PP_FADE_MS = 50; // pp淡入淡出时长。0-不使用淡入淡出
|
||
|
||
struct file_dec_hdl *file_dec = NULL; // 文件解码句柄
|
||
u8 file_dec_start_pause = 0; // 启动解码后但不马上开始播放
|
||
extern struct audio_dac_hdl dac_hdl;
|
||
|
||
|
||
//////////////////////////////////////////////////////////////////////////////
|
||
|
||
void file_eq_drc_open(struct file_dec_hdl *hdl, u16 sample_rate, u8 ch_num);
|
||
void file_eq_drc_close(struct file_dec_hdl *hdl);
|
||
|
||
extern void *local_tws_dec_sync_open(u8 channel, u16 sample_rate, u16 output_rate);
|
||
extern void local_tws_sync_no_check_data_buf(u8 no_check);
|
||
extern void audio_mix_ch_event_handler(void *priv, int event);
|
||
extern void bt_audio_sync_nettime_select(u8 base);
|
||
|
||
int file_dec_repeat_set(u8 repeat_num);
|
||
|
||
//////////////////////////////////////////////////////////////////////////////
|
||
/*----------------------------------------------------------------------------*/
|
||
/**@brief 获取文件解码hdl
|
||
@param
|
||
@return
|
||
@note
|
||
*/
|
||
/*----------------------------------------------------------------------------*/
|
||
void *get_file_dec_hdl()
|
||
{
|
||
return file_dec;
|
||
}
|
||
|
||
static enum audio_channel file_dec_get_output_channel()
|
||
{
|
||
enum audio_channel channel;
|
||
|
||
#if TCFG_USER_TWS_ENABLE
|
||
int 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;
|
||
} else {
|
||
u8 dac_connect_mode = audio_dac_get_channel(&dac_hdl);
|
||
if (dac_connect_mode == DAC_OUTPUT_LR) {
|
||
channel = AUDIO_CH_LR;
|
||
} else {
|
||
channel = AUDIO_CH_DIFF;
|
||
}
|
||
}
|
||
#else
|
||
u8 dac_connect_mode = audio_dac_get_channel(&dac_hdl);
|
||
if (dac_connect_mode == DAC_OUTPUT_LR) {
|
||
channel = AUDIO_CH_LR;
|
||
} else {
|
||
channel = AUDIO_CH_DIFF;
|
||
}
|
||
#endif
|
||
return channel;
|
||
}
|
||
|
||
static u8 file_dec_output_channel_num(void)
|
||
{
|
||
u8 dac_connect_mode = audio_dac_get_channel(&dac_hdl);
|
||
if (dac_connect_mode == AUDIO_CH_LR) {
|
||
return 2;
|
||
}
|
||
return 1;
|
||
}
|
||
/*----------------------------------------------------------------------------*/
|
||
/**@brief 读取文件数据
|
||
@param *decoder: 解码器句柄
|
||
@param *buf: 数据
|
||
@param len: 数据长度
|
||
@return >=0:读到的数据长度
|
||
@return <0:错误
|
||
@note
|
||
*/
|
||
/*----------------------------------------------------------------------------*/
|
||
static int file_fread(struct audio_decoder *decoder, void *buf, u32 len)
|
||
{
|
||
int rlen;
|
||
struct file_dec_hdl *dec = file_dec;
|
||
|
||
#if TCFG_DEC_DECRYPT_ENABLE
|
||
u32 addr;
|
||
addr = fpos(dec->file);
|
||
rlen = fread(dec->file, buf, len);
|
||
if (rlen && (rlen <= len)) {
|
||
cryptanalysis_buff(&dec->mply_cipher, buf, addr, rlen);
|
||
}
|
||
#else
|
||
rlen = fread(dec->file, buf, len);
|
||
#endif
|
||
if (rlen > len) {
|
||
// putchar('r');
|
||
if (rlen == (-1)) {
|
||
//file err
|
||
dec->read_err = 1;
|
||
} else {
|
||
//dis err
|
||
dec->read_err = 2;
|
||
}
|
||
rlen = 0;
|
||
} else {
|
||
// putchar('R');
|
||
dec->read_err = 0;
|
||
}
|
||
return rlen;
|
||
}
|
||
|
||
/*----------------------------------------------------------------------------*/
|
||
/**@brief 文件指针定位
|
||
@param *decoder: 解码器句柄
|
||
@param offset: 定位偏移
|
||
@param seek_mode: 定位类型
|
||
@return 0:成功
|
||
@return 非0:错误
|
||
@note
|
||
*/
|
||
/*----------------------------------------------------------------------------*/
|
||
static int file_fseek(struct audio_decoder *decoder, u32 offset, int seek_mode)
|
||
{
|
||
struct file_dec_hdl *dec = file_dec;
|
||
|
||
return fseek(dec->file, offset, seek_mode);
|
||
}
|
||
|
||
/*----------------------------------------------------------------------------*/
|
||
/**@brief 读取文件长度
|
||
@param *decoder: 解码器句柄
|
||
@return 文件长度
|
||
@note
|
||
*/
|
||
/*----------------------------------------------------------------------------*/
|
||
static int file_flen(struct audio_decoder *decoder)
|
||
{
|
||
int len = 0;
|
||
struct file_dec_hdl *dec = file_dec;
|
||
|
||
len = flen(dec->file);
|
||
return len;
|
||
}
|
||
|
||
static const u32 file_input_coding_more[] = {
|
||
#if TCFG_DEC_WAV_ENABLE
|
||
AUDIO_CODING_WAV,
|
||
#endif
|
||
#if TCFG_DEC_MP3_ENABLE
|
||
AUDIO_CODING_MP3,
|
||
#endif
|
||
0,
|
||
};
|
||
|
||
static const struct audio_dec_input file_input = {
|
||
.coding_type = 0
|
||
#if TCFG_DEC_WMA_ENABLE
|
||
| AUDIO_CODING_WMA
|
||
#endif
|
||
|
||
#if TCFG_DEC_FLAC_ENABLE
|
||
| AUDIO_CODING_FLAC
|
||
#endif
|
||
#if TCFG_DEC_APE_ENABLE
|
||
| AUDIO_CODING_APE
|
||
#endif
|
||
#if TCFG_DEC_M4A_ENABLE
|
||
| AUDIO_CODING_M4A
|
||
#endif
|
||
#if TCFG_DEC_ALAC_ENABLE
|
||
| AUDIO_CODING_ALAC
|
||
#endif
|
||
#if TCFG_DEC_AMR_ENABLE
|
||
| AUDIO_CODING_AMR
|
||
#endif
|
||
#if TCFG_DEC_DTS_ENABLE
|
||
| AUDIO_CODING_DTS
|
||
#endif
|
||
#if TCFG_DEC_G726_ENABLE
|
||
| AUDIO_CODING_G726
|
||
#endif
|
||
|
||
,
|
||
.p_more_coding_type = (u32 *)file_input_coding_more,
|
||
.data_type = AUDIO_INPUT_FILE,
|
||
.ops = {
|
||
.file = {
|
||
.fread = file_fread,
|
||
.fseek = file_fseek,
|
||
.flen = file_flen,
|
||
}
|
||
}
|
||
};
|
||
|
||
#if TCFG_DEC2TWS_ENABLE
|
||
|
||
static inline u16 local_tws_audio_seqn(void *buf)
|
||
{
|
||
u16 seqn;
|
||
/*Get local tws audio sequence.*/
|
||
if (!buf) {
|
||
return 0;
|
||
}
|
||
|
||
memcpy(&seqn, buf, sizeof(seqn));
|
||
return seqn;
|
||
}
|
||
|
||
static inline u16 local_tws_audio_timestamp(void *buf)
|
||
{
|
||
u32 timestamp;
|
||
/*Get local tws audio sequence.*/
|
||
if (!buf) {
|
||
return 0;
|
||
}
|
||
|
||
memcpy(×tamp, buf, sizeof(timestamp));
|
||
return timestamp;
|
||
}
|
||
|
||
/*static int frame_fread(struct audio_decoder *decoder, u8 **frame)*/
|
||
static int frame_fread(struct audio_decoder *decoder, void *buf, u32 len)
|
||
{
|
||
int offset = 0;
|
||
int frame_len;
|
||
struct file_dec_hdl *dec = file_dec;
|
||
|
||
while (len) {
|
||
int clen = MIN(dec->frame_remain_len, len);
|
||
if (clen) {
|
||
memcpy((u8 *)buf + offset,
|
||
dec->frame + dec->frame_len - dec->frame_remain_len, clen);
|
||
len -= clen;
|
||
offset += clen;
|
||
dec->frame_remain_len -= clen;
|
||
break;
|
||
} else {
|
||
if (dec->frame) {
|
||
tws_api_data_trans_free(dec->tws_channel, dec->frame);
|
||
}
|
||
dec->frame = tws_api_data_trans_pop(dec->tws_channel, &frame_len);
|
||
if (!dec->frame) {
|
||
dec->frame_remain_len = 0;
|
||
break;
|
||
}
|
||
#if 0
|
||
u16 seqn = local_tws_audio_seqn(dec->frame);
|
||
if ((u16)(seqn - dec->seqn) > 1) {
|
||
log_w("Local tws audio sequence error : %d, %d.\n", seqn, dec->seqn);
|
||
}
|
||
dec->seqn = seqn;
|
||
#else
|
||
u32 timestamp = local_tws_audio_timestamp(dec->frame);
|
||
audio_syncts_next_pts(dec->syncts, timestamp);
|
||
dec->mix_ch_event_params[2] = timestamp;
|
||
#endif
|
||
dec->frame_len = frame_len;
|
||
dec->frame_remain_len = frame_len - sizeof(dec->seqn);
|
||
}
|
||
}
|
||
|
||
if (offset == 0) {
|
||
// r_printf("no_data\n");
|
||
if (dec->trans_dec_end) {
|
||
return -EINVAL;
|
||
}
|
||
}
|
||
|
||
return offset;
|
||
}
|
||
|
||
static int frame_fseek(struct audio_decoder *decoder, u32 offset, int seek_mode)
|
||
{
|
||
return 0;
|
||
}
|
||
|
||
static int frame_flen(struct audio_decoder *decoder)
|
||
{
|
||
return 0x7fffffff;
|
||
}
|
||
|
||
static const struct audio_dec_input frame_input = {
|
||
.coding_type = 0,
|
||
.data_type = AUDIO_INPUT_FILE,
|
||
.ops = {
|
||
.file = {
|
||
.fread = frame_fread,
|
||
.fseek = frame_fseek,
|
||
.flen = frame_flen,
|
||
}
|
||
}
|
||
};
|
||
#endif
|
||
|
||
|
||
|
||
/*----------------------------------------------------------------------------*/
|
||
/**@brief 文件解码释放
|
||
@param
|
||
@return
|
||
@note
|
||
*/
|
||
/*----------------------------------------------------------------------------*/
|
||
static void file_dec_release(void)
|
||
{
|
||
struct file_dec_hdl *dec = file_dec;
|
||
|
||
#if TCFG_DEC_ID3_V1_ENABLE
|
||
if (dec->p_mp3_id3_v1) {
|
||
id3_obj_post(&dec->p_mp3_id3_v1);
|
||
}
|
||
#endif
|
||
#if TCFG_DEC_ID3_V2_ENABLE
|
||
if (dec->p_mp3_id3_v2) {
|
||
id3_obj_post(&dec->p_mp3_id3_v2);
|
||
}
|
||
#endif
|
||
|
||
audio_decoder_task_del_wait(&decode_task, &dec->wait);
|
||
|
||
audio_codec_clock_del(AUDIO_FILE_MODE);
|
||
|
||
#if TCFG_DEC2TWS_ENABLE
|
||
if (dec->tws_channel) {
|
||
tws_api_data_trans_close(dec->tws_channel);
|
||
}
|
||
#endif
|
||
|
||
#if (SYS_VOL_TYPE == VOL_TYPE_DIGITAL)
|
||
audio_digital_vol_close(MUSIC_DVOL);
|
||
#endif/*SYS_VOL_TYPE == VOL_TYPE_DIGITAL*/
|
||
|
||
|
||
local_irq_disable();
|
||
if (file_dec->dec_bp) {
|
||
free(file_dec->dec_bp);
|
||
file_dec->dec_bp = NULL;
|
||
}
|
||
free(file_dec);
|
||
file_dec = NULL;
|
||
local_irq_enable();
|
||
}
|
||
|
||
/*----------------------------------------------------------------------------*/
|
||
/**@brief 文件解码事件处理
|
||
@param *decoder: 解码器句柄
|
||
@param argc: 参数个数
|
||
@param *argv: 参数
|
||
@return
|
||
@note
|
||
*/
|
||
/*----------------------------------------------------------------------------*/
|
||
static void file_dec_event_handler(struct audio_decoder *decoder, int argc, int *argv)
|
||
{
|
||
printf("file_dec_event_handler: %d\n", argv[0]);
|
||
|
||
switch (argv[0]) {
|
||
case AUDIO_DEC_EVENT_END:
|
||
log_i("AUDIO_DEC_EVENT_END\n");
|
||
if (!file_dec) {
|
||
log_i("file_dec handle err ");
|
||
break;
|
||
}
|
||
#if TCFG_DEC2TWS_ENABLE
|
||
if (decoder == &file_dec->trans_dec.decoder) {
|
||
file_dec->trans_dec_end = 1;
|
||
break;
|
||
}
|
||
#endif
|
||
if (decoder != &file_dec->file_dec.decoder) {
|
||
break;
|
||
}
|
||
|
||
// 有回调,让上层close,避免close后上层读不到断点等
|
||
if (file_dec->evt_cb) {
|
||
/* file_dec->evt_cb(file_dec->evt_priv, argc, argv); */
|
||
int msg[2];
|
||
msg[0] = argv[0];
|
||
msg[1] = file_dec->read_err;
|
||
/* log_i("read err0:%d ", file_dec->read_err); */
|
||
file_dec->evt_cb(file_dec->evt_priv, 2, msg);
|
||
} else {
|
||
file_dec_close();
|
||
}
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
|
||
static int file_decoder_output_after_syncts(void *priv, void *data, int len)
|
||
{
|
||
struct file_dec_hdl *dec = (struct file_dec_hdl *)priv;
|
||
#if TCFG_EQ_ENABLE&&TCFG_MUSIC_MODE_EQ_ENABLE
|
||
if (dec->eq_drc && dec->eq_drc->async) {
|
||
return eq_drc_run(dec->eq_drc, data, len);//异步eq
|
||
}
|
||
#endif//TCFG_MUSIC_MODE_EQ_ENABLE
|
||
|
||
int wlen = audio_mixer_ch_write(&dec->mix_ch, data, len);
|
||
return wlen;
|
||
}
|
||
|
||
static int file_decoder_output_hander(struct file_decoder *decoder, s16 *data, int len)
|
||
{
|
||
int wlen = 0;
|
||
|
||
struct file_dec_hdl *dec = container_of(decoder, struct file_dec_hdl, file_dec);
|
||
|
||
if (!dec->remain) {
|
||
#if (SYS_VOL_TYPE == VOL_TYPE_DIGITAL)
|
||
audio_digital_vol_run(MUSIC_DVOL, data, len);
|
||
#endif/*SYS_VOL_TYPE == VOL_TYPE_DIGITAL*/
|
||
|
||
#if TCFG_EQ_ENABLE&&TCFG_MUSIC_MODE_EQ_ENABLE
|
||
if (dec->eq_drc && !dec->eq_drc->async) {
|
||
eq_drc_run(dec->eq_drc, data, len);//同步eq
|
||
}
|
||
#endif
|
||
}
|
||
#if TCFG_DEC2TWS_ENABLE
|
||
if (dec->syncts) {
|
||
int wlen = audio_syncts_frame_filter(dec->syncts, data, len);
|
||
if (wlen < len) {
|
||
audio_syncts_trigger_resume(dec->syncts, (void *)decoder, (void (*)(void *))audio_decoder_resume);
|
||
}
|
||
dec->remain = wlen < len ? 1 : 0;
|
||
return wlen;
|
||
}
|
||
#endif
|
||
wlen = file_decoder_output_after_syncts(dec, data, len);
|
||
dec->remain = wlen < len ? 1 : 0;
|
||
return wlen;
|
||
}
|
||
|
||
static int tws_local_media_trans_handler(struct file_decoder *decoder, s16 *data, int len)
|
||
{
|
||
/*int wlen = tws_api_local_media_trans_bulk_push((u8 *)data, len);*/
|
||
struct file_dec_hdl *dec = container_of(decoder, struct file_dec_hdl, file_dec);
|
||
int wlen = 0;
|
||
#if TCFG_DEC2TWS_ENABLE
|
||
/*wlen = tws_api_local_media_push_with_sequence((u8 *)data, len, file_dec->tx_seqn);*/
|
||
u32 timestamp = 0;
|
||
if (dec->ts_handle) {
|
||
timestamp = file_audio_timestamp_update(dec->ts_handle, dec->pcm_num);
|
||
}
|
||
wlen = tws_api_local_media_push_with_timestamp((u8 *)data, len, timestamp);
|
||
if (wlen) {
|
||
u16 pcm_num = 0;
|
||
memcpy(&pcm_num, data, sizeof(pcm_num));
|
||
/*printf("Num : %d x 32\n", pcm_num);*/
|
||
dec->pcm_num += (pcm_num * 32);
|
||
/*file_dec->tx_seqn++;*/
|
||
}
|
||
#endif
|
||
/*printf("trans: %d, %d\n", wlen, len);*/
|
||
return wlen;
|
||
}
|
||
|
||
static int tws_file_decoder_syncts_setup(struct file_dec_hdl *dec)
|
||
{
|
||
int err = 0;
|
||
#if TCFG_DEC2TWS_ENABLE
|
||
struct audio_syncts_params params = {0};
|
||
params.nch = file_dec_output_channel_num();
|
||
params.pcm_device = PCM_INSIDE_DAC;
|
||
params.network = AUDIO_NETWORK_BT2_1;
|
||
params.rin_sample_rate = dec->file_dec.sample_rate;
|
||
params.rout_sample_rate = dec->file_dec.sample_rate;
|
||
params.priv = dec;
|
||
params.factor = TIME_US_FACTOR;
|
||
params.output = file_decoder_output_after_syncts;
|
||
|
||
bt_audio_sync_nettime_select(1);
|
||
err = audio_syncts_open(&dec->syncts, ¶ms);
|
||
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);
|
||
}
|
||
#endif
|
||
return err;
|
||
}
|
||
|
||
|
||
|
||
static void tws_file_decoder_syncts_free(struct file_dec_hdl *dec)
|
||
{
|
||
#if TCFG_DEC2TWS_ENABLE
|
||
if (dec->syncts) {
|
||
audio_syncts_close(dec->syncts);
|
||
dec->syncts = NULL;
|
||
}
|
||
#endif
|
||
}
|
||
static int tws_data_trans_handler(struct file_decoder *dec, s16 *data, int len)
|
||
{
|
||
int wlen = 0;
|
||
|
||
#if TCFG_DEC2TWS_ENABLE
|
||
u8 *buf = tws_api_data_trans_buf_alloc(file_dec->tws_channel, len + 2);
|
||
if (!buf) {
|
||
return 0;
|
||
}
|
||
|
||
memcpy(buf, &file_dec->tx_seqn, 2);
|
||
memcpy(buf + 2, data, len);
|
||
tws_api_data_trans_push(file_dec->tws_channel, buf, len + 2);
|
||
file_dec->tx_seqn++;
|
||
#endif
|
||
/*printf("trans: %d, %d\n", wlen, len);*/
|
||
return len;
|
||
}
|
||
|
||
/*----------------------------------------------------------------------------*/
|
||
/**@brief 文件解码开始
|
||
@param
|
||
@return 0:成功
|
||
@return 非0:失败
|
||
@note
|
||
*/
|
||
/*----------------------------------------------------------------------------*/
|
||
static int file_dec_start()
|
||
{
|
||
int err;
|
||
enum audio_channel channel;
|
||
struct file_dec_hdl *dec = file_dec;
|
||
struct audio_mixer *p_mixer = &mixer;
|
||
|
||
if (!dec) {
|
||
return -EINVAL;
|
||
}
|
||
|
||
log_i("file_dec_start: in\n");
|
||
|
||
// 打开file解码器
|
||
#if TCFG_DEC2TWS_ENABLE
|
||
err = frame_decoder_open(&dec->file_dec, &frame_input, &decode_task);
|
||
#else
|
||
err = file_decoder_open(&dec->file_dec, &file_input, &decode_task, dec->bp, 0);
|
||
#endif
|
||
if (err) {
|
||
goto __err1;
|
||
}
|
||
dec->file_dec.output_handler = file_decoder_output_hander;
|
||
file_decoder_set_event_handler(&dec->file_dec, file_dec_event_handler, dec->id);
|
||
|
||
channel = file_dec_get_output_channel();
|
||
audio_decoder_set_output_channel(&dec->file_dec.decoder, channel);
|
||
|
||
#if (SYS_VOL_TYPE == VOL_TYPE_DIGITAL)
|
||
audio_digital_vol_open(MUSIC_DVOL, app_audio_get_volume(APP_AUDIO_STATE_MUSIC), MUSIC_DVOL_MAX, MUSIC_DVOL_FS, -1);
|
||
#endif/*SYS_VOL_TYPE == VOL_TYPE_DIGITAL*/
|
||
|
||
// 设置叠加功能
|
||
audio_mixer_ch_open(&dec->mix_ch, p_mixer);
|
||
audio_mixer_ch_set_sample_rate(&dec->mix_ch, dec->file_dec.sample_rate);
|
||
int ch_num = 1;
|
||
if (channel == AUDIO_CH_LR) {
|
||
ch_num = 2;
|
||
}
|
||
file_eq_drc_open(dec, dec->file_dec.sample_rate, ch_num);
|
||
|
||
sound_pcm_dev_channel_mapping(ch_num);
|
||
|
||
#if TCFG_DEC2TWS_ENABLE
|
||
tws_file_decoder_syncts_setup(dec);
|
||
#endif
|
||
|
||
app_audio_state_switch(APP_AUDIO_STATE_MUSIC, get_max_sys_vol());
|
||
|
||
// 设置时钟
|
||
/*clk_set("sys", 120000000);*/
|
||
audio_codec_clock_set(AUDIO_FILE_MODE, dec->file_dec.coding_type, dec->wait.preemption);
|
||
|
||
dec->file_dec.status = FILE_DEC_STATUS_PLAY;
|
||
if (dec->evt_cb) {
|
||
int msg[2];
|
||
msg[0] = AUDIO_DEC_EVENT_START;
|
||
dec->evt_cb(dec->evt_priv, 2, msg);
|
||
}
|
||
|
||
err = audio_decoder_start(&dec->file_dec.decoder);
|
||
if (err) {
|
||
goto __err2;
|
||
}
|
||
|
||
return 0;
|
||
|
||
__err2:
|
||
dec->file_dec.status = 0;
|
||
audio_mixer_ch_close(&dec->mix_ch);
|
||
file_eq_drc_close(dec);
|
||
file_decoder_close(&dec->file_dec);
|
||
|
||
__err1:
|
||
if (dec->evt_cb && (dec->wait_add)) {
|
||
int msg[2];
|
||
msg[0] = AUDIO_DEC_EVENT_ERR;
|
||
dec->evt_cb(dec->evt_priv, 2, msg);
|
||
}
|
||
file_dec_release();
|
||
/*clk_set("sys", 24000000);*/
|
||
audio_codec_clock_del(AUDIO_FILE_MODE);
|
||
|
||
return err;
|
||
}
|
||
|
||
#if TCFG_DEC2TWS_ENABLE
|
||
static void tws_file_trans_timestamp_free(struct file_dec_hdl *dec)
|
||
{
|
||
if (dec->ts_handle) {
|
||
file_audio_timestamp_close(dec->ts_handle);
|
||
dec->ts_handle = NULL;
|
||
}
|
||
}
|
||
|
||
static void tws_file_trans_timestamp_create(struct file_dec_hdl *dec)
|
||
{
|
||
tws_file_trans_timestamp_free(dec);
|
||
bt_audio_sync_nettime_select(1);
|
||
dec->ts_handle = file_audio_timestamp_create(0, dec->trans_dec.sample_rate, bt_audio_sync_lat_time(), 250, TIME_US_FACTOR);
|
||
dec->pcm_num = 0;
|
||
}
|
||
static void send_data_trans_dec_start_cmd();
|
||
static int tws_file_dec_trans_start(void)
|
||
{
|
||
int err;
|
||
u8 channel = AUDIO_CH_LR;
|
||
struct file_dec_hdl *dec = file_dec;
|
||
|
||
if (!dec) {
|
||
return -EINVAL;
|
||
}
|
||
|
||
log_i("file_dec_trans_start: in\n");
|
||
|
||
// 打开file解码器
|
||
err = file_decoder_open(&dec->trans_dec, &file_input, &decode_task, dec->bp, 1);
|
||
if (err) {
|
||
goto __err1;
|
||
}
|
||
dec->tx_seqn = 1;
|
||
dec->trans_dec.output_handler = tws_data_trans_handler;
|
||
file_decoder_set_event_handler(&dec->trans_dec, file_dec_event_handler, dec->id);
|
||
audio_decoder_set_output_channel(&dec->trans_dec.decoder, channel);
|
||
audio_decoder_set_run_max(&dec->trans_dec.decoder, 5);
|
||
|
||
dec->file_dec.sample_rate = dec->trans_dec.sample_rate;
|
||
dec->file_dec.coding_type = dec->trans_dec.coding_type & 0x0fffffff;
|
||
|
||
log_i("total_time : %d\n", dec->trans_dec.dec_total_time);
|
||
|
||
// 设置时钟
|
||
/*clk_set("sys", 120000000);*/
|
||
audio_codec_clock_set(AUDIO_FILE_MODE, dec->file_dec.coding_type, dec->wait.preemption);
|
||
|
||
dec->tws_channel = tws_api_data_trans_open(dec->tws_channel,
|
||
TWS_DTC_LOCAL_MEDIA, 10 * 1024);
|
||
|
||
send_data_trans_dec_start_cmd();
|
||
|
||
int ch_num = 1;
|
||
if (channel == AUDIO_CH_LR) {
|
||
ch_num = 2;
|
||
}
|
||
|
||
/* file_eq_drc_open(dec, dec->file_dec.sample_rate, ch_num); */
|
||
tws_file_trans_timestamp_create(dec);
|
||
dec->trans_dec_end = 0;
|
||
dec->trans_dec.status = FILE_DEC_STATUS_PLAY;
|
||
err = audio_decoder_start(&dec->trans_dec.decoder);
|
||
if (err) {
|
||
goto __err2;
|
||
}
|
||
|
||
return 0;
|
||
|
||
__err2:
|
||
dec->file_dec.status = 0;
|
||
file_decoder_close(&dec->file_dec);
|
||
tws_file_trans_timestamp_free(dec);
|
||
tws_api_data_trans_stop(dec->tws_channel);
|
||
file_eq_drc_close(dec);
|
||
|
||
__err1:
|
||
file_dec_release();
|
||
/*clk_set("sys", 24000000);*/
|
||
audio_codec_clock_del(AUDIO_FILE_MODE);
|
||
|
||
return err;
|
||
}
|
||
#endif
|
||
/*----------------------------------------------------------------------------*/
|
||
/**@brief 文件解码资源等待
|
||
@param *wait: 句柄
|
||
@param event: 事件
|
||
@return 0:成功
|
||
@note 用于多解码打断处理
|
||
*/
|
||
/*----------------------------------------------------------------------------*/
|
||
static int file_wait_res_handler(struct audio_res_wait *wait, int event)
|
||
{
|
||
int err = 0;
|
||
|
||
log_i("file_wait_res_handler, event:%d, status:%d ", event,
|
||
file_dec->file_dec.status);
|
||
|
||
if (event == AUDIO_RES_GET) {
|
||
// 启动解码
|
||
if (file_dec->file_dec.status == 0) {
|
||
err = file_dec_start();
|
||
} else if (file_dec->file_dec.tmp_pause) {
|
||
file_dec->file_dec.tmp_pause = 0;
|
||
if (file_dec->file_dec.status == FILE_DEC_STATUS_PLAY) {
|
||
audio_mixer_ch_open(&file_dec->mix_ch, &mixer);
|
||
#if TCFG_DEC2TWS_ENABLE
|
||
tws_api_auto_drop_frame_enable(0);
|
||
tws_file_decoder_syncts_setup(file_dec);
|
||
#endif
|
||
err = audio_decoder_start(&file_dec->file_dec.decoder);
|
||
audio_decoder_resume_all(&decode_task);
|
||
} else if (file_dec->file_dec.status == FILE_DEC_STATUS_PAUSE) {
|
||
audio_mixer_ch_open(&file_dec->mix_ch, &mixer);
|
||
}
|
||
}
|
||
} else if (event == AUDIO_RES_PUT) {
|
||
// 被打断
|
||
if (file_dec->file_dec.status) {
|
||
if (file_dec->file_dec.status == FILE_DEC_STATUS_PLAY || \
|
||
file_dec->file_dec.status == FILE_DEC_STATUS_PAUSE) {
|
||
audio_decoder_resume_all(&decode_task);
|
||
err = audio_decoder_pause(&file_dec->file_dec.decoder);
|
||
audio_mixer_ch_close(&file_dec->mix_ch);
|
||
#if TCFG_DEC2TWS_ENABLE
|
||
tws_file_decoder_syncts_free(file_dec);
|
||
tws_api_auto_drop_frame_enable(1);
|
||
#endif
|
||
}
|
||
file_dec->file_dec.tmp_pause = 1;
|
||
}
|
||
}
|
||
|
||
return err;
|
||
}
|
||
|
||
#if TCFG_DEC2TWS_ENABLE
|
||
|
||
static void send_data_trans_dec_start_cmd()
|
||
{
|
||
u8 args[8];
|
||
|
||
if (file_dec->file_dec.status) {
|
||
u32 data[1];
|
||
data[0] = FILE_DEC_INVITE;
|
||
tws_api_send_data_to_sibling(data, sizeof(data), TWS_FUNC_ID_FILE_DEC);
|
||
}
|
||
|
||
if (file_dec->file_dec.coding_type == AUDIO_CODING_MP3) {
|
||
args[0] = 1;
|
||
} else if (file_dec->file_dec.coding_type == AUDIO_CODING_WMA) {
|
||
args[0] = 2;
|
||
}
|
||
args[1] = file_dec->file_dec.sample_rate;
|
||
args[2] = file_dec->file_dec.sample_rate >> 8;
|
||
args[3] = file_dec->id & 0xff;
|
||
|
||
tws_api_data_trans_start(file_dec->tws_channel, args, 4);
|
||
}
|
||
|
||
|
||
static int tws_file_wait_res_handler(struct audio_res_wait *wait, int event)
|
||
{
|
||
int err = 0;
|
||
|
||
log_i("tws_file_wait_res_handler, event:%d, status:%d ", event,
|
||
file_dec->trans_dec.status);
|
||
|
||
if (event == AUDIO_RES_GET) {
|
||
// 启动解码
|
||
if (file_dec->trans_dec.status == 0) {
|
||
err = tws_file_dec_trans_start();
|
||
if (err) {
|
||
return err;
|
||
}
|
||
} else if (file_dec->trans_dec.tmp_pause) {
|
||
file_dec->trans_dec.tmp_pause = 0;
|
||
if (file_dec->trans_dec.status == FILE_DEC_STATUS_PLAY) {
|
||
err = audio_decoder_start(&file_dec->trans_dec.decoder);
|
||
}
|
||
}
|
||
} else if (event == AUDIO_RES_PUT) {
|
||
// 被打断
|
||
if (file_dec->trans_dec.status) {
|
||
if (file_dec->trans_dec.status == FILE_DEC_STATUS_PLAY || \
|
||
file_dec->trans_dec.status == FILE_DEC_STATUS_PAUSE) {
|
||
err = audio_decoder_pause(&file_dec->trans_dec.decoder);
|
||
}
|
||
file_dec->trans_dec.tmp_pause = 1;
|
||
}
|
||
}
|
||
|
||
file_wait_res_handler(wait, event);
|
||
|
||
return err;
|
||
}
|
||
|
||
void send_local_media_dec_open_cmd()
|
||
{
|
||
puts("send_local_media_dec_open_cmd\n");
|
||
|
||
if (!file_dec) {
|
||
return;
|
||
}
|
||
if (file_dec->trans_dec.status) {
|
||
puts("---trans_open\n");
|
||
file_dec->tws_channel = tws_api_data_trans_open(file_dec->tws_channel,
|
||
TWS_DTC_LOCAL_MEDIA, 10 * 1024);
|
||
}
|
||
if (file_dec->file_dec.status) {
|
||
puts("---dec_open\n");
|
||
send_data_trans_dec_start_cmd();
|
||
}
|
||
}
|
||
|
||
#endif
|
||
/*----------------------------------------------------------------------------*/
|
||
/**@brief file解码pp处理
|
||
@param play: 1-播放。0-暂停
|
||
@return
|
||
@note 弱函数重定义
|
||
*/
|
||
/*----------------------------------------------------------------------------*/
|
||
static void file_dec_pp_ctrl(u8 play)
|
||
{
|
||
if (!file_dec) {
|
||
return ;
|
||
}
|
||
#if TCFG_DEC2TWS_ENABLE
|
||
if (play) {
|
||
// 播放前处理
|
||
if (!file_dec->pick_flag) {
|
||
audio_mixer_ch_pause(&file_dec->mix_ch, 0);
|
||
}
|
||
} else {
|
||
// 暂停后处理
|
||
if (!file_dec->pick_flag) {
|
||
audio_mixer_ch_pause(&file_dec->mix_ch, 1);
|
||
}
|
||
audio_decoder_resume_all_by_sem(&decode_task, 2); // 超时等待解码task运行一轮
|
||
}
|
||
#else
|
||
if (play) {
|
||
// 播放前处理
|
||
if (!file_dec->pick_flag) {
|
||
audio_mixer_ch_open(&file_dec->mix_ch, &mixer);
|
||
}
|
||
} else {
|
||
// 暂停后处理
|
||
if (!file_dec->pick_flag) {
|
||
audio_mixer_ch_close(&file_dec->mix_ch);
|
||
}
|
||
audio_decoder_resume_all_by_sem(&decode_task, 2); // 超时等待解码task运行一轮
|
||
}
|
||
|
||
#endif
|
||
}
|
||
|
||
/*----------------------------------------------------------------------------*/
|
||
/**@brief 创建一个文件解码
|
||
@param *priv: 事件回调私有参数
|
||
@param *handler: 事件回调句柄
|
||
@return 0:成功
|
||
@return 非0:失败
|
||
@note
|
||
*/
|
||
/*----------------------------------------------------------------------------*/
|
||
int file_dec_create(void *priv, void (*handler)(void *, int argc, int *argv))
|
||
{
|
||
struct file_dec_hdl *dec;
|
||
if (file_dec) {
|
||
file_dec_close();
|
||
}
|
||
|
||
dec = zalloc(sizeof(*dec));
|
||
if (!dec) {
|
||
return -ENOMEM;
|
||
}
|
||
|
||
file_dec = dec;
|
||
file_dec->evt_cb = handler;
|
||
file_dec->evt_priv = priv;
|
||
|
||
return 0;
|
||
}
|
||
|
||
/*----------------------------------------------------------------------------*/
|
||
/**@brief 设置解码数据流设置回调接口
|
||
@param *dec: 解码句柄
|
||
@param *stream_handler: 数据流设置回调
|
||
@param *stream_priv: 数据流设置回调私有句柄
|
||
@return
|
||
@note
|
||
*/
|
||
/*----------------------------------------------------------------------------*/
|
||
void file_dec_set_stream_set_hdl(struct file_dec_hdl *dec,
|
||
void (*stream_handler)(void *priv, int event, struct file_dec_hdl *),
|
||
void *stream_priv)
|
||
{
|
||
if (dec) {
|
||
dec->stream_handler = stream_handler;
|
||
dec->stream_priv = stream_priv;
|
||
}
|
||
}
|
||
|
||
/*----------------------------------------------------------------------------*/
|
||
/**@brief 打开文件解码
|
||
@param *file: 文件句柄
|
||
@param *bp: 断点信息
|
||
@return 0:成功
|
||
@return 非0:失败
|
||
@note
|
||
*/
|
||
/*----------------------------------------------------------------------------*/
|
||
int file_dec_open(void *file, struct audio_dec_breakpoint *bp)
|
||
{
|
||
int err;
|
||
struct file_dec_hdl *dec = file_dec;
|
||
|
||
log_i("file_dec_open: in, 0x%x, bp:0x%x \n", file, bp);
|
||
|
||
if ((!dec) || (!file)) {
|
||
return -EPERM;
|
||
}
|
||
dec->file = file;
|
||
dec->bp = bp;
|
||
dec->id = rand32();
|
||
|
||
dec->file_dec.ch_type = AUDIO_CH_MAX;
|
||
dec->file_dec.output_ch_num = 2;//audio_output_channel_num();
|
||
|
||
#if TCFG_DEC_DECRYPT_ENABLE
|
||
cipher_init(&dec->mply_cipher, TCFG_DEC_DECRYPT_KEY);
|
||
cipher_check_decode_file(&dec->mply_cipher, file);
|
||
#endif
|
||
dec->wait_add = 1;
|
||
#if TCFG_DEC2TWS_ENABLE
|
||
dec->wait.priority = 1;
|
||
dec->wait.preemption = 1;
|
||
dec->wait.handler = tws_file_wait_res_handler;
|
||
err = audio_decoder_task_add_wait(&decode_task, &dec->wait);
|
||
#else
|
||
dec->wait.priority = 1;
|
||
dec->wait.preemption = 1;
|
||
dec->wait.handler = file_wait_res_handler;
|
||
err = audio_decoder_task_add_wait(&decode_task, &dec->wait);
|
||
#endif
|
||
if (file_dec) {
|
||
file_dec->wait_add = 0;
|
||
}
|
||
|
||
return err;
|
||
}
|
||
|
||
int tws_local_media_dec_open(u8 channel, u8 *arg)
|
||
{
|
||
int err;
|
||
struct file_dec_hdl *dec = file_dec;
|
||
|
||
log_i("tws_local_media_dec_open\n");
|
||
|
||
if (!dec) {
|
||
dec = zalloc(sizeof(*dec));
|
||
if (!dec) {
|
||
return -EPERM;
|
||
}
|
||
file_dec = dec;
|
||
}
|
||
|
||
if (arg[0] == 1) {
|
||
dec->file_dec.coding_type = AUDIO_CODING_MP3;
|
||
} else if (arg[0] == 2) {
|
||
dec->file_dec.coding_type = AUDIO_CODING_WMA;
|
||
}
|
||
dec->file_dec.sample_rate = (arg[2] << 8) | arg[1];
|
||
dec->id = arg[3];
|
||
#if TCFG_USER_TWS_ENABLE
|
||
dec->tws_channel = channel;
|
||
#endif
|
||
|
||
dec->wait.priority = 1;
|
||
dec->wait.preemption = 1;
|
||
dec->wait.handler = file_wait_res_handler;
|
||
err = audio_decoder_task_add_wait(&decode_task, &dec->wait);
|
||
|
||
return err;
|
||
}
|
||
|
||
int tws_local_media_dec_state()
|
||
{
|
||
if (!file_dec) {
|
||
return 0;
|
||
}
|
||
if (file_dec->file_dec.status == FILE_DEC_STATUS_PLAY) {
|
||
return 1;
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
static void __file_dec_close(void)
|
||
{
|
||
if (!file_dec) {
|
||
return;
|
||
}
|
||
|
||
if (file_dec->file_dec.status) {
|
||
file_dec->file_dec.status = 0;
|
||
audio_mixer_ch_pause(&file_dec->mix_ch, 1);
|
||
file_decoder_close(&file_dec->file_dec);
|
||
file_eq_drc_close(file_dec);
|
||
tws_file_decoder_syncts_free(file_dec);
|
||
audio_mixer_ch_close(&file_dec->mix_ch);
|
||
|
||
if (file_dec->stream_handler) {
|
||
file_dec->stream_handler(file_dec->stream_priv, FILE_DEC_STREAM_CLOSE,
|
||
file_dec);
|
||
}
|
||
#if TCFG_DEC2TWS_ENABLE
|
||
if (file_dec->frame) {
|
||
tws_api_data_trans_free(file_dec->tws_channel, file_dec->frame);
|
||
file_dec->frame = NULL;
|
||
}
|
||
#endif
|
||
}
|
||
|
||
file_dec_release();
|
||
|
||
log_i("file_dec_close: exit\n");
|
||
}
|
||
|
||
/*----------------------------------------------------------------------------*/
|
||
/**@brief 关闭文件解码
|
||
@param
|
||
@return
|
||
@note
|
||
*/
|
||
/*----------------------------------------------------------------------------*/
|
||
void file_dec_close(void)
|
||
{
|
||
#if TCFG_DEC2TWS_ENABLE
|
||
if (!file_dec) {
|
||
return;
|
||
}
|
||
if (file_dec->trans_dec.status) {
|
||
file_dec->trans_dec.status = 0;
|
||
file_decoder_close(&file_dec->trans_dec);
|
||
tws_api_data_trans_stop(file_dec->tws_channel);
|
||
file_eq_drc_close(file_dec);
|
||
}
|
||
|
||
tws_file_trans_timestamp_free(file_dec);
|
||
tws_api_data_trans_clear(file_dec->tws_channel);
|
||
#endif
|
||
__file_dec_close();
|
||
|
||
}
|
||
|
||
#if TCFG_DEC2TWS_ENABLE
|
||
void tws_local_media_dec_close()
|
||
{
|
||
file_dec_close();
|
||
}
|
||
#endif
|
||
|
||
/*----------------------------------------------------------------------------*/
|
||
/**@brief 获取file_dec句柄
|
||
@param
|
||
@return file_dec句柄
|
||
@note
|
||
*/
|
||
/*----------------------------------------------------------------------------*/
|
||
struct file_decoder *file_dec_get_file_decoder_hdl(void)
|
||
{
|
||
if (!file_dec) {
|
||
return NULL;
|
||
}
|
||
|
||
#if TCFG_DEC2TWS_ENABLE
|
||
return &file_dec->trans_dec;
|
||
#else
|
||
return &file_dec->file_dec;
|
||
#endif
|
||
}
|
||
|
||
/*----------------------------------------------------------------------------*/
|
||
/**@brief 获取file_dec状态
|
||
@param
|
||
@return 解码状态
|
||
@note
|
||
*/
|
||
/*----------------------------------------------------------------------------*/
|
||
int file_dec_get_status(void)
|
||
{
|
||
struct file_decoder *dec = file_dec_get_file_decoder_hdl();
|
||
if (dec) {
|
||
return dec->status;
|
||
}
|
||
return FILE_DEC_STATUS_STOP;
|
||
}
|
||
|
||
int file_dec_get_source()
|
||
{
|
||
if (!file_dec) {
|
||
return -EINVAL;
|
||
}
|
||
#if TCFG_DEC2TWS_ENABLE
|
||
if (file_dec->trans_dec.status) {
|
||
return FILE_FROM_LOCAL;
|
||
}
|
||
if (file_dec->file_dec.status) {
|
||
return FILE_FROM_TWS;
|
||
}
|
||
#else
|
||
if (file_dec->file_dec.status) {
|
||
return FILE_FROM_LOCAL;
|
||
}
|
||
#endif
|
||
return -EINVAL;
|
||
}
|
||
|
||
/*----------------------------------------------------------------------------*/
|
||
/**@brief 文件解码重新开始
|
||
@param id: 文件解码id
|
||
@return 0:成功
|
||
@return 非0:失败
|
||
@note
|
||
*/
|
||
/*----------------------------------------------------------------------------*/
|
||
int file_dec_restart(int id)
|
||
{
|
||
if ((!file_dec) || (id != file_dec->id)) {
|
||
return -1;
|
||
}
|
||
if (file_dec->bp == NULL) {
|
||
if (file_dec->dec_bp == NULL) {
|
||
file_dec->dec_bp = zalloc(sizeof(struct audio_dec_breakpoint) +
|
||
BREAKPOINT_DATA_LEN);
|
||
ASSERT(file_dec->dec_bp);
|
||
file_dec->dec_bp->data_len = BREAKPOINT_DATA_LEN;
|
||
}
|
||
file_dec->bp = file_dec->dec_bp;
|
||
}
|
||
if (file_dec->file_dec.status && file_dec->bp) {
|
||
audio_decoder_get_breakpoint(&file_dec->file_dec.decoder, file_dec->bp);
|
||
}
|
||
|
||
void *file = file_dec->file;
|
||
void *bp = file_dec->bp;
|
||
void *evt_cb = file_dec->evt_cb;
|
||
void *evt_priv = file_dec->evt_priv;
|
||
int err;
|
||
void *dec_bp = file_dec->dec_bp; // 先保存一下,避免close被释放
|
||
file_dec->dec_bp = NULL;
|
||
|
||
file_dec_close();
|
||
|
||
err = file_dec_create(evt_priv, evt_cb);
|
||
if (!err) {
|
||
file_dec->dec_bp = dec_bp; // 还原回去
|
||
err = file_dec_open(file, bp);
|
||
} else {
|
||
if (dec_bp) {
|
||
free(dec_bp); // 失败,释放
|
||
}
|
||
}
|
||
return err;
|
||
}
|
||
|
||
/*----------------------------------------------------------------------------*/
|
||
/**@brief 推送文件解码重新开始命令
|
||
@param
|
||
@return true:成功
|
||
@return false:失败
|
||
@note
|
||
*/
|
||
/*----------------------------------------------------------------------------*/
|
||
int file_dec_push_restart(void)
|
||
{
|
||
if (!file_dec) {
|
||
return false;
|
||
}
|
||
int argv[3];
|
||
argv[0] = (int)file_dec_restart;
|
||
argv[1] = 1;
|
||
argv[2] = (int)file_dec->id;
|
||
os_taskq_post_type(os_current_task(), Q_CALLBACK, ARRAY_SIZE(argv), argv);
|
||
return true;
|
||
}
|
||
|
||
/*----------------------------------------------------------------------------*/
|
||
/**@brief file decoder pp处理
|
||
@param *dec: file解码句柄
|
||
@param play: 1-播放。0-暂停
|
||
@return
|
||
@note 弱函数重定义
|
||
*/
|
||
/*----------------------------------------------------------------------------*/
|
||
void file_decoder_pp_ctrl(struct file_decoder *dec, u8 play)
|
||
{
|
||
if (file_dec && (&file_dec->file_dec == dec)) {
|
||
file_dec_pp_ctrl(play);
|
||
}
|
||
}
|
||
|
||
/*----------------------------------------------------------------------------*/
|
||
/**@brief 音乐模式 eq drc 打开
|
||
@param sample_rate:采样率
|
||
@param ch_num:通道个数
|
||
@return 句柄
|
||
@note
|
||
*/
|
||
/*----------------------------------------------------------------------------*/
|
||
void file_eq_drc_open(struct file_dec_hdl *hdl, u16 sample_rate, u8 ch_num)
|
||
{
|
||
#if TCFG_EQ_ENABLE&&TCFG_MUSIC_MODE_EQ_ENABLE
|
||
u8 drc_en = 0;
|
||
#if TCFG_DRC_ENABLE&&TCFG_MUSIC_MODE_DRC_ENABLE
|
||
drc_en = 1;
|
||
#endif//TCFG_MUSIC_MODE_DRC_ENABLE
|
||
|
||
hdl->eq_drc = dec_eq_drc_setup(&hdl->mix_ch, (eq_output_cb)audio_mixer_ch_write, sample_rate, ch_num, 1, drc_en);
|
||
#endif//TCFG_MUSIC_MODE_EQ_ENABLE
|
||
|
||
}
|
||
/*----------------------------------------------------------------------------*/
|
||
/**@brief 音乐模式 eq drc 关闭
|
||
@param 句柄
|
||
@return
|
||
@note
|
||
*/
|
||
/*----------------------------------------------------------------------------*/
|
||
void file_eq_drc_close(struct file_dec_hdl *hdl)
|
||
{
|
||
#if TCFG_EQ_ENABLE&&TCFG_MUSIC_MODE_EQ_ENABLE
|
||
if (hdl->eq_drc) {
|
||
dec_eq_drc_free(hdl->eq_drc);
|
||
hdl->eq_drc = NULL;
|
||
}
|
||
#endif//TCFG_MUSIC_MODE_EQ_ENABLE
|
||
|
||
}
|
||
|
||
|
||
#endif /*TCFG_APP_MUSIC_EN*/
|
||
|