蓝牙HFP协议推荐的语音丢包补偿算法浮点实现的定点化
最近在做蓝牙的宽带语音通话。相对于蓝牙窄带语音,主要变化是把采样率从8k变到16k,以及编解码器从CVSD变成mSBC(modified SBC,改进的SBC)等。蓝牙语音通话相关的HFP(Hand Free Profile)强烈建议在宽带语音通话时要用上语音丢包补偿(packet lost concealment,PLC)算法来保证丢包时的语音质量,也给出了推荐的PLC算法的浮点实现。由于是在ADSP上做,算力有限,浮点实现是不能直接用的,因此要把浮点实现定点化。下面就讲讲我是怎么来做定点化的。
1, 理解算法的浮点实现
算法实现是基于paper “Waveform Substitution Techniques for Recovering Missing Speech Segments in Packet Voice Communications”的。 函数不多,API主要有三个:InitPLC()是初始化,PLC_good_frame()是正常帧处理,PLC_bad_frame()是丢包帧处理。内部函数也有三个:CrossCorrelation()算互相关,PatternMatch()算最匹配的起始位置,AmplitudeMatch()根据最匹配的位置算比例因子(scale factor),这些函数均在处理丢包帧时调用。
2, 结合mSBC实现做一个丢包补偿的demo
先前只有用于蓝牙音乐播放的SBC编解码demo(基于blueZ)。 为了支持mSBC, 对SBC代码做了修改(核心算法不变,对外围代码做了修改以支持mSBC)。现在又要结合PLC做丢包补偿,需要把PLC代码嵌到mSBC解码程序里。做丢包补偿demo的大致步骤如下:
1) 把一段16k采样的语音PCM用mSBC编码程序编码成sbc码流
2) 用mSBC解码程序把sbc码流解码成PCM
3) 在mSBC的解码程序里嵌入PLC代码。假设每20帧丢一帧(即丢包率为5%),用PLC算法去补偿丢的一帧,看补偿效果。补偿后的语音听起来无异样才算OK。这个PLC算法以及实现是HFP里推荐的,理论上不会有问题。如果补偿后声音有异样,一般是API没用好。
3, PLC算法的定点化
做定点化前需要找到做的点。我通过梳理代码发现有三处需要做定点化,下面看看这三处是怎么做定点化的。
1) 余弦表的定点化
代码中有一个浮点的余弦表,如下:

需要变成定点的表。看了表中值的范围,绝对值都是小于1的,因此在定点表示时适合用Q0.15。这样浮点的表就变成了定点的表,如下:

代码中用到余弦表时都是与PCM值相乘。两个short值相乘,要注意溢出,因此乘前要把一个值强制转换成int型。相乘后要做移位操作(右移15位),在移位前使值更接近浮点值,要做四舍五入(加上 1<<14,即加上0.5)处理。示例代码如下:

2) 算互相关时的定点化
代码中算互相关的代码如下:

从代码看出,用的算式如下:

既涉及到求平方根,又涉及到除法。以前做代码优化时知道求平方根可以用牛顿迭代法,于是我就在AMR-WB的参考代码(主要是basic operation的相关代码)里找有没有现成的可以用。不仅找到了,而且还是算平方根的倒数的(Word32 Isqrt(Word32 L_x),输入是一个32位的值,输出是Q0.31的值),这样除法就变成了乘法。我用几个值(比如100)带进函数Isqrt()试试,Q0.31的结果跟浮点值是对得上的。算式也就变成了如下的:

代码中可以看出x2,y2均是32位的,相乘后很可能超出32位,而Isqrt()的输入是32位的,不能直接使用,需要做些变形,变成 m * 22n(m为16位以内的整数,n为正整数)的形式。

这时m1 * m2是一个32位以内的数,就可以用函数Isqrt()了。

用Isqrt()求,
就是就是右移(n1 + n2)位。结果再乘以num就可求出定点的Cn了。
3) 做除法时的定点化
浮点实现中在算比例因子时用到了除法,代码如下:

看了AMR-WB参考代码,也有除法实现,即Word16 div_s (Word16 var1, Word16 var2)。不过是16位的除法,输出也是一个Q0.15的16位值。使用时还有其他限制条件:被除数和除数要都是正数,且被除数小于等于除数。在浮点代码中被除数和除数均可能是32位的正值,因此不能直接用,需要做些改进,变成 m * 2n(m为16位以内的正整数,n为正整数)的形式。

用div_s()求出m1/m2,2(n1-n2)就是移位(左移、右移或者不移)。从浮点代码看出比例因子范围在0.75~1.2,要用Q1.14表示,因此要把用div_s()算出来的Q0.15值转换成Q1.14形式。最后再加一个限幅,范围是0.75~1.2,用Q1.14表示就是12288~19661。经过以上处理后就可求出定点的比例因子了。
在定点化的过程中,每一步定点化时都要比较定点的结果和浮点的结果,确保误差在很小的范围内,通常不超过1。做完后还要比较最终的误差,即最后的PCM值的误差。下图给出了浮点实现和定点实现最终的部分PCM值比较:

