KT24-1110_65E-HA-651B/apps/common/audio/decode/audio_key_tone.c

683 lines
20 KiB
C
Raw Normal View History

2024-11-10 10:44:17 +00:00
#include "asm/includes.h"
#include "media/includes.h"
#include "system/includes.h"
#include "app_config.h"
#include "audio_config.h"
#include "audio_dec.h"
#include "tone_player.h"
#include "sine_make.h"
#if TCFG_KEY_TONE_EN
// 按键提示音任务名
#define AUDIO_KEY_TONE_TASK_NAME "key_tone"
// 按键提示音数字音量控制
#if SYS_DIGVOL_GROUP_EN
#define AUDIO_KEY_TONE_DIGVOL_EN 0
#define AUDIO_KEY_TONE_DIGVOL_NAME "key_tone"
#else
#define AUDIO_KEY_TONE_DIGVOL_EN 0
#endif
//////////////////////////////////////////////////////////////////////////////
/*
* 使audio_dec_app.h里面的接口
*/
// 参数
struct __key_tone_play_info {
const char *file_name; // 文件名
struct audio_sin_param *sin; // 正弦波数组
u8 sin_num; // 正弦波数组长度
u8 preemption; // 1-抢占0-叠加
void (*evt_handler)(void *priv, int flag); // 事件回调
void *evt_priv; // 事件回调私有句柄
};
// 按键提示音
struct __key_tone {
volatile u8 busy; // 任务工作中
volatile u8 start; // 运行标志
volatile u8 play;
#if AUDIO_KEY_TONE_DIGVOL_EN
u8 volume; // 音量
#endif
struct __key_tone_play_info play_info; // 输入参数
struct audio_dec_sine_app_hdl *dec_sin; // 文件播放句柄
struct audio_dec_file_app_hdl *dec_file; // sine播放句柄
void (*evt_handler)(void *priv, int flag); // 事件回调
void *evt_priv; // 事件回调私有句柄
const char *evt_owner; // 事件回调所在任务
};
//////////////////////////////////////////////////////////////////////////////
static struct __key_tone *key_tone = NULL;
//////////////////////////////////////////////////////////////////////////////
/*
*********************************************************************
* Audio Key Tone Get File Ext Name
* Description:
* Arguments : *name
* Return :
* Note(s) : None.
*********************************************************************
*/
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;
}
/*
*********************************************************************
* Audio Key Tone Post Event
* Description:
* Arguments : *ktone
* end_flag
* Return : true
* Note(s) : None.
*********************************************************************
*/
static int key_tone_dec_event_handler(struct __key_tone *ktone, u8 end_flag)
{
int argv[4];
if (!ktone->evt_handler) {
log_i("evt_handler null\n");
return false;
}
argv[0] = (int)ktone->evt_handler;
argv[1] = 2;
argv[2] = (int)ktone->evt_priv;
argv[3] = (int)end_flag; //0正常关闭1被打断关闭
int ret = os_taskq_post_type(ktone->evt_owner, Q_CALLBACK, 4, argv);
if (ret) {
return false;
}
return true;
}
/*
*********************************************************************
* Audio Key Tone Reelease
* Description:
* Arguments : *ktone
* Return : None.
* Note(s) : None.
*********************************************************************
*/
static void key_tone_dec_hdl_release(struct __key_tone *ktone)
{
if (ktone->dec_file) {
audio_dec_file_app_close(ktone->dec_file);
ktone->dec_file = NULL;
}
if (ktone->dec_sin) {
audio_dec_sine_app_close(ktone->dec_sin);
ktone->dec_sin = NULL;
}
/* app_audio_state_exit(APP_AUDIO_STATE_WTONE); */
/* clock_remove_set(DEC_TONE_CLK); */
}
/*
*********************************************************************
* Audio Key Tone Init OK
* Description:
* Arguments : *ktone
* Return : None.
* Note(s) : None.
*********************************************************************
*/
static void key_tone_dec_hdl_init_ok(struct __key_tone *ktone)
{
/* app_audio_state_switch(APP_AUDIO_STATE_WTONE, get_tone_vol()); */
/* clock_add_set(DEC_TONE_CLK); */
}
/*
*********************************************************************
* Audio Key Tone Close
* Description:
* Arguments : *ktone
* Return : None.
* Note(s) : None.
*********************************************************************
*/
static void key_tone_play_close(struct __key_tone *ktone)
{
/* log_i("ktone:0x%x, sin:0x%x, file:0x%x \n", ktone, ktone->dec_file, ktone->dec_file); */
if (ktone->dec_file || ktone->dec_sin) {
key_tone_dec_hdl_release(ktone);
key_tone_dec_event_handler(ktone, 1);
}
}
/*
*********************************************************************
* Audio Key Tone Event Callback
* Description:
* Arguments : *ktone
* event
* *param
* Return : 0
* Note(s) : None.
*********************************************************************
*/
static int key_tone_dec_app_evt_cb(struct __key_tone *ktone, enum audio_dec_app_event event, int *param)
{
switch (event) {
case AUDIO_DEC_APP_EVENT_START_INIT_OK:
log_i("key_tone start init ok\n");
key_tone_dec_hdl_init_ok(ktone);
break;
case AUDIO_DEC_APP_EVENT_PLAY_END:
log_i("key_tone play end\n");
key_tone_dec_hdl_release(ktone);
key_tone_dec_event_handler(ktone, 0);
break;
case AUDIO_DEC_APP_EVENT_STREAM_OPEN: {
#if AUDIO_KEY_TONE_DIGVOL_EN
struct audio_dec_stream_entries_hdl *entries_hdl = (struct audio_dec_stream_entries_hdl *)param;
void *dvol_entry = NULL;
audio_dig_vol_param temp_digvol_param = {
.vol_start = ktone->volume,//get_max_sys_vol(),
.vol_max = get_max_sys_vol(),
.ch_total = audio_output_channel_num(),
.fade_en = 0,
.fade_points_step = 5,
.fade_gain_step = 10,
.vol_list = NULL,
};
dvol_entry = sys_digvol_group_ch_open(AUDIO_KEY_TONE_DIGVOL_NAME, -1, &temp_digvol_param);
(entries_hdl->entries_addr)[entries_hdl->entries_cnt++] = dvol_entry;
#endif // SYS_DIGVOL_GROUP_EN
}
break;
case AUDIO_DEC_APP_EVENT_DEC_CLOSE:
#if AUDIO_KEY_TONE_DIGVOL_EN
sys_digvol_group_ch_close(AUDIO_KEY_TONE_DIGVOL_NAME);
#endif // SYS_DIGVOL_GROUP_EN
break;
case AUDIO_DEC_APP_EVENT_STREAM_CLOSE: {
}
break;
default :
break;
}
return 0;
}
/*
*********************************************************************
* Audio Key Tone Sin Event Callback
* Description: sine提示音解码回调
* Arguments : *priv
* event
* *param
* Return : 0
* Note(s) : None.
*********************************************************************
*/
static int key_tone_dec_sine_app_evt_cb(void *priv, enum audio_dec_app_event event, int *param)
{
struct audio_dec_sine_app_hdl *sine_dec = priv;
struct __key_tone *ktone = sine_dec->priv;
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;
default :
return key_tone_dec_app_evt_cb(ktone, event, param);
}
return 0;
}
/*
*********************************************************************
* Audio Key Tone File Event Callback
* Description: file提示音解码回调
* Arguments : *priv
* event
* *param
* Return : 0
* Note(s) : None.
*********************************************************************
*/
static int key_tone_dec_file_app_evt_cb(void *priv, enum audio_dec_app_event event, int *param)
{
struct audio_dec_file_app_hdl *file_dec = priv;
struct __key_tone *ktone = file_dec->priv;
switch (event) {
case AUDIO_DEC_APP_EVENT_DEC_PROBE:
break;
default :
return key_tone_dec_app_evt_cb(ktone, event, param);
}
return 0;
}
/*
*********************************************************************
* Audio Key Tone Run
* Description:
* Arguments : *ktone
* Return : 0
* Note(s) : None.
*********************************************************************
*/
static int key_tone_play_run(struct __key_tone *ktone)
{
if (!ktone->start) {
return -1;
}
struct __key_tone_play_info info = {0};
local_irq_disable();
if (!ktone->play) {
local_irq_enable();
return 0;
}
// 保存播放参数
memcpy(&info, &ktone->play_info, sizeof(struct __key_tone_play_info));
ktone->play = 0;
local_irq_enable();
// 关闭现有play
key_tone_play_close(ktone);
// 设置参数
ktone->evt_handler = info.evt_handler;
ktone->evt_priv = info.evt_priv;
ktone->evt_owner = "app_core";
// 正弦波数组播放
if (info.sin && info.sin_num) {
ktone->dec_sin = audio_dec_sine_app_create_by_parm(info.sin, info.sin_num, !info.preemption);
if (ktone->dec_sin == NULL) {
return -1;
}
ktone->dec_sin->dec->evt_cb = key_tone_dec_sine_app_evt_cb;
ktone->dec_sin->priv = ktone;
audio_dec_sine_app_open(ktone->dec_sin);
return 0;
}
// 判断文件名后缀
u8 file_name[16];
char *format = NULL;
FILE *file = fopen(info.file_name, "r");
if (!file) {
return -1;
}
fget_name(file, file_name, 16);
format = get_file_ext_name((char *)file_name);
fclose(file);
// 正弦波文件播放
if (ASCII_StrCmpNoCase(format, "sin", 3) == 0) {
ktone->dec_sin = audio_dec_sine_app_create(info.file_name, !info.preemption);
if (ktone->dec_sin == NULL) {
return -1;
}
ktone->dec_sin->dec->evt_cb = key_tone_dec_sine_app_evt_cb;
ktone->dec_sin->priv = ktone;
audio_dec_sine_app_open(ktone->dec_sin);
return 0;
}
// 普通文件播放
ktone->dec_file = audio_dec_file_app_create(info.file_name, !info.preemption);
if (ktone->dec_file == NULL) {
return -1;
}
if (ktone->dec_file->dec->dec_type == AUDIO_CODING_SBC) {
audio_dec_app_set_frame_info(ktone->dec_file->dec, 0x4e, ktone->dec_file->dec->dec_type);
}
ktone->dec_file->dec->evt_cb = key_tone_dec_file_app_evt_cb;
ktone->dec_file->priv = ktone;
audio_dec_file_app_open(ktone->dec_file);
return 0;
}
/*
*********************************************************************
* Audio Key Tone Task Run
* Description:
* Arguments : *p
* Return : None.
* Note(s) : None.
*********************************************************************
*/
static void key_tone_task_deal(void *p)
{
int res = 0;
int msg[16];
struct __key_tone *ktone = (struct __key_tone *)p;
ktone->start = 1;
ktone->busy = 1;
while (1) {
__os_taskq_pend(msg, ARRAY_SIZE(msg), portMAX_DELAY);
res = key_tone_play_run(ktone);
if (res) {
///等待删除线程
key_tone_play_close(ktone);
ktone->busy = 0;
while (1) {
os_time_dly(10000);
}
}
}
}
/*
*********************************************************************
* Audio Key Tone Destroy
* Description:
* Arguments : None.
* Return : None.
* Note(s) : None.
*********************************************************************
*/
void audio_key_tone_destroy(void)
{
if (!key_tone) {
return ;
}
key_tone->start = 0;
while (key_tone->busy) {
os_taskq_post_msg(AUDIO_KEY_TONE_TASK_NAME, 1, 0);
os_time_dly(1);
}
task_kill(AUDIO_KEY_TONE_TASK_NAME);
local_irq_disable();
free(key_tone);
key_tone = NULL;
local_irq_enable();
}
/*
*********************************************************************
* Audio Key Tone Init
* Description:
* Arguments : None.
* Return : true
* Note(s) : None.
*********************************************************************
*/
int audio_key_tone_init(void)
{
int err = 0;
if (key_tone) {
return true;
}
struct __key_tone *ktone = zalloc(sizeof(struct __key_tone));
err = task_create(key_tone_task_deal, (void *)ktone, AUDIO_KEY_TONE_TASK_NAME);
if (err != OS_NO_ERR) {
log_e("%s creat fail %x\n", __FUNCTION__, err);
free(ktone);
return false;
}
#if AUDIO_KEY_TONE_DIGVOL_EN
ktone->volume = get_max_sys_vol();
#endif
key_tone = ktone;
return true;
}
//////////////////////////////////////////////////////////////////////////////
// 正弦波序号
#define KTONE_SINE_NORAML 0
// 按键提示音序号
enum {
KTONE_IDEX_NORAML = 0,
KTONE_IDEX_NUM_0,
KTONE_IDEX_NUM_1,
KTONE_IDEX_MAX,
};
// 序号对应表
static const char *const key_tone_index[] = {
[KTONE_IDEX_NORAML] = DEFAULT_SINE_TONE(KTONE_SINE_NORAML),
[KTONE_IDEX_NUM_0] = SDFILE_RES_ROOT_PATH"tone/0.*",
[KTONE_IDEX_NUM_1] = SDFILE_RES_ROOT_PATH"tone/1.*",
};
/*
* :
* freq : * 512
* points :
* win :
* decay : (), *512
*/
static const struct sin_param sine_16k_normal[] = {
/*{0, 1000, 0, 100},*/
{200 << 9, 4000, 0, 100},
};
//////////////////////////////////////////////////////////////////////////////
/*
*********************************************************************
* Audio Key Tone Get Sine Param Data
* Description:
* Arguments : id
* *num
* Return :
* Note(s) : None.
*********************************************************************
*/
static const struct sin_param *get_sine_param_data(u8 id, u8 *num)
{
const struct sin_param *param_data = NULL;
switch (id) {
case KTONE_SINE_NORAML:
param_data = sine_16k_normal;
*num = ARRAY_SIZE(sine_16k_normal);
break;
default:
return NULL;
}
return param_data;
};
/*
*********************************************************************
* Audio Key Tone Open With Callback
* Description:
* Arguments : *file_name
* *sin
* sin_num
* preemption 1-0-
* evt_handler
* evt_priv
* Return : 0
* Note(s) : None.
*********************************************************************
*/
static int ktone_play_open_with_callback_base(const char *file_name, struct audio_sin_param *sin, u8 sin_num, u8 preemption, void (*evt_handler)(void *priv, int flag), void *evt_priv)
{
struct __key_tone *ktone = key_tone;
if ((!ktone) || (!ktone->start)) {
return -1;
}
struct __key_tone_play_info info = {0};
info.preemption = preemption;
info.evt_handler = evt_handler;
info.evt_priv = evt_priv;
if (sin && sin_num) {
info.sin = sin;
info.sin_num = sin_num;
} else {
info.file_name = file_name;
if (IS_DEFAULT_SINE(file_name)) {
info.sin = get_sine_param_data(DEFAULT_SINE_ID(file_name), &info.sin_num);
}
}
local_irq_disable();
memcpy(&ktone->play_info, &info, sizeof(struct __key_tone_play_info));
ktone->play = 1;
local_irq_enable();
os_taskq_post_msg(AUDIO_KEY_TONE_TASK_NAME, 1, 0);
return 0;
}
/*
*********************************************************************
* Audio Key Tone Play Sine
* Description:
* Arguments : *sin
* sin_num
* preemption 1-0-
* Return : 0
* Note(s) : None.
*********************************************************************
*/
int audio_key_tone_play_sin(struct audio_sin_param *sin, u8 sin_num, u8 preemption)
{
/* y_printf("n:0x%x \n", name); */
return ktone_play_open_with_callback_base(NULL, sin, sin_num, preemption, NULL, NULL);
}
/*
*********************************************************************
* Audio Key Tone Play File
* Description:
* Arguments : *name
* preemption 1-0-
* Return : 0
* Note(s) : None.
*********************************************************************
*/
int audio_key_tone_play_name(const char *name, u8 preemption)
{
/* y_printf("n:0x%x \n", name); */
return ktone_play_open_with_callback_base(name, NULL, 0, preemption, NULL, NULL);
}
/*
*********************************************************************
* Audio Key Tone Play Index
* Description:
* Arguments : index
* preemption 1-0-
* Return : 0
* Note(s) : 使key_tone_index[]
*********************************************************************
*/
int audio_key_tone_play_index(u8 index, u8 preemption)
{
if (index >= KTONE_IDEX_MAX) {
return -1;
}
return audio_key_tone_play_name(key_tone_index[index], preemption);
}
/*
*********************************************************************
* Audio Key Tone Play
* Description:
* Arguments : None.
* Return : None.
* Note(s) :
*********************************************************************
*/
void audio_key_tone_play(void)
{
audio_key_tone_play_index(KTONE_IDEX_NORAML, 0);
/* audio_key_tone_play_index(KTONE_IDEX_NUM_0, 0); */
/* audio_key_tone_play_sin(sine_16k_normal, ARRAY_SIZE(sine_16k_normal), 0); */
}
/*
*********************************************************************
* Audio Key Tone Check Play
* Description:
* Arguments : None.
* Return : true
* Note(s) : None.
*********************************************************************
*/
int audio_key_tone_is_play(void)
{
if ((!key_tone) || (!key_tone->start)) {
return false;
}
if (key_tone->dec_file || key_tone->dec_sin) {
return true;
}
return false;
}
/*
*********************************************************************
* Audio Key Tone Set Digvol
* Description:
* Arguments : volume
* Return : None.
* Note(s) : None.
*********************************************************************
*/
void audio_key_tone_digvol_set(u8 volume)
{
#if AUDIO_KEY_TONE_DIGVOL_EN
log_i("vol:%d \n", volume);
if (!key_tone) {
return ;
}
key_tone->volume = volume;
void *vol_hdl = audio_dig_vol_group_hdl_get(sys_digvol_group, AUDIO_KEY_TONE_DIGVOL_NAME);
if (vol_hdl == NULL) {
return;
}
audio_dig_vol_set(vol_hdl, AUDIO_DIG_VOL_ALL_CH, volume);
#endif
}
#endif