开发一个语音通信解决方案是一个软件项目。既然是软件项目,就要有相应的计划:有多少功能,安排多少软件工程师去做,这些工程师在这一领域的经验如何,是否需要培训,要多长时间做完,中间有几个主要的milestone等。我们曾经四个人花了近一年时间开发了一个语音解决方案,成功通过验收,各项关键指标(语音质量、单向时延)均达到运营商要求。当时是在芯片公司,在公司自己的芯片上做语音解决方案,增加芯片的卖点,增强芯片竞争力。我们做语音数据面实现,同时提供API。用户在上层控制协议(例如SIP)中调用API,从而实现语音通信功能。下面聊聊我们当时是怎么一步步做出来的。

1,讨论需求和软件架构

第一步是讨论需求,看要实现哪些功能,并对功能排一个优先级。讨论下来前处理(回声消除、噪声抑制、增益控制)、tone generation、重采样、codec(g.711、g.722、g.729)、RTP、RTCP 、jitter buffer等是第一优先级功能,VAD、CNG、SID、PLC等是第二优先级功能。同时制定了几个关键的milestone点:讨论需求和软件架构、成功打通第一个basic call、完成第一优先级功能产品基本能用、完成第二优先级功能攻克关键指标、全面测试通过验收。需求讨论后就要看用一个什么样的软件架构去实现这个解决方案。由于在Linux上开发,Linux上关于声音的架构是ALSA,讨论下来我们基于ALSA来做,这样可以缩短开发周期,在driver上仅仅是调试,在user space里用好ALSA-Lib等。同时确定了需要三个thread。Capture thread每隔10ms运行一次,靠ALSA获取采集到的语音PCM数据,然后做前处理编码打包等发到网络上。Play thread也是每隔10ms运行一次,从jitter buffer中获取10ms的码流,然后解码成PCM等再经由ALSA送给audio device播放出来。Packet receive thread用来从网络上收包,收到后解析并放进jitter buffer中。由于jitter buffer会被两个thread访问,需要加保护。这样语音数据面的软件架构图如下:

这些都确定后我们就开始向第一个Milestone进军了。

2,成功打通第一个basic call

这一阶段的目标就是成功打通第一个basic call。在每个阶段的开始我们都讨论一下大家的分工。共四个人,一个同学负责搭软件框架以及做API给上层协议调用。一个同学对ALSA比较熟悉,由他负责调ALSA,分两个阶段:第一阶段是把从ALSA得到的MIC的PCM数据再经由ALSA送给speaker播放出来,即在PCM侧形成Loopback。如果从MIC讲的话到speaker正确播放出来,ALSA的调试就完成了。第二阶段是加上最简单的codec G.711,形成codec loopback,即从ALSA得到的MIC的PCM数据用G.711编码得到码流,然后用G.711解码得到PCM数据再经由ALSA送给speaker播放出来。我主要负责网络侧,包括RTP的实现以及UDP收发包的实现等。也是通过loopback的方式调试,即将特殊字符(如全’a’)作为RTP的payload打包(codec用G.711),然后通过UDP socket发给目标地址,在目标地址板子上用UDP socket收包,收到后解析RTP得到payload,这个payload与发送端的payload 相比较,如果完全相同则说明RTP的实现UDP收发包的实现是正确的。由于jitter buffer相对比较复杂,这一阶段暂时不用jitter buffer,用固定的缓冲buffer来替代,但是jitter buffer的设计开始做起来。一个同学负责上层协议,也就是SIP,用一个开源的实现(上层协议不是我们的重点,主要是配合底层实现的),把基本功能调试好就可以了。

经过大家的努力,这一阶段的目标如期实现。当成功打通第一个basic call的时刻,大家别提多高兴啦。毕竟这几乎是从零开始做方案,这种经历还是难得的。我们还特地出去吃了一顿大餐,庆祝basic call成功打通。

3,完成第一优先级功能,产品基本能用

这一阶段的目标就是完成第一优先级功能,产品基本能用。依旧先分好工。先前做框架和API的做重采样、tone generation和codec(G.722/G.729)。先前调试ALSA的负责前处理(回声消除、噪声抑制、增益控制)。他们主要是先验证算法再调试算法使其在我们的方案里能很好的运行,先保证能用,后面再优化。我还是负责网络侧,完成jitter buffer和RTCP。做SIP的同学在这一阶段使功能更完善。这一阶段相对于上一阶段难度加大了,我们每个人在做的过程中都或多或少的遇到了一些困难。以我自己为例,在做jitter buffer的过程中就遇到了不少困难,主要是在一些细节上设计时想的不全,导致在良好网络下音质有时也不好。这些问题后来都一一被解决,同时也更新了设计文档。在大家的努力下,这一阶段也如期完工。老板来验收后对目标完成表示满意,又带着大家出去吃了一顿大餐。

