918 lines
29 KiB
C
918 lines
29 KiB
C
#include "system/includes.h"
|
||
#include "media/includes.h"
|
||
#include "tone_player.h"
|
||
#include "audio_config.h"
|
||
#include "app_main.h"
|
||
#include "clock_cfg.h"
|
||
#include "audio_dec.h"
|
||
|
||
#define AUDIO_DEC_TONE_AT_CODE_EVENT_CB AT(.audio_dec_tone_event_callback)
|
||
|
||
#define AUDIO_DEC_TONE_WAIT_USE_PRIO 0 // 采用优先级顺序播放方式
|
||
|
||
extern struct audio_dac_hdl dac_hdl;
|
||
extern struct audio_dac_channel default_dac;
|
||
extern const int audio_dec_app_mix_en;
|
||
|
||
//////////////////////////////////////////////////////////////////////////////
|
||
extern int audio_dec_file_app_init_ok(struct audio_dec_file_app_hdl *file_dec);
|
||
extern int audio_dec_sine_app_init_ok(struct audio_dec_sine_app_hdl *sine_dec);
|
||
extern int audio_dec_file_app_play_end(struct audio_dec_file_app_hdl *file_dec);
|
||
extern int audio_dec_sine_app_play_end(struct audio_dec_sine_app_hdl *sine_dec);
|
||
|
||
static int tone_dec_list_play(struct tone_dec_handle *dec, u8 next);
|
||
|
||
//////////////////////////////////////////////////////////////////////////////
|
||
|
||
/*----------------------------------------------------------------------------*/
|
||
/**@brief tone解码数据流推送stop
|
||
@param *dec: 解码句柄
|
||
@return
|
||
@note
|
||
*/
|
||
/*----------------------------------------------------------------------------*/
|
||
static void tone_dec_stream_run_stop(struct audio_dec_app_hdl *dec)
|
||
{
|
||
#if AUDIO_DAC_MULTI_CHANNEL_ENABLE
|
||
struct audio_data_frame frame = {0};
|
||
struct audio_data_frame output = {0};
|
||
frame.stop = 1;
|
||
frame.channel = audio_output_channel_num();
|
||
frame.sample_rate = app_audio_output_samplerate_get();
|
||
/* audio_stream_run(&default_dac.entry, &frame); */
|
||
default_dac.entry.data_handler(&default_dac.entry, &frame, &output);
|
||
audio_stream_del_entry(&default_dac.entry);
|
||
#else /*AUDIO_DAC_MULTI_CHANNEL_ENABLE*/
|
||
audio_dac_stop(&dac_hdl);
|
||
#endif /*AUDIO_DAC_MULTI_CHANNEL_ENABLE*/
|
||
}
|
||
|
||
#if TONE_DEC_PROTECT_LIST_PLAY
|
||
struct tone_dec_list_protect {
|
||
struct audio_res_wait wait;
|
||
};
|
||
/*----------------------------------------------------------------------------*/
|
||
/**@brief tone链表播放保护用的临时解码资源等待
|
||
@param *wait: 句柄
|
||
@param event: 事件
|
||
@return 0:成功
|
||
@note
|
||
*/
|
||
/*----------------------------------------------------------------------------*/
|
||
static int tone_dec_list_protect_res_handler(struct audio_res_wait *wait, int event)
|
||
{
|
||
y_printf("tone protect event:%d \n", event);
|
||
return 0;
|
||
}
|
||
/*----------------------------------------------------------------------------*/
|
||
/**@brief tone链表播放保护用的临时解码释放
|
||
@param *dec: 解码链表句柄
|
||
@return
|
||
@note
|
||
*/
|
||
/*----------------------------------------------------------------------------*/
|
||
static void tone_dec_list_protect_release(struct tone_dec_list_handle *dec_list)
|
||
{
|
||
if ((!dec_list) || (!dec_list->list_protect)) {
|
||
return ;
|
||
}
|
||
y_printf("tone_dec_list_protect_release \n");
|
||
struct tone_dec_list_protect *prot = dec_list->list_protect;
|
||
audio_decoder_task_del_wait(&decode_task, &prot->wait);
|
||
free(dec_list->list_protect);
|
||
dec_list->list_protect = NULL;
|
||
}
|
||
/*----------------------------------------------------------------------------*/
|
||
/**@brief tone链表播放保护用的临时解码处理
|
||
@param *dec_list: 解码链表句柄
|
||
@return
|
||
@note
|
||
*/
|
||
/*----------------------------------------------------------------------------*/
|
||
static void tone_dec_list_protect_deal(struct tone_dec_list_handle *dec_list)
|
||
{
|
||
if ((!dec_list) || (!dec_list->preemption)) {
|
||
return ;
|
||
}
|
||
if ((!dec_list->file_list) || (!dec_list->file_list[1])) {
|
||
return ;
|
||
}
|
||
if (dec_list->list_protect) {
|
||
return ;
|
||
}
|
||
struct tone_dec_list_protect *prot = zalloc(sizeof(struct tone_dec_list_protect));
|
||
if (!prot) {
|
||
return ;
|
||
}
|
||
y_printf("tone_dec_list_protect_deal \n");
|
||
dec_list->list_protect = prot;
|
||
#if AUDIO_DEC_TONE_WAIT_USE_PRIO
|
||
prot->wait.priority = 3;
|
||
prot->wait.preemption = 0;
|
||
prot->wait.snatch_same_prio = 1;
|
||
#else
|
||
prot->wait.preemption = 1;
|
||
#endif
|
||
prot->wait.handler = tone_dec_list_protect_res_handler;
|
||
audio_decoder_task_add_wait(&decode_task, &prot->wait);
|
||
}
|
||
#endif
|
||
|
||
/*----------------------------------------------------------------------------*/
|
||
/**@brief 获取文件名后缀
|
||
@param *name: 文件名
|
||
@return 后缀
|
||
@note
|
||
*/
|
||
/*----------------------------------------------------------------------------*/
|
||
static char *get_file_ext_name(char *name)
|
||
{
|
||
int len = strlen(name);
|
||
char *ext = (char *)name;
|
||
|
||
while (len--) {
|
||
if (*ext++ == '.') {
|
||
break;
|
||
}
|
||
}
|
||
if (len <= 0) {
|
||
ext = name + (strlen(name) - 3);
|
||
}
|
||
|
||
return ext;
|
||
}
|
||
|
||
/*----------------------------------------------------------------------------*/
|
||
/**@brief 提示音list解码事件
|
||
@param *dec_list: list句柄
|
||
@param end_flag: 结束类型
|
||
@return true: 成功
|
||
@return false: 成功
|
||
@note
|
||
*/
|
||
/*----------------------------------------------------------------------------*/
|
||
static int tone_dec_list_event_handler(struct tone_dec_list_handle *dec_list, u8 end_flag)
|
||
{
|
||
int argv[4];
|
||
if (!dec_list->evt_handler) {
|
||
log_i("evt_handler null\n");
|
||
return false;
|
||
}
|
||
argv[0] = (int)dec_list->evt_handler;
|
||
argv[1] = 2;
|
||
argv[2] = (int)dec_list->evt_priv;
|
||
argv[3] = (int)end_flag; //0正常关闭,1被打断关闭
|
||
|
||
int ret = os_taskq_post_type(dec_list->evt_owner, Q_CALLBACK, 4, argv);
|
||
if (ret) {
|
||
return false;
|
||
}
|
||
return true;
|
||
}
|
||
|
||
/*----------------------------------------------------------------------------*/
|
||
/**@brief 创建提示音播放句柄
|
||
@param
|
||
@return 提示音句柄
|
||
@note
|
||
*/
|
||
/*----------------------------------------------------------------------------*/
|
||
struct tone_dec_handle *tone_dec_create(void)
|
||
{
|
||
struct tone_dec_handle *dec = zalloc(sizeof(struct tone_dec_handle));
|
||
if (!dec) {
|
||
return NULL;
|
||
}
|
||
INIT_LIST_HEAD(&dec->head);
|
||
os_mutex_create(&dec->mutex);
|
||
return dec;
|
||
}
|
||
|
||
/*----------------------------------------------------------------------------*/
|
||
/**@brief 设置sine数组获取回调
|
||
@param *dec: 提示音句柄
|
||
@param *get_sine: sine数组获取
|
||
@return
|
||
@note
|
||
*/
|
||
/*----------------------------------------------------------------------------*/
|
||
void tone_dec_set_sin_get_hdl(struct tone_dec_handle *dec, struct sin_param * (*get_sine)(u8 id, u8 *num))
|
||
{
|
||
if (dec) {
|
||
dec->get_sine = get_sine;
|
||
}
|
||
}
|
||
|
||
/*----------------------------------------------------------------------------*/
|
||
/**@brief 提示音解码器释放
|
||
@param *dec: 提示音句柄
|
||
@return
|
||
@note
|
||
*/
|
||
/*----------------------------------------------------------------------------*/
|
||
static void tone_dec_hdl_release(struct tone_dec_handle *dec)
|
||
{
|
||
if (dec->dec_file) {
|
||
audio_dec_file_app_play_end(dec->dec_file);
|
||
dec->dec_file = NULL;
|
||
}
|
||
if (dec->dec_sin) {
|
||
audio_dec_sine_app_play_end(dec->dec_sin);
|
||
dec->dec_sin = NULL;
|
||
}
|
||
|
||
clock_remove_set(DEC_TONE_CLK);
|
||
}
|
||
|
||
/*----------------------------------------------------------------------------*/
|
||
/**@brief 提示音list释放
|
||
@param *dec_list: list句柄
|
||
@param push_event: 普通提示音是否推送消息
|
||
@param end_flag: 结束类型
|
||
@return
|
||
@note
|
||
*/
|
||
/*----------------------------------------------------------------------------*/
|
||
static void tone_dec_list_release(struct tone_dec_list_handle *dec_list, u8 push_event, u8 end_flag)
|
||
{
|
||
if (dec_list == NULL) {
|
||
return ;
|
||
}
|
||
if (push_event) {
|
||
tone_dec_list_event_handler(dec_list, end_flag);
|
||
}
|
||
#if TONE_DEC_PROTECT_LIST_PLAY
|
||
tone_dec_list_protect_release(dec_list);
|
||
#endif
|
||
list_del(&dec_list->list_entry);
|
||
if (dec_list->file_list) {
|
||
free(dec_list->file_list);
|
||
}
|
||
free(dec_list);
|
||
}
|
||
|
||
/*----------------------------------------------------------------------------*/
|
||
/**@brief 提示音解码结束处理
|
||
@param *dec: 提示音句柄
|
||
@return
|
||
@note
|
||
*/
|
||
/*----------------------------------------------------------------------------*/
|
||
static void tone_dec_end_ctrl(struct tone_dec_handle *dec)
|
||
{
|
||
os_mutex_pend(&dec->mutex, 0);
|
||
// 检查循环播放
|
||
int ret = tone_dec_list_play(dec, 1);
|
||
if (ret == true) {
|
||
os_mutex_post(&dec->mutex);
|
||
return ;
|
||
}
|
||
// 发送播放完成
|
||
tone_dec_list_release(dec->cur_list, 1, TONE_DEC_STOP_NOR);
|
||
dec->cur_list = NULL;
|
||
|
||
// 检查链表播放
|
||
struct list_head *list_entry = dec->head.next;
|
||
if (list_entry && (list_entry != &dec->head)) {
|
||
struct tone_dec_list_handle *dec_list = container_of(list_entry, struct tone_dec_list_handle, list_entry);
|
||
dec->cur_list = dec_list;
|
||
tone_dec_list_play(dec, 0);
|
||
}
|
||
os_mutex_post(&dec->mutex);
|
||
}
|
||
|
||
/*----------------------------------------------------------------------------*/
|
||
/**@brief file提示音解码回调
|
||
@param *priv: 私有句柄
|
||
@param event: 事件
|
||
@param *param: 事件参数
|
||
@return 0: 成功
|
||
@note
|
||
*/
|
||
/*----------------------------------------------------------------------------*/
|
||
AUDIO_DEC_TONE_AT_CODE_EVENT_CB
|
||
static int tone_dec_file_app_evt_cb(void *priv, enum audio_dec_app_event event, int *param)
|
||
{
|
||
/* log_i("audio_dec_file_app_evt_cb, priv:0x%x, event:%d \n", priv, event); */
|
||
|
||
struct audio_dec_stream_entries_hdl *entries_hdl = (struct audio_dec_stream_entries_hdl *)param;
|
||
void *dvol_entry = NULL;
|
||
|
||
int ret ;
|
||
struct audio_dec_file_app_hdl *file_dec = priv;
|
||
struct tone_dec_handle *dec = file_dec->priv;
|
||
switch (event) {
|
||
case AUDIO_DEC_APP_EVENT_DEC_PROBE:
|
||
break;
|
||
case AUDIO_DEC_APP_EVENT_DEC_OUTPUT:
|
||
// param[0]:*data. param[1]:data_len
|
||
break;
|
||
case AUDIO_DEC_APP_EVENT_DEC_POST:
|
||
break;
|
||
case AUDIO_DEC_APP_EVENT_START_INIT_OK:
|
||
log_i("tone_file start init ok\n");
|
||
if (dec->cur_list->stream_handler) {
|
||
// 删除原有的数据流,需要在回调中重新设置
|
||
if (file_dec->dec->stream) {
|
||
audio_stream_del_entry(&file_dec->dec->mix_ch.entry);
|
||
audio_stream_del_entry(&file_dec->dec->decoder.entry);
|
||
audio_stream_close(file_dec->dec->stream);
|
||
file_dec->dec->stream = NULL;
|
||
}
|
||
dec->cur_list->stream_handler(dec->cur_list->stream_priv, event, file_dec->dec);
|
||
}
|
||
clock_add_set(DEC_TONE_CLK);
|
||
audio_dec_file_app_init_ok(file_dec);
|
||
break;
|
||
case AUDIO_DEC_APP_EVENT_DEC_CLOSE:
|
||
if (!audio_dec_app_mix_en) {
|
||
tone_dec_stream_run_stop(file_dec->dec);
|
||
}
|
||
if (dec->cur_list->stream_handler) {
|
||
dec->cur_list->stream_handler(dec->cur_list->stream_priv, event, file_dec->dec);
|
||
}
|
||
|
||
#if SYS_DIGVOL_GROUP_EN
|
||
if (dec->cur_list->stream_handler == NULL) {
|
||
sys_digvol_group_ch_close("tone_tone");
|
||
}
|
||
#endif // SYS_DIGVOL_GROUP_EN
|
||
|
||
#if AUDUO_DEC_TONE_HIGH_BASS_ENABLE
|
||
high_bass_eq_close(dec->high_bass);
|
||
dec->high_bass = NULL;
|
||
high_bass_drc_close(dec->hb_drc);
|
||
dec->hb_drc = NULL;
|
||
convet_data_close(dec->hb_convert);
|
||
dec->hb_convert = NULL;
|
||
#endif
|
||
|
||
|
||
break;
|
||
case AUDIO_DEC_APP_EVENT_START_OK:
|
||
dec->cur_list->dec_ok_cnt++;
|
||
break;
|
||
case AUDIO_DEC_APP_EVENT_START_ERR:
|
||
log_i("tone_file start err\n");
|
||
case AUDIO_DEC_APP_EVENT_PLAY_END:
|
||
log_i("tone_file play end\n");
|
||
tone_dec_end_ctrl(dec);
|
||
break;
|
||
case AUDIO_DEC_APP_EVENT_STREAM_OPEN:
|
||
|
||
#if SYS_DIGVOL_GROUP_EN
|
||
|
||
audio_dig_vol_param temp_digvol_param = {
|
||
.vol_start = get_max_sys_vol(),
|
||
.vol_max = get_max_sys_vol(),
|
||
.ch_total = 2,
|
||
.fade_en = 0, //提示音不能淡入淡出
|
||
.fade_points_step = 5,
|
||
.fade_gain_step = 10,
|
||
.vol_list = NULL,
|
||
};
|
||
|
||
if (dec->cur_list->stream_handler == NULL) {
|
||
dvol_entry = sys_digvol_group_ch_open("tone_tone", -1, &temp_digvol_param);
|
||
(entries_hdl->entries_addr)[entries_hdl->entries_cnt++] = dvol_entry;
|
||
}
|
||
#endif // SYS_DIGVOL_GROUP_EN
|
||
|
||
#if AUDUO_DEC_TONE_HIGH_BASS_ENABLE
|
||
if (dec->cur_list->stream_handler == NULL) {
|
||
dec->high_bass = high_bass_eq_open(file_dec->dec->sample_rate, file_dec->dec->out_ch_num);
|
||
dec->hb_drc = high_bass_drc_open(file_dec->dec->sample_rate, file_dec->dec->out_ch_num);
|
||
if (dec->hb_drc) {
|
||
dec->hb_convert = convet_data_open(0, 512);
|
||
}
|
||
if (dec->high_bass) { //高低音
|
||
(entries_hdl->entries_addr)[entries_hdl->entries_cnt++] = &dec->high_bass->entry;
|
||
}
|
||
if (dec->hb_drc) { //高低音后drc
|
||
(entries_hdl->entries_addr)[entries_hdl->entries_cnt++] = &dec->hb_drc->entry;
|
||
if (dec->hb_convert) {
|
||
(entries_hdl->entries_addr)[entries_hdl->entries_cnt++] = &dec->hb_convert->entry;
|
||
}
|
||
}
|
||
}
|
||
#endif
|
||
|
||
|
||
break;
|
||
case AUDIO_DEC_APP_EVENT_STREAM_CLOSE:
|
||
|
||
break;
|
||
|
||
default :
|
||
break;
|
||
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
/*----------------------------------------------------------------------------*/
|
||
/**@brief sine提示音解码回调
|
||
@param *priv: 私有句柄
|
||
@param event: 事件
|
||
@param *param: 事件参数
|
||
@return 0: 成功
|
||
@note
|
||
*/
|
||
/*----------------------------------------------------------------------------*/
|
||
AUDIO_DEC_TONE_AT_CODE_EVENT_CB
|
||
static int tone_dec_sine_app_evt_cb(void *priv, enum audio_dec_app_event event, int *param)
|
||
{
|
||
/* log_i("audio_dec_sine_app_evt_cb, priv:0x%x, event:%d \n", priv, event); */
|
||
struct audio_dec_sine_app_hdl *sine_dec = priv;
|
||
struct tone_dec_handle *dec = sine_dec->priv;
|
||
struct audio_dec_stream_entries_hdl *entries_hdl = (struct audio_dec_stream_entries_hdl *)param;
|
||
void *dvol_entry = NULL;
|
||
switch (event) {
|
||
case AUDIO_DEC_APP_EVENT_DEC_PROBE:
|
||
if (sine_dec->sin_maker) {
|
||
break;
|
||
}
|
||
audio_dec_sine_app_probe(sine_dec);
|
||
if (!sine_dec->sin_maker) {
|
||
return -ENOENT;
|
||
}
|
||
break;
|
||
case AUDIO_DEC_APP_EVENT_START_INIT_OK:
|
||
log_i("tone_sine start init ok\n");
|
||
if (dec->cur_list->stream_handler) {
|
||
// 删除原有的数据流,需要在回调中重新设置
|
||
if (sine_dec->dec->stream) {
|
||
audio_stream_del_entry(&sine_dec->dec->mix_ch.entry);
|
||
audio_stream_del_entry(&sine_dec->dec->decoder.entry);
|
||
audio_stream_close(sine_dec->dec->stream);
|
||
sine_dec->dec->stream = NULL;
|
||
}
|
||
dec->cur_list->stream_handler(dec->cur_list->stream_priv, event, sine_dec->dec);
|
||
}
|
||
clock_add_set(DEC_TONE_CLK);
|
||
audio_dec_sine_app_init_ok(sine_dec);
|
||
break;
|
||
case AUDIO_DEC_APP_EVENT_DEC_CLOSE:
|
||
if (!audio_dec_app_mix_en) {
|
||
tone_dec_stream_run_stop(sine_dec->dec);
|
||
}
|
||
if (dec->cur_list->stream_handler) {
|
||
dec->cur_list->stream_handler(dec->cur_list->stream_priv, event, sine_dec->dec);
|
||
}
|
||
#if SYS_DIGVOL_GROUP_EN
|
||
if (dec->cur_list->stream_handler == NULL) {
|
||
sys_digvol_group_ch_close("tone_tone");
|
||
}
|
||
#endif // SYS_DIGVOL_GROUP_EN
|
||
|
||
#if AUDUO_DEC_TONE_HIGH_BASS_ENABLE
|
||
high_bass_eq_close(dec->high_bass);
|
||
dec->high_bass = NULL;
|
||
high_bass_drc_close(dec->hb_drc);
|
||
dec->hb_drc = NULL;
|
||
convet_data_close(dec->hb_convert);
|
||
dec->hb_convert = NULL;
|
||
#endif
|
||
|
||
break;
|
||
case AUDIO_DEC_APP_EVENT_START_OK:
|
||
dec->cur_list->dec_ok_cnt++;
|
||
break;
|
||
case AUDIO_DEC_APP_EVENT_START_ERR:
|
||
log_i("tone_file start err\n");
|
||
case AUDIO_DEC_APP_EVENT_PLAY_END:
|
||
log_i("tone_sine play end\n");
|
||
/* audio_dec_sine_app_play_end(sine_dec); */
|
||
tone_dec_end_ctrl(dec);
|
||
break;
|
||
case AUDIO_DEC_APP_EVENT_STREAM_OPEN:
|
||
|
||
#if SYS_DIGVOL_GROUP_EN
|
||
|
||
audio_dig_vol_param temp_digvol_param = {
|
||
.vol_start = get_max_sys_vol(),
|
||
.vol_max = get_max_sys_vol(),
|
||
.ch_total = 2,
|
||
.fade_en = 0, //提示音不能淡入淡出
|
||
.fade_points_step = 5,
|
||
.fade_gain_step = 10,
|
||
.vol_list = NULL,
|
||
};
|
||
|
||
if (dec->cur_list->stream_handler == NULL) {
|
||
dvol_entry = sys_digvol_group_ch_open("tone_tone", -1, &temp_digvol_param);
|
||
(entries_hdl->entries_addr)[entries_hdl->entries_cnt++] = dvol_entry;
|
||
}
|
||
#endif // SYS_DIGVOL_GROUP_EN
|
||
|
||
#if AUDUO_DEC_TONE_HIGH_BASS_ENABLE
|
||
if (dec->cur_list->stream_handler == NULL) {
|
||
dec->high_bass = high_bass_eq_open(sine_dec->dec->sample_rate, sine_dec->dec->out_ch_num);
|
||
dec->hb_drc = high_bass_drc_open(sine_dec->dec->sample_rate, sine_dec->dec->out_ch_num);
|
||
if (dec->hb_drc && dec->hb_drc->run32bit) {
|
||
dec->hb_convert = convet_data_open(0, 512);
|
||
}
|
||
if (dec->high_bass) { //高低音
|
||
(entries_hdl->entries_addr)[entries_hdl->entries_cnt++] = &dec->high_bass->entry;
|
||
}
|
||
if (dec->hb_drc) { //高低音后drc
|
||
(entries_hdl->entries_addr)[entries_hdl->entries_cnt++] = &dec->hb_drc->entry;
|
||
if (dec->hb_convert) {
|
||
(entries_hdl->entries_addr)[entries_hdl->entries_cnt++] = &dec->hb_convert->entry;
|
||
}
|
||
}
|
||
}
|
||
#endif
|
||
break;
|
||
|
||
default :
|
||
break;
|
||
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
static void _tone_dec_app_comm_deal(struct audio_dec_app_hdl *dec, struct tone_dec_handle *tone)
|
||
{
|
||
dec->sync_confirm_time = tone->cur_list->sync_confirm_time;
|
||
if (dec->dec_type == AUDIO_CODING_SBC) {
|
||
audio_dec_app_set_frame_info(dec, 0x4e, dec->dec_type);
|
||
}
|
||
#if AUDIO_DEC_TONE_WAIT_USE_PRIO
|
||
if (dec->dec_mix == 0) {
|
||
dec->wait.priority = 3;
|
||
dec->wait.preemption = 0;
|
||
dec->wait.snatch_same_prio = 1;
|
||
}
|
||
#endif
|
||
}
|
||
|
||
/*----------------------------------------------------------------------------*/
|
||
/**@brief 提示音list播放
|
||
@param *dec: 句柄
|
||
@param next: 播放下一个
|
||
@return true: 成功
|
||
@return false: 成功
|
||
@note
|
||
*/
|
||
/*----------------------------------------------------------------------------*/
|
||
static int tone_dec_list_play(struct tone_dec_handle *dec, u8 next)
|
||
{
|
||
struct tone_dec_list_handle *dec_list = dec->cur_list;
|
||
if (!dec_list) {
|
||
return false;
|
||
}
|
||
#if TONE_DEC_PROTECT_LIST_PLAY
|
||
tone_dec_list_protect_deal(dec_list);
|
||
#endif
|
||
|
||
tone_dec_hdl_release(dec);
|
||
|
||
if (next) {
|
||
dec_list->idx++;
|
||
}
|
||
if (IS_REPEAT_END(dec_list->file_list[dec_list->idx])) {
|
||
//log_i("repeat_loop:%d",dec_list->loop);
|
||
if (!dec_list->dec_ok_cnt) {
|
||
log_i("repeat dec err \n");
|
||
return false;
|
||
}
|
||
if (dec_list->loop) {
|
||
dec_list->loop--;
|
||
dec_list->idx = dec_list->repeat_begin;
|
||
} else {
|
||
dec_list->idx++;
|
||
if (!dec_list->file_list[dec_list->idx]) {
|
||
log_i("repeat end 2:idx end");
|
||
return false;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (IS_REPEAT_BEGIN(dec_list->file_list[dec_list->idx])) {
|
||
if (dec_list->loop == 0) {
|
||
dec_list->loop = TONE_REPEAT_COUNT(dec_list->file_list[dec_list->idx]);
|
||
log_i("repeat begin:%d", dec_list->loop);
|
||
}
|
||
dec_list->idx++;
|
||
dec_list->repeat_begin = dec_list->idx;
|
||
dec_list->dec_ok_cnt = 0;
|
||
}
|
||
|
||
if (dec_list->file_list[dec_list->idx] == NULL) {
|
||
return false;
|
||
}
|
||
|
||
if (IS_DEFAULT_SINE(dec_list->file_list[dec_list->idx])) {
|
||
// is sine idx
|
||
if (dec->get_sine == NULL) {
|
||
log_e("get_sine is NULL ");
|
||
return false;
|
||
}
|
||
u8 num = 0;
|
||
struct sin_param *sin = dec->get_sine(DEFAULT_SINE_ID(dec_list->file_list[dec_list->idx]), &num);
|
||
if (!sin) {
|
||
log_e("sine is NULL ");
|
||
return false;
|
||
}
|
||
dec->dec_sin = audio_dec_sine_app_create_by_parm(sin, num, !dec_list->preemption);
|
||
if (dec->dec_sin == NULL) {
|
||
return false;
|
||
}
|
||
_tone_dec_app_comm_deal(dec->dec_sin->dec, dec);
|
||
dec->dec_sin->dec->evt_cb = tone_dec_sine_app_evt_cb;
|
||
dec->dec_sin->priv = dec;
|
||
audio_dec_sine_app_open(dec->dec_sin);
|
||
return true;
|
||
}
|
||
u8 file_name[16];
|
||
char *format = NULL;
|
||
FILE *file = fopen(dec_list->file_list[dec_list->idx], "r");
|
||
if (!file) {
|
||
return false;
|
||
}
|
||
fget_name(file, file_name, 16);
|
||
format = get_file_ext_name((char *)file_name);
|
||
fclose(file);
|
||
if (ASCII_StrCmpNoCase(format, "sin", 3) == 0) {
|
||
// is sine file
|
||
dec->dec_sin = audio_dec_sine_app_create(dec_list->file_list[dec_list->idx], !dec_list->preemption);
|
||
if (dec->dec_sin == NULL) {
|
||
return false;
|
||
}
|
||
_tone_dec_app_comm_deal(dec->dec_sin->dec, dec);
|
||
dec->dec_sin->dec->evt_cb = tone_dec_sine_app_evt_cb;
|
||
dec->dec_sin->priv = dec;
|
||
audio_dec_sine_app_open(dec->dec_sin);
|
||
return true;
|
||
}
|
||
|
||
// is file
|
||
dec->dec_file = audio_dec_file_app_create(dec_list->file_list[dec_list->idx], !dec_list->preemption);
|
||
if (dec->dec_file == NULL) {
|
||
return false;
|
||
}
|
||
_tone_dec_app_comm_deal(dec->dec_file->dec, dec);
|
||
dec->dec_file->dec->evt_cb = tone_dec_file_app_evt_cb;
|
||
dec->dec_file->priv = dec;
|
||
audio_dec_file_app_open(dec->dec_file);
|
||
return true;
|
||
}
|
||
|
||
|
||
/*----------------------------------------------------------------------------*/
|
||
/**@brief 创建提示音播放list句柄
|
||
@param *dec: 提示音句柄
|
||
@param **file_list: 文件名
|
||
@param preemption: 打断标记
|
||
@param *evt_handler: 事件回调接口
|
||
@param *evt_priv: 事件回调私有句柄
|
||
@param *stream_handler: tone数据流设置回调
|
||
@param *stream_priv: tone数据流设置回调私有句柄
|
||
@return list句柄
|
||
@note
|
||
*/
|
||
/*----------------------------------------------------------------------------*/
|
||
struct tone_dec_list_handle *tone_dec_list_create(struct tone_dec_handle *dec,
|
||
const char **file_list,
|
||
u8 preemption,
|
||
void (*evt_handler)(void *priv, int flag),
|
||
void *evt_priv,
|
||
void (*stream_handler)(void *priv, int event, struct audio_dec_app_hdl *app_dec),
|
||
void *stream_priv)
|
||
{
|
||
if (!dec || !file_list) {
|
||
return NULL;
|
||
}
|
||
struct tone_dec_list_handle *dec_list = zalloc(sizeof(struct tone_dec_list_handle));
|
||
if (!dec_list) {
|
||
return NULL;
|
||
}
|
||
|
||
int i = 0;
|
||
while (file_list[i] != NULL) {
|
||
i++;
|
||
}
|
||
dec_list->file_list = malloc(4 * (i + 1));
|
||
if (!dec_list->file_list) {
|
||
free(dec_list);
|
||
return NULL;
|
||
}
|
||
memcpy(dec_list->file_list, file_list, 4 * (i + 1));
|
||
dec_list->preemption = preemption;
|
||
dec_list->evt_handler = evt_handler;
|
||
dec_list->evt_priv = evt_priv;
|
||
dec_list->evt_owner = os_current_task();
|
||
dec_list->stream_handler = stream_handler;
|
||
dec_list->stream_priv = stream_priv;
|
||
return dec_list;
|
||
}
|
||
|
||
/*----------------------------------------------------------------------------*/
|
||
/**@brief 提示音list开始播放
|
||
@param *dec: 提示音句柄
|
||
@param *dec_list: list句柄
|
||
@return true: 成功
|
||
@return false: 成功
|
||
@note 当前没有播放,马上开始播放。当前有播放,挂载到链表后面等待播放
|
||
*/
|
||
/*----------------------------------------------------------------------------*/
|
||
int tone_dec_list_add_play(struct tone_dec_handle *dec, struct tone_dec_list_handle *dec_list)
|
||
{
|
||
int ret = false;
|
||
if (!dec || !dec_list) {
|
||
return false;
|
||
}
|
||
|
||
os_mutex_pend(&dec->mutex, 0);
|
||
|
||
list_add_tail(&dec_list->list_entry, &dec->head);
|
||
|
||
if (dec->cur_list == NULL) {
|
||
// 当前没有播放,开始播放
|
||
dec->cur_list = dec_list;
|
||
ret = tone_dec_list_play(dec, 0);
|
||
} else {
|
||
// 当前有播放,等播放完自动播放
|
||
ret = true;
|
||
}
|
||
|
||
os_mutex_post(&dec->mutex);
|
||
|
||
return ret;
|
||
}
|
||
|
||
|
||
/*----------------------------------------------------------------------------*/
|
||
/**@brief 提示音播放停止
|
||
@param **ppdec: 提示音句柄
|
||
@param push_event: 普通提示音是否推送消息
|
||
@param end_flag: 结束类型
|
||
@return
|
||
@note
|
||
*/
|
||
/*----------------------------------------------------------------------------*/
|
||
void tone_dec_stop(struct tone_dec_handle **ppdec,
|
||
u8 push_event,
|
||
u8 end_flag)
|
||
{
|
||
if (!ppdec || !*ppdec) {
|
||
return ;
|
||
}
|
||
struct tone_dec_handle *dec = *ppdec;
|
||
struct tone_dec_list_handle *p, *n;
|
||
|
||
os_mutex_pend(&dec->mutex, 0);
|
||
|
||
tone_dec_hdl_release(dec);
|
||
|
||
list_for_each_entry_safe(p, n, &dec->head, list_entry) {
|
||
tone_dec_list_release(p, push_event, end_flag);
|
||
}
|
||
|
||
os_mutex_post(&dec->mutex);
|
||
|
||
free(dec);
|
||
|
||
*ppdec = NULL;
|
||
}
|
||
|
||
|
||
/*----------------------------------------------------------------------------*/
|
||
/**@brief 指定提示音播放停止
|
||
@param **ppdec: 提示音句柄
|
||
@param push_event: 普通提示音是否推送消息
|
||
@param end_flag: 结束类型
|
||
@return
|
||
@note 如果该提示音正在播,停止播放并且播放下一个。如果不在播放,只从链表中删除
|
||
*/
|
||
/*----------------------------------------------------------------------------*/
|
||
void tone_dec_stop_spec_file(struct tone_dec_handle **ppdec,
|
||
char *file_name,
|
||
u8 push_event,
|
||
u8 end_flag)
|
||
{
|
||
if (!ppdec || !*ppdec || !file_name) {
|
||
return ;
|
||
}
|
||
struct tone_dec_handle *dec = *ppdec;
|
||
struct tone_dec_list_handle *p, *n;
|
||
|
||
os_mutex_pend(&dec->mutex, 0);
|
||
if (dec->cur_list) {
|
||
do {
|
||
if (IS_DEFAULT_SINE(file_name)) {
|
||
if (dec->cur_list->file_list[0] != file_name) {
|
||
break;
|
||
}
|
||
} else if (IS_DEFAULT_SINE(dec->cur_list->file_list[0])) {
|
||
break;
|
||
} else if (strcmp(dec->cur_list->file_list[0], file_name)) {
|
||
break;
|
||
}
|
||
// 当前正在播放,停止播放
|
||
tone_dec_hdl_release(dec);
|
||
tone_dec_list_release(dec->cur_list, push_event, end_flag);
|
||
dec->cur_list = NULL;
|
||
// 检查链表播放
|
||
struct list_head *list_entry = dec->head.next;
|
||
if (list_entry && (list_entry != &dec->head)) {
|
||
// 如果还有,则继续播放
|
||
struct tone_dec_list_handle *dec_list = container_of(list_entry, struct tone_dec_list_handle, list_entry);
|
||
dec->cur_list = dec_list;
|
||
tone_dec_list_play(dec, 0);
|
||
os_mutex_post(&dec->mutex);
|
||
} else {
|
||
// 如果没有,释放
|
||
os_mutex_post(&dec->mutex);
|
||
free(dec);
|
||
*ppdec = NULL;
|
||
}
|
||
return ;
|
||
} while (0);
|
||
}
|
||
|
||
// 从链表中删除,不停止解码
|
||
list_for_each_entry_safe(p, n, &dec->head, list_entry) {
|
||
do {
|
||
if (IS_DEFAULT_SINE(file_name)) {
|
||
if (dec->cur_list->file_list[0] != file_name) {
|
||
break;
|
||
}
|
||
} else if (IS_DEFAULT_SINE(dec->cur_list->file_list[0])) {
|
||
break;
|
||
} else if (strcmp(dec->cur_list->file_list[0], file_name)) {
|
||
break;
|
||
}
|
||
tone_dec_list_release(p, push_event, end_flag);
|
||
os_mutex_post(&dec->mutex);
|
||
return ;
|
||
} while (0);
|
||
}
|
||
|
||
os_mutex_post(&dec->mutex);
|
||
}
|
||
|
||
|
||
#if 0
|
||
static struct tone_dec_handle *test_tone_dec = NULL;
|
||
static struct audio_eq_drc *test_tone_eq_drc = NULL;
|
||
|
||
extern void *file_eq_drc_open(u16 sample_rate, u8 ch_num);
|
||
extern void file_eq_drc_close(struct audio_eq_drc *eq_drc);
|
||
|
||
static void tone_test_stream_resume(void *p)
|
||
{
|
||
struct audio_dec_app_hdl *app_dec = p;
|
||
audio_decoder_resume(&app_dec->decoder);
|
||
}
|
||
|
||
static void tone_test_stream_handler(void *priv, int event, struct audio_dec_app_hdl *app_dec)
|
||
{
|
||
switch (event) {
|
||
case AUDIO_DEC_APP_EVENT_START_INIT_OK:
|
||
y_printf("AUDIO_DEC_APP_EVENT_START_INIT_OK \n");
|
||
struct audio_stream_entry *entries[8] = {NULL};
|
||
u8 entry_cnt = 0;
|
||
entries[entry_cnt++] = &app_dec->decoder.entry;
|
||
{
|
||
// add eq
|
||
test_tone_eq_drc = file_eq_drc_open(app_dec->sample_rate, app_dec->ch_num);
|
||
entries[entry_cnt++] = &test_tone_eq_drc->entry;
|
||
}
|
||
entries[entry_cnt++] = &app_dec->mix_ch.entry;
|
||
app_dec->stream = audio_stream_open(app_dec, tone_test_stream_resume);
|
||
audio_stream_add_list(app_dec->stream, entries, entry_cnt);
|
||
break;
|
||
case AUDIO_DEC_APP_EVENT_DEC_CLOSE:
|
||
y_printf("AUDIO_DEC_APP_EVENT_DEC_CLOSE \n");
|
||
{
|
||
// del eq
|
||
if (test_tone_eq_drc) {
|
||
file_eq_drc_close(test_tone_eq_drc);
|
||
test_tone_eq_drc = NULL;
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
|
||
static void tone_test_play_close(void)
|
||
{
|
||
tone_dec_stop(&test_tone_dec, 0, 0);
|
||
}
|
||
|
||
void tone_test_play(void)
|
||
{
|
||
tone_test_play_close();
|
||
test_tone_dec = tone_dec_create();
|
||
static char *single_file[2] = {NULL};
|
||
single_file[0] = (char *)TONE_POWER_OFF;
|
||
single_file[1] = NULL;
|
||
struct tone_dec_list_handle *dec_list = tone_dec_list_create(test_tone_dec, single_file, 1, NULL, NULL, tone_test_stream_handler, NULL);
|
||
tone_dec_list_add_play(test_tone_dec, dec_list);
|
||
}
|
||
#endif
|
||
|
||
|