KT24-1110_65E-HA-651B/cpu/br25/audio_dec/audio_dec_tone.c

918 lines
29 KiB
C
Raw Normal View History

2024-11-10 10:44:17 +00:00
#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