4,完成第二优先级功能,攻克关键指标

这一阶段的目标就是完成第二优先级功能,攻克关键指标。关键指标有各种场景下的打电话时CPU load、各种网络环境下的语音质量(MOS值)、单向时延(one way delay)、连续打多少通电话不出错(bulk call)、单通电话最大能持续多长时间(long call)等。先前做重采样等的同学做第二优先级功能(VAD、CNG、SID、PLC等)。先前做前处理的做CPU load优化,使打电话时全部模块所占的CPU load控制在一个合理的范围内,当然是越小越好,做的很好就是我们方案的一个卖点。我主要负责语音质量、bulk call、long call等。做SIP的同学依旧完善SIP的功能。这一阶段使越来越难越来越有挑战了。优化算法load的同学需要测出各个算法的load,然后一一优化,尽可能降到最小。语音质量把我折腾的够呛。单向时延也是,仪器测出来的是一个总的值,我要找到各个模块引入的delay是多少,然后看怎么减小。bulk call和long call都是做起来非常头疼伤脑细胞的,一般都是晚上或者周末测,第二天早上或者下周一早上看结果,如果有问题就分析看怎么解决。

在这一阶段不少问题都是大家一起讨论看怎么解决的,毕竟这些问题都是很难的。 我们没被困难打趴,还是在规定时间内搞定了。我们离最终目标越来越近了!

5,全面测试,通过验收

在前面几个阶段中,把一个功能做完后会对这个功能相关的进行测试,确保功能完好,但是由于赶进度,并没有做全面性的测试。现在各项功能全部完备,关键指标也已全部达标,是时候全面测试确保产品质量了。首先是由我们开发人员自己测,我们觉得质量可以了再交由测试人员测。我们自己测时先由一个人写测试用例,然后大家一起review讨论,确保尽量全的覆盖,还有就是异常case要尽量多的考虑。测试用例review后大家分工测,发现了些问题,由于代码除了算法全是我们自己写的,对代码机制非常熟悉,发现的问题很快就解决了(算法都是非常成熟的,一般不会出问题)。交给测试人员后共测试了三轮,也发现了一些问题(测试人员的测试用例会更多一些,他们的测试也会更专业一些,一定要由他们把关产品质量),也都很快解决了。最终顺利的通过了验收。老板和我们都特别高兴,虽然我们的方案是免费提供给客户,但是这增强了我们芯片的竞争力,可以提高芯片的出货量。对我们个人而言也是一次很难得的一个方案从无到成功完成的经历,毕竟工作中这种经历太少了。

最后我们也进行了总结,有哪些lesson learnt,哪些做的不错,哪些还可以做的更好。

