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

手机SIM卡打电话时识别对方按下的DTMF按键(二)

手机SIM卡打电话时识别对方按下的DTMF按键(二)

--本地AI电话机器人

  • 前言

书接上篇,在上一篇章《手机打电话时如何识别对方按下的DTMF按键的字符》中,我们从理论的角度来论述了DTMF的频率组成。并尝试使用400Kb左右的【TarsosDSP-Android-2.4.jar】第三方库进行FFT(傅里叶变换)运算,以提取对方通话语音中掺杂的DTMF按键的字符(术语叫“DTMF解码”)。

本篇章中,我们将这个DTMF解码器的功能,整合到蓝牙电话SDK,并在其示例app的界面中展示DTMF字符的内容。使SIM卡电话通话时(来电或手机拨打出去)均可在界面中能正常查看到通话的目标手机按下的DTMF按键的字符内容。

蓝牙电话SDK示例app的下载路径为:

拨号器SDK示例app:http://120.78.211.195:8060/sdk/SdkDemo.apk

USB蓝牙配件购买路径(参考):https://item.taobao.com/item.htm?_u=pk10l4ccbcd&id=649368472986

  • 通话语音传输路径

蓝牙电话SDK方案中采用外置USB蓝牙配件的方式,拦截手机SIM卡通话的语音和通话事件,并将语音数据上抛给【手机App】进行处理,如下图右侧所示。

DTMF解码器是整合到手机App中的一个纯软件模块,它通过读取通话时的语音,对语音进行FFT运算后,识别其低频和高频的数值进行对应的查表匹对,从而检测出DTMF按键值的功能。

实现DTMF解码的前提条件是手机App能够实时获取得到SIM卡通话的原始PCM语音数据,这个也是本篇内容为何要基于【蓝牙电话SDK】做进一步加工的原因。(因为只有挂载了该SDK的普通安卓App并插入USB蓝牙,才能拦截电话通话的声音)

  • SDK示例App界面

由于蓝牙电话SDK依赖一个外置的USB蓝牙的手机配件,对于手机App来说,插入和不插入该USB配件,在App界面上应需要做出区分。

App主界面的中部区域,增设了【USB蓝牙信息】的显示区域。未插入USB蓝牙时这个区域是隐藏的,插入【vid=0x0a12 pid=0x0001】的USB设备后App会弹出USB授权提示框(这个是Android的授权机制),如下图所示:

弹框后会依次进行蓝牙【配对-连接】等操作,手机App通过USB接口操控外置USB蓝牙进行各种绑定、连接、数据收发等业务和数据控制操作。外置USB蓝牙和手机连接成功后,界面标注黄色会消失。此时,表明手机中电话通话的拦截效果开始生效。

  • 通话对方DTMF识别与界面显示

示例App界面中,【功能设置】区域底部增设了“对方按下DTMF按键”的显示区域,如下图右侧界面所示。

当电话通话时(手机来电或手机拨打出去),当对方的手机通过其电话软键盘按下对应的DTMF字符时,蓝牙电话SDK示例App的界面会实时的显示对方按下的DTMF按键值。供后续基于这个SDK开发的应用根据这个DTMF交互按键来进行各种IVR语音导航或进一步的增值扩展操作。

  • 总结

本来上一篇《手机打电话时如何识别对方按下的DTMF按键的字符》当中的内容已经足够描述功能和场景了。但是后来想一想,毕竟识别出DTMF的字符后,直接打印到Android的Logcat日志里面毕竟不直观。干脆就上抛到手机界面上,进行实时的显示和变更,也方便用户和使用者进行校对和分析。

附注:蓝牙电话SDK示例App其实是开放源代码的。有兴趣的读者或朋友,其实可以获取App最新的源代码,自己解析、优化、以及在这个基础之上扩展出更多的自己关于电话通话方面的新能力。

最后,放上一段即兴录制的视频,展示了【来电自动接听】和【实时解码DTMF】功能的大致操作效果,如下视频所示:

SIM卡打电话时识别对方按下的DTMF按键


上一篇:手机打电话时电脑坐席同时收听对方说话并插入IVR预录声音片段

下一篇:手机打电话时由对方DTMF响应切换多级IVR语音应答(一)

http://www.xdnf.cn/news/287515.html

相关文章:

  • SpringBoot整合RabbitMQ(Java注解方式配置)
  • CMake基础介绍
  • D. Pythagorean Triples 题解
  • 手机打电话时由对方DTMF响应切换多级IVR语音应答(一)
  • \documentclass[lettersize,journal]{IEEEtran}什么意思
  • 机器人强化学习入门学习笔记(二)
  • DeepSeek-Prover-V2:数学定理证明领域的新突破
  • Dify网页版 + vllm + Qwen
  • Matlab自学笔记五十三:保存save和载入load
  • 杨校老师竞赛课之C++备战蓝桥杯初级组省赛
  • Python爬虫实战:获取优美图库各类高清图片,为用户提供设计素材
  • 洛谷 P9007 [入门赛 #9] 最澄澈的空与海 (Hard Version)
  • 【从零开始学习微服务 | 第一篇】单体项目到微服务拆分实践
  • 本地MySQL连接hive
  • ASP.NET Core 请求限速的ActionFilter
  • 算法中的数学:质数(素数)
  • 30天通过软考高项-第十一天
  • CodeBlocks25配置wxWidgets3.2
  • 004-nlohmann/json 快速认识-C++开源库108杰
  • 地埋式燃气泄漏检测装置与地下井室可燃气体检测装置有什么区别
  • 专业课复习笔记 4
  • Vue中的过滤器参数:灵活处理文本格式化
  • 5月5日日记
  • 基于 HTML5 Canvas 实现图片旋转与下载功能
  • linux tar命令详解。压缩格式对比
  • Java IO流核心处理方式详解
  • 论高并发下的高可用
  • LeetCode 热题 100 46. 全排列
  • 【PostgreSQL数据分析实战:从数据清洗到可视化全流程】5.1 描述性统计分析(均值/方差/分位数计算)
  • 代码随想录算法训练营Day45