当前位置: 首页 > news >正文

杰理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_PATH"tone/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); // preemption=0不允许抢占 } #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); // 发送同步命令到从机 }

制作不易!喜欢的小伙伴给个小赞赞!喜欢我的小伙伴点个关注!有不懂的地方和需要的资源随时问我哟!

http://www.gsyq.cn/news/1584788.html

相关文章:

  • 【读书笔记】《金钱心理学》完结篇:终极真相与作者亲授的可落地理财方案
  • 大模型评估基准大全:解析MMLU、GSM8K、HumanEval与BBH
  • ANR触发原理与监控机制:深入Android Framework的核心实战解析
  • 二叉搜索树【C++】
  • linux笔记6(软链接)
  • 车联网蓝牙测试:经典蓝牙数据抓包.(SSP配对模式)
  • 数字化赋能传统离散制造:智能化技术在高端石材工程领域的落地与深度优化
  • OpencvSharp 算子学习教案之 - Cv2.Circle 重载2
  • 【LangChain核心组件】文档加载器
  • CircleCI自动化_circleci-automation
  • 花5万买串口屏,总结出的7条血泪教训做储能设备的千万别再踩坑
  • 鸿蒙PC中使用ohos-sdk完成Rust适配,自动签名编译安装第三方库walkdir是 Rust 递归遍历目录的专用库
  • 一篇文章带你入门漏洞靶场:从 0 到 1 玩转 bWAPP(附完整安装教程)
  • 屏幕截图文字识别工具帮你屏幕截图取字
  • 5分钟搞定OpenCode Go套餐无缝接入Claude Code,性价比直接起飞!
  • 在MacOS上如何安装配置工时通
  • HoRain云--R循环实战:从语法到高效向量化技巧
  • 使用 Python 调用商品条形码查询API并解析商品信息
  • FAST-LIVO2 源码精读(九):VoxelMap 体素地图——哈希索引与八叉树平面拟合
  • 西瓜/甜瓜智能病虫害防控喷雾机上位机 Qt信创完整项目
  • 第31章:构建自定义Code Agent——打造专属的代码助手
  • Power BI 6 月重磅更新:9 大新功能全面提升数据分析效率
  • 【ComfyUI】在Windows电脑上安装 ComfyUI并通过python脚本调用API批量生成图片
  • window显示驱动开发-Direct3D 着色器代码
  • 计算机毕业设计之网络商城系统的设计与实现
  • TVA在机电产品视觉检测的创新应用(13)
  • 告别重复造轮子:C#抽象机器人控制层,兼容ABB/安川/发那科
  • Python之stubsplit包语法、参数和实际应用案例
  • 第六章—18—数据容器的通用操作
  • Kimi LeetCode 3347. 执行操作后元素的最高频率 II C语言实现