从图上可以看出,在做丢包补偿时,定点的和浮点的实现部分PCM值有误差,但误差都是在1范围内,这是可以接受的。
蓝牙HFP协议推荐的语音丢包补偿算法浮点实现的定点化的更多相关文章
- 深入剖析iLBC的丢包补偿技术(PLC)
转自:http://blog.csdn.net/wanggp_2007/article/details/5136609 丢包补偿技术(Packet Loss Concealment——PLC)是iLB ...
- TCP传输协议中如何解决丢包问题
TCP在不可靠的网络上实现可靠的传输,必然会有丢包.TCP是一个“流”协议,一个详细的包将会被TCP拆分为好几个包上传,也是将会把小的封裝成大的上传,这就是说TCP粘包和拆包难题. 但是许多人有不同的 ...
- 【转】使用TCP协议连续传输大量数据时,是否会丢包,应如何避免?
使用TCP协议连续传输大量数据时,是否会丢包,应如何避免? 比如发送文件.记得有人提过可能会发生什么堆栈溢出.怎样避免呢?是不是可以收到数据后发送确认包,收到确认包后再继续发送.或是发送方发送了一些数 ...
- QUIC协议详解之Initial包的处理
从服务器发起请求开始追踪,细说数据包在 QUIC 协议中经历的每一步.大量实例代码展示,简明易懂了解 QUIC. 前言 本文介绍了在 QUIC 服务器在收到 QUIC 客户端发起的第一个 UDP 请求 ...
- 丢包 ICMP
小结: 1.ICMP 常见网络丢包故障分析及处理 云极安 云极安 2019-12-25 我们在管理维护网络的过程中经常会遇到数据包丢失的现象.使用Ping命令进行连通性测试,则会发现Ping包延时远远 ...
- luogu题解 P2419 【牛大赛Cow Contest】传递丢包
题目链接: https://www.luogu.org/problemnew/show/P2419 分析: "在交际网络中,给定若干元素和若干对二元关系,且关系具有传递性. 通过传递性推导出 ...
- 蓝牙 BLE 协议学习: 000-有关概念介绍
背景 在学校内就用过蓝牙技术参加过比赛(并拿了奖):而蓝牙作为物联网中比较常见的协议,有必要进行深入的学习.此后的文章会以 ble(v4.0) 进行学习. 介绍 蓝牙技术最初由电信巨头爱立信公司于 1 ...
- UDP主要丢包原因及具体问题分析
UDP主要丢包原因及具体问题分析 一.主要丢包原因 1.接收端处理时间过长导致丢包:调用recv方法接收端收到数据后,处理数据花了一些时间,处理完后再次调用recv方法,在这二次调用间隔里,发过来 ...
- UDP丢包和无序 问题的解决方法
最近在做一个项目,在这之前,做了个验证程序. 发现客户端连续发来1000个1024字节的包,服务器端出现了丢包现象. 纠其原因,是服务端在还未完全处理掉数据,客户端已经数据发送完毕且关闭了. 我用过s ...
- 用clumsy模拟丢包测试socket库的失败重传
用python的socket库写了通信小程序,现在我需要通过软件模拟出在网络极差的情况下,socket底层解决丢包问题的能力怎么样,我一开始想的是分别在linux和windowns下分别测试,后来一想 ...
随机推荐
- MFC-ODBC API动态连接配置数据库
一.ODBC管理器介绍 在Window中,ODBC数据远管理器有6个标签:用户DSN.系统DSN.文件DSN.驱动程序.跟踪.连接池,通常情况下,使用用户DSN或者系统DSN,这里主要了解用户DSN和 ...
- NC22544 车站
题目链接 题目 题目描述 一个国家有n个城市,有n-1条道路连接,保证联通.还有m条铁路,从1~m编号,第i条铁路是从ui到vi的简单路径,多次询问一段区间的铁路的车站. 一个点可以作为区间[L,R] ...
- NC15128 老子的全排列呢
题目链接 题目 题目描述 老李见和尚赢了自己的酒,但是自己还舍不得,所以就耍起了赖皮,对和尚说,光武不行,再来点文的,你给我说出来1-8的全排序,我就让你喝,这次绝不耍你,你能帮帮和尚么? 输入描述 ...
- MQTT-QoS与协议流程
QoS的报文收发流程 QoS 0 最多交付一次,消息有可能丢失,最低的QoS等级,没有任何的机制,不需要等待确认和重传,只要保证消息发送,也可能到达不了接收端 QoS0消息发送流程: 发送端调用API ...
- 【Unity3D】协同程序
1 简介 1)协程概念 协同程序(Coroutine)简称协程,是伴随主线程一起运行的程序片段,是一个能够暂停执行的函数,用于解决程序并行问题.协程是 C# 中的概念,由于 Unity3D 的 ...
- KQL笔记
KQL: {'query': {'bool': {'must': [{'match': {'Sql': 'insert'}}, {'match': {'PolicyName.keyword': 'd8 ...
- Spring rce CVE-2022-22965
原理大致是这样:spring框架在传参的时候会与对应实体类自动参数绑定,通过"."还可以访问对应实体类的引用类型变量.使用getClass方法,通过反射机制最终获取tomcat的日 ...
- Qt三方库开发技术:QXlsx介绍、编译和使用
若该文为原创文章,未经允许不得转载原博主博客地址:https://blog.csdn.net/qq21497936原博主博客导航:https://blog.csdn.net/qq21497936/ar ...
- 【LeetCode二叉树#10】从中序与后序(或者前序)遍历序列构造二叉树(首次构造二叉树)
从中序与后序遍历序列构造二叉树 力扣题目链接(opens new window) 根据一棵树的中序遍历与后序遍历构造二叉树. 注意: 你可以假设树中没有重复的元素. 例如,给出 中序遍历 inorde ...
- 以下总结了Java一些面试前准备和技术参考题,希望对你有所帮助
以下真实模拟JAVA面试场景: 感谢您参加我们的面试: 以下是我们总结一些面试前准备和技术参考题,希望对你有所帮助. 首先,你需要先准备下工作相关的自我介绍,包括以下内容: 几年 Java 开发经验, ...