如何在嵌入式Linux上开发一个语音通信解决方案的更多相关文章

  1. 嵌入式Linux驱动开发日记

    嵌入式Linux驱动开发日记 主机硬件环境 开发机:虚拟机Ubuntu12.04 内存: 1G 硬盘:80GB 目标板硬件环境 CPU: SP5V210 (开发板:QT210) SDRAM: 512M ...

  2. 嵌入式linux应用开发完全手册学习笔记一

    2015.3.25星期三 晴 有两个星期没写学习日记了,找个时间把这段时间做的电子词典和ARM小项目总结一下. 下面的知识点总结,U-BOOT:参考PDF文档:嵌入式linux应用开发完全手册 当虚拟 ...

  3. 如何使用eclipse进行嵌入式Linux的开发

    如何使用eclipse进行嵌入式Linux的开发 作者:曾宏安,华清远见嵌入式学院高级讲师. 如何使用eclipse进行嵌入式Linux的开发 习惯了在windows环境下开发的程序员在转到Linux ...

  4. 嵌入式Linux上通过boa服务器实现cgi/html的web上网【转】

    转自:http://blog.csdn.net/tianmohust/article/details/6595996 版权声明:本文为博主原创文章,未经博主允许不得转载. 嵌入式Linux上通过boa ...

  5. 嵌入式Linux应用开发完全手册之环境搭建

    @ 目录 0.下载源配置 1.电脑BIOS启动虚拟化 2.linux网卡查看与IP设置 3.windows NAT虚拟网络配置 4.修改 Ubuntu 的 mountd 端口 5.vim设置 6.Mo ...

  6. 驱动开发学习笔记. 0.06 嵌入式linux视频开发之预备知识

    驱动开发读书笔记. 0.06  嵌入式linux视频开发之预备知识 由于毕业设计选择了嵌入式linux视频开发相关的项目,于是找了相关的资料,下面是一下预备知识 UVC : UVC,全称为:USB v ...

  7. Linux上构建一个RADIUS服务器详解

    作为一名网络管理员,您需要为您所需管理的每个网络设备存放用于管理的用户信息.但是网络设备通常只支持有限的用户管理功能.学习如何使用Linux上的一个外部RADIUS服务器来验证用户,具体来说是通过一个 ...

  8. 嵌入式linux驱动开发之点亮led(驱动编程思想之初体验)

    这节我们就开始开始进行实战啦!这里顺便说一下啊,出来做开发的基础很重要啊,基础不好,迟早是要恶补的.个人深刻觉得像这种嵌入式的开发对C语言和微机接口与原理是非常依赖的,必须要有深厚的基础才能hold的 ...

  9. 学习嵌入式Linux有没有一个最佳的顺序(持续更新)

    作为一个嵌入式Linux的初学者,我知道我可能将长期处于初学者阶段,因为我至今仍然没有能够摸索出一条很好的道路让我由初学者进入到更高级阶段.但是我始终没有放弃,本篇文章就是用来记录我学习嵌入式Linu ...

随机推荐

  1. 【Jquery系列】prop和attr区别

    问题描述 由于prop(property的缩写)和attr(attribute的缩写)翻译成汉语,均有“特性.属性”等意思的原因,导致大家容易混淆分不清,本篇文章将试图从英文含义,中文含义和Jquer ...

  2. Java filter中的chain

    一.Filter Filter:用来拦截请求,处于客户端和被请求资源之间,是为了代码的复用性.Filter链,在web.xml中哪个先配置就先调用哪个 二.FilterChain(过滤链) 服务器会按 ...

  3. charles支持https抓包配置

    自从公司站点全部启用https后,使用charles就不能像以前那样愉快的抓包啦!不过没关系,这里教你怎么配置charles,使其支持https抓包.之前有一篇介绍charles的使用,参考这篇:ht ...

  4. Bootstrap学习笔记(二)---常见工具和流程导航范例

    使用bootstrap框架避免不了写CSS,当CSS文件较大时,会发现维护起来很麻烦,一些默认值,如行高.背景色.标注颜色.字号等信息往往反复出现,还有一些大体上一致,只有小部分不同的样式定义,这就需 ...

  5. 环链表相关的题目和算法[LeetCode]

    这篇文章讨论一下与链表的环相关的题目,我目前遇到的一共有3种题目. 1.判断一个链表是否有环(LeetCode相关题目:https://leetcode.com/problems/linked-lis ...

  6. iOS 友盟推送,应用内推送启动图推送闪动黑屏,插屏推送方法报错

    以前都是用的极光推送,应公司需求要求使用友盟推送,为了以后是有分享都适用,,, 友盟推送文档,下载demo 感觉比极光用着要简单顺手 一切就绪后,开始发送消息测试,,,,,搞了半天没有发过来消息 原来 ...

  7. java 异常处理机制(java 编程思想)

    一.概念 "异常"这个词有"我对此感到意外"的意思.问题出现了,你也许并不清楚该如何处理,但你的确知道不应该置之不理:你要停下来,看看是不是有别人或在别的地方, ...

  8. Java I/O---概述

    对于程序设计者来说,创建一个好的输入/输出系统(I/O)系统是一项艰难的任务. 现在大量不同方案已经说明了这一点.挑战似乎来自于要涵盖所有的可能性.不仅存在各种I/O源端和想要与之通信的接收端(文件. ...

  9. android v4兼容包

    一句话解释android兼容包就是:支持更多的组件,样式更好看了.好粗糙的解释啊! 我们都知道Android一些SDK比较分裂,为此google官方提供了Android Support Library ...

  10. bzoj 3531: [Sdoi2014]旅行

    Description S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,满足从一个城市出发可以到达其它所有城市.每个城市信仰不同的宗教,如飞天面条神教.隐形独角兽教.绝地教都是常见的信仰. ...