KT24-1110_65E-HA-651B/apps/common/audio/decode/audio_key_tone.c
2024-11-10 18:44:17 +08:00

683 lines
20 KiB
C
Raw 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 "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