杰理SDK开发-TWS配对提示音修改和播放教程(提示音教程) 前言现在为止也开发了许多杰理TWS蓝牙耳机、音响项目 SDK的案子在调试案子时不断的向前辈们学习到了很多关于蓝牙音响、蓝牙TWS耳机专业的知识。想在这里做一个学习汇总方便各位同行和对杰理芯片可视化 SDK感兴趣的小伙伴们学习本章详细讲解杰理SDK开发TWS配对提示音修改和播放教程TWS配对提示音是对箱或TWS蓝牙耳机主机和副机开机之后顺利配对成功后播放的提示音。方便用户更好的感知TWS配对成功的状态。一般要求都是同步播放。不能一个先播一个后播。今天就遇到了一个客户反映配置的TWS配对提示音播放不同步。本章就详细分析讲解一些杰理SDK中关于TWS配对提示音的修改和播放教程。也正好顺带给大家讲解杰理SDK中提示音的播放和修改。提示音修改步骤1首先打开 tone_player.h 文件观察宏定义#define TONE_TWS_CONN发现有两个这样的宏定义可以发现有一个#define TONE_TWS_TONE后面跟随着tone的文件名。这样要注意需要保持修改的TWS配对提示音的文件名要和图片中的代码相对应。如果不对应要么更改文件名使其对应上代码中的定义要不就修改代码中的定义使其对应上文件名。必须要对应还可以发现还有一个#undef TONE_TWS_TONE。这是指取消/删除之前的宏定义重新定义#define TONE_TWS_TONE第一个宏定义是我们配置工具配置音频文件的TWS配对提示音第二个宏定义是SDK正弦波默认生成的TWS配对提示音代码学习预处理器指令#define和#undef特性#define#undef作用定义宏取消宏语法#define 名称 文本#undef 名称效果从此处起生效从此处起失效是否报错重复定义会警告取消未定义的宏不报错可以观察到代码中先是定义了#define TONE_TWS_CONN SDFILE_RES_ROOT_PATHtone/tws_conn.*紧接着判断默认正弦波提示音功能CONFIG_USE_DEFAULT_SINE是否打开如打开了则CONFIG_USE_DEFAULT_SINE上方部分提示音文件将被#undef预处理器指令取消之前的宏定义重新使用SIN正弦波提示音定义。所以在这里小伙伴们在往后的开发中遇到了提示音明明已在配置工具中配置但是提示音不对的情况下往往是被正弦波提示音功能干扰了。在这里有两种解决方法。解决方法1要不直接在 tone_player_api.h 文件中将CONFIG_USE_DEFAULT_SINE置零关闭j功能。解决方法2要不对不想受影响的提示音直接注释掉。本章我们需要自定义TWS配对提示音所以当个例子参考如图所示方法1方法2步骤2打开杰理SDK文件夹中的配置工具如图所示进行TWS配对提示音文件的修改如下图所示注意配置工具中添加和修改的提示音文件一定要和代码中定义的文件名保持一致。要不然修改和添加是无效的。同步播放TWS配对提示音在代码中的流程TWS配对提示音的播放是在SDK代码中的 bt_tws.c 文件中的bt_tws_connction_status_event_handler(struct bt_event *evt)tws事件状态处理函数中的TWS_EVENT_CONNECTEDtws连接事件中播放如图所示函数代码追踪一下可以发现bt_tws_play_tone_at_same_time(SYNC_TONE_TWS_CONNECTED, 400);TWS配对提示音同步播放本质上还是使用了TWS主从同步调用相同函数接口实现的。这也在以后的项目开发中也可以仿照写法实现一些自定义提示音的播放提示音同步播放核心函数/* * 提示音同步播放 * tone_name: 提示音类型(SYNC_TONE_xxx) * err: 错误码-TWS_SYNC_CALL_RX表示从机调用 */ static void play_tone_at_same_time(int tone_name, int err) { STATUS *p_tone get_tone_config(); // 获取提示音配置表 switch (tone_name) { #if TCFG_EAR_DETECT_ENABLE case SYNC_TONE_EARDET_IN: // 耳机佩戴检测提示音 tone_play(TONE_EAR_CHECK, 1); // 播放检测音允许抢占 break; #endif case SYNC_TONE_TWS_CONNECTED: // TWS左右耳连接成功提示音 #if TCFG_DEC2TWS_ENABLE break; // DEC2TWS模式不播放 #endif tone_play_index(p_tone-tws_connect_ok, 1); // 播放TWS连接音 break; case SYNC_TONE_PHONE_CONNECTED: // 手机蓝牙连接成功提示音 if (err ! -TWS_SYNC_CALL_RX) { // 从机调用时不播放避免重复 tone_play_index(p_tone-bt_connect_ok, 1); } break; case SYNC_TONE_PHONE_DISCONNECTED: // 手机蓝牙断开提示音 if (!app_var.goto_poweroff_flag) { // 关机时不播放 tone_play_index(p_tone-bt_disconnect, 1); } ui_update_status(STATUS_BT_TWS_CONN); // 更新UI状态 break; case SYNC_TONE_MAX_VOL: // 音量最大提示音 #if TCFG_MAX_VOL_PROMPT if (p_tone-max_vol ! IDEX_TONE_NONE) { // 检查是否配置了提示音 tone_play_index(p_tone-max_vol, 0); // preemption0不允许抢占 } #endif break; case SYNC_TONE_POWER_OFF: // 关机提示音 y_printf(SYNC_TONE_POWER_OFF\n); tone_play_index(p_tone-power_off, 0); // 关机音不允许被抢占 break; case SYNC_TONE_PHONE_NUM: // 来电号码显示提示音 if (bt_user_priv_var.phone_con_sync_num_ring) { // 从机正在同步号码铃声不播放 break; } if (tws_api_get_role() TWS_ROLE_SLAVE) { // 从机清除旧定时器 if (bt_user_priv_var.phone_timer_id) { sys_timeout_del(bt_user_priv_var.phone_timer_id); bt_user_priv_var.phone_timer_id 0; } } if (bt_user_priv_var.phone_ring_flag) { // 正在响铃则启动号码播放 phone_num_play_timer(NULL); } break; case SYNC_TONE_PHONE_RING: // 来电铃声同步 if (bt_user_priv_var.phone_ring_flag) { if (bt_user_priv_var.phone_con_sync_ring) { // 从机刚加入来电过程 if (phone_ring_play_start()) { bt_user_priv_var.phone_con_sync_ring 0; if (tws_api_get_role() TWS_ROLE_MASTER) { // 主机播完一声后关闭AEC/MSBC解码避免铃声被误判消除 } } } else { phone_ring_play_start(); // 正常流程直接播放 } } break; case SYNC_TONE_PHONE_NUM_RING: // 来电号码铃声同步 if (bt_user_priv_var.phone_ring_flag) { if (phone_ring_play_start()) { if (tws_api_get_role() TWS_ROLE_MASTER) { // 主机播完一声后关闭AEC准备播下一声循环播放 } bt_user_priv_var.phone_con_sync_num_ring 1; // 设置标志下一声走PHONE_RING逻辑 } } break; #if TCFG_AUDIO_ANC_ENABLE case SYNC_TONE_ANC_ON: // ANC开启提示音 case SYNC_TONE_ANC_OFF: // ANC关闭提示音 case SYNC_TONE_ANC_TRANS: // 通透模式提示音 anc_tone_sync_play(tone_name); // 调用ANC专用同步播放函数 break; #endif } }同步调用注册机制// 定义同步调用结构体 struct tws_sync_call { int uuid; // 唯一标识符命令ID void (*func)(int priv, int err); // 要执行的函数指针 const char *task_name; // 任务名称 }; // 宏定义注册同步调用 TWS_SYNC_CALL_REGISTER(tws_tone_play) { .uuid 0x123A9E50, // 提示音同步的唯一ID .task_name app_core, // 在app_core任务中执行 .func play_tone_at_same_time, // 实际播放函数 };触发提示音同步播放函数/* * 外部接口触发提示音同步播放 * tone_name: 提示音类型 * msec: 超时时间等待从机确认的最大时间 */ void bt_tws_play_tone_at_same_time(int tone_name, int msec) { tws_api_sync_call_by_uuid(0x123A9E50, tone_name, msec); // 发送同步命令到从机 }制作不易喜欢的小伙伴给个小赞赞喜欢我的小伙伴点个关注有不懂的地方和需要的资源随时问我哟