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

918 lines
29 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 "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