最近在做蓝牙的宽带语音通话。相对于蓝牙窄带语音,主要变化是把采样率从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协议推荐的语音丢包补偿算法浮点实现的定点化的更多相关文章

  1. 深入剖析iLBC的丢包补偿技术(PLC)

    转自:http://blog.csdn.net/wanggp_2007/article/details/5136609 丢包补偿技术(Packet Loss Concealment——PLC)是iLB ...

  2. TCP传输协议中如何解决丢包问题

    TCP在不可靠的网络上实现可靠的传输,必然会有丢包.TCP是一个“流”协议,一个详细的包将会被TCP拆分为好几个包上传,也是将会把小的封裝成大的上传,这就是说TCP粘包和拆包难题. 但是许多人有不同的 ...

  3. 【转】使用TCP协议连续传输大量数据时,是否会丢包,应如何避免?

    使用TCP协议连续传输大量数据时,是否会丢包,应如何避免? 比如发送文件.记得有人提过可能会发生什么堆栈溢出.怎样避免呢?是不是可以收到数据后发送确认包,收到确认包后再继续发送.或是发送方发送了一些数 ...

  4. QUIC协议详解之Initial包的处理

    从服务器发起请求开始追踪,细说数据包在 QUIC 协议中经历的每一步.大量实例代码展示,简明易懂了解 QUIC. 前言 本文介绍了在 QUIC 服务器在收到 QUIC 客户端发起的第一个 UDP 请求 ...

  5. 丢包 ICMP

    小结: 1.ICMP 常见网络丢包故障分析及处理 云极安 云极安 2019-12-25 我们在管理维护网络的过程中经常会遇到数据包丢失的现象.使用Ping命令进行连通性测试,则会发现Ping包延时远远 ...

  6. luogu题解 P2419 【牛大赛Cow Contest】传递丢包

    题目链接: https://www.luogu.org/problemnew/show/P2419 分析: "在交际网络中,给定若干元素和若干对二元关系,且关系具有传递性. 通过传递性推导出 ...

  7. 蓝牙 BLE 协议学习: 000-有关概念介绍

    背景 在学校内就用过蓝牙技术参加过比赛(并拿了奖):而蓝牙作为物联网中比较常见的协议,有必要进行深入的学习.此后的文章会以 ble(v4.0) 进行学习. 介绍 蓝牙技术最初由电信巨头爱立信公司于 1 ...

  8. UDP主要丢包原因及具体问题分析

    UDP主要丢包原因及具体问题分析 一.主要丢包原因   1.接收端处理时间过长导致丢包:调用recv方法接收端收到数据后,处理数据花了一些时间,处理完后再次调用recv方法,在这二次调用间隔里,发过来 ...

  9. UDP丢包和无序 问题的解决方法

    最近在做一个项目,在这之前,做了个验证程序. 发现客户端连续发来1000个1024字节的包,服务器端出现了丢包现象. 纠其原因,是服务端在还未完全处理掉数据,客户端已经数据发送完毕且关闭了. 我用过s ...

  10. 用clumsy模拟丢包测试socket库的失败重传

    用python的socket库写了通信小程序,现在我需要通过软件模拟出在网络极差的情况下,socket底层解决丢包问题的能力怎么样,我一开始想的是分别在linux和windowns下分别测试,后来一想 ...

随机推荐

  1. Git将某个文件合并到指定分支

    企业开发中,经常会单独拉分支去做自己的需求开发,但是某些时候一些公共的配置我们需要从主线pull,这时候整个分支merge显然不合适 1.切换至待合并文件的分支 git checkout <br ...

  2. 实操开源版全栈测试工具RunnerGo安装(三)MacOS安装

    以Sonoma 14.1.2系统为例 视频教程:https://www.bilibili.com/video/BV1fG411e7h2/?spm_id_from=333.999.0.0 1.下载并安装 ...

  3. etcd实现分布式锁分析

    3篇关于分布式锁的文章,可以结合看: consul实现分布式锁:https://www.cnblogs.com/jiujuan/p/10527786.html redis实现分布式锁:https:// ...

  4. 【Android 逆向】【攻防世界】RememberOther

    1. apk安装到手机,提示输入用户名注册码 2. jadx 打开apk public boolean checkSN(String userName, String sn) { try { if ( ...

  5. 【Android 抓包对抗】代理检查绕过

    1. 安装apk,点进去发现一点就挂 2. apk 拖入到jadx中观察,发现多出检查,一旦满足条件就会退出 .... if (((ConnectivityManager) getSystemServ ...

  6. .NET高级调试之sos命令输出看不懂怎么办

    一:背景 1. 讲故事 很多.NET开发者在学习高级调试的时候,使用sos的命令输出会发现这里也看不懂那里也看不懂,比如截图中的这位朋友. .NET高级调试属于一个偏冷门的领域,国内可观测的资料比较少 ...

  7. golang泛型简介

    linux下go版本安装(1.18.1版本) >>> wget https://go.dev/dl/go1.18.1.linux-amd64.tar.gz >>> ...

  8. 【系统选型】OA需求分析,OA系统选型及各供应商对比。

    去年公司内部做OA信息化升级,需要更新换代一下OA系统,当时OA选型整理下来的资料分享一下. 需求调研整理后如下: 一共四个模块需要更新&升级 :  OA模块(包括行政) + 合同模块 + 费 ...

  9. 【Azure Storage Account Table】询问批量将存储账户中的表嵌入另一个账户中的办法

    问题描述 询问批量将存储账户中的表嵌入另一个账户中的办法? 问题解答 方式一:使用 AzCopy 使用Az copy做表格的导入导出,注意您需要使用Azcopy 7.3版本来实现对Table的操作,可 ...

  10. 【Azure 应用服务】在Azure App Service多实例的情况下,如何在应用中通过代码获取到实例名(Instance ID)呢?

    问题描述 App Service开启多实例后,如何在代码中获取当前请求所真实到达的实例ID(Instance ID)呢? 问题答案 App Service 通过 环境变量的方式 显示的输出实例ID等信 ...