本文系作者原创。如转载,请注明出处。 谢谢!

音频软件开发同其他软件开发一样,都需要去调试。音频软件调试同其他软件调试方法有相同的地方,也有不同的地方,同时调试时还需要借助一些专门的工具,有了这些方法和工具,就能快速的定位问题和解决问题。下面我们就谈谈这些方法和工具。

1,方法

1)log

这是软件调试中最常用的方法,音频调试也不例外。在写代码时加上一定的log, 在出问题时就打开这些log,通过log分析问题出在什么地方。一个好的log体现在如下几点:

a)    要有时间和日期,有时候时间戳对分析问题很重要。

b)    函数入口处和出口处要加上log,有了这就能很快看出函数调用流程。

c)    发生问题时的相关变量值要打印出来,这对分析问题至关重要。

d)    log要分级别,常见级别有error/warning/debug/info等。有时候log打印太多会导致load大从而出现不同的结果影响分析。

2)二分法

当前版本有问题,而以前的某个版本没问题,这说明是近期的某个改动引起的。这时我们就需要用二分法快速找出哪个版本开始出问题的。先把当前版本和那个好的版本中间一分为二,取中间那个版本,看有没有问题,有的话说明这个中间版本之前就有问题了,没有的话说明是这个中间版本后面的改动引入的。这样的话就把范围缩小一半了。在这样继续二分下去,直到最后找到最初出问题的版本。找到版本后再看这个版本加入了几个改动,分析哪个改动最可能引起这个问题,直到最后找到根本原因解决问题。

3)crash的分析方法

写代码crash是难免的,关键是crash后能快速找到原因并最好后面不犯这个错误。通常crash主要有这几种原因:空指针,除零,越界,死循环,当然还有其他的原因。在Linux下有好的工具,很容易查。有些小众的OS没什么工具查crash问题,如果是做底层的可以借助JTAG工具,不然的话还得靠log。Log是实时的还好办,多加点打印总能找出crash的地方。就怕log非实时,这时只能具体问题具体分析了。记得在一个OS下log非实时,一个模块相对独立,只能把函数调用关系和输入参数值都保存在文件里,在Linux下做一个应用程序去读这个保存的文件从而模拟当时的过程,再借助Linux的工具找到crash的地方,最终这个应用程序成了一个工具,以后再遇到类似的问题就能很快解决了。

4)最小系统法

做一个软件系统时刚开始是一个最小系统,即缺了任何一个模块,系统不能用。后来加上一个个功能使系统完备。在写代码时我们可以加上一些标志位使这些后加的功能enable或者disable。这有助于后面出现问题时排查。下图是语音通信的软件框图,最小系统是采集播放编解码网络发送接收等,没有这些不能通话。而前处理的一些模块(AEC/ANS/AGC等)则不是最小系统里面的,它们是后来一步步加上去的。假设系统出问题了,我们先disable前处理的诸多模块,形成最小系统,看有没有问题,有说明问题在最小系统里,再继续调查。没有的话先把AEC使能看有没有问题,有说明问题在AEC里,没有说明问题在ANS或者AGC里。如没有问题继续使能ANS看是否有问题,有说明问题在ANS里,没有说明问题在AGC里。经过这几步基本定位问题在哪个模块里,后面再结合其他方法直到找到根本原因。

音频开发时不管是voice还是music好多问题是音频听下来不对,这时就要用音频特有的debug方法了。

5)dump音频数据

Dump音频数据就是把音频数据dump出来用工具(比如CoolEdit, 后面讲工具时会具体讲)播放,或者看波形,或者看频谱,看是否正确。一般是找几个可能的dump点,进模块前一个dump点, 出模块后一个dump点。如果进模块前dump出来的数据是好的,而出模块后的音频数据是坏的,那么问题就出在这个模块了,再一步步排查,最终找到把音频数据写坏的地方。还是以上面的语音通信软件框图为例,在AEC前设一个dump点,AEC后再设一个dump点,如果AEC前的音频数据是好的,AEC后的音频数据不好了,问题肯定出在AEC里。

Dump音频数据也有几种不同的方法,在不同的场合用不同的方法。

a)把音频数据写进指定的文件里,问题复现后把这个文件导出来用工具分析。

b)把音频数据放进RTP包里发送到指定的IP地址上,用抓包工具(比如wireshark, 后面讲工具时具体讲)抓到这些包。由于是PCM数据,在wireshark上可以直接听或者看波形。这多用于语音通信场景。

c)有时候有些模块对自己是黑盒的,比如在linux下kernel space的音频驱动对做use space的来说就是黑盒。在use space里调查下来音频数据没问题,但是最终从扬声器或者耳机出来的音频是有问题的,这时可以用一根音频线一头连着出问题的设备的耳机,另一头连着电脑,复现问题,用CoolEdit把出问题时的音频录下来,先听确认问题出在这个黑盒模块里,然后看波形,是否有规律,如果有规律,好查一些,没规律再具体问题具体分析。

6)loopback音频数据

loopback音频数据就是形成回环,从而来排查问题。还是以上面的语音通信软件框图为例,有几种不同层次的loopback,见下图:

1)    把采集和播放形成loopback,即把采集到的音频数据立刻payback出来,听下来是好的说明音频驱动没问题,不好说明问题在音频驱动里面。

2)    把前处理后的数据和播放形成loopback,即把ANS后的PCM数据直接播放出来,听下来是好的说明前处理没问题,不好说明问题在前处理里面。

3)    把编码和解码形成loopback,即把编码后的码流立刻放进解码器得到pcm数据再playback出来,听下来是好的说明问题出在网络侧,不好说明问题出在编解码里面。

通过上面几个loopback基本上可以定位问题出在哪个模块里,再在这个模块里仔细调查直到找到根本原因。

2,工具

上面讲方法时提到了几个工具,如CoolEdit,下面具体讲。

1)CoolEdit / Audition

这应该算是做音频开发的必备工具了。以前叫CoolEdit,后来被Adobe收购重新包装后形成了Audition。我个人还是习惯于用CoolEdit,原因一是用习惯了,二是CoolEdit可以保存成PCM文件,而Audition却不可以,做音频开发的保存成PCM文件最方便。

用CoolEdit可以听音频是否正常,也可以看波形,在出问题时看波形是否有规律,还可以看频谱。同时还可以生成一些特定的音频文件用于去调试。比如调试音频算法时用一个时间相对较长的(> 1秒)的音频文件会很不方便,主要是因为log多,不便于分析。算法通常一帧为10ms或者20ms,需要几帧就可以调试算法了。这时用CoolEdit做一个几十ms的PCM文件给算法调试用。再比如用CoolEdit做一个20HZ到20000HZ的扫频文件作为某个算法或者某个系统的输入,看这个算法或者系统的频响如何。

CoolEdit的具体使用可以看help文件,或者看网上的文章,这里就不详细讲了。

2)Wireshark

Wireshark主要用于语音通信场景,抓网络上的语音包。当然它也可以抓其他类型的包,在做音频开发时就是抓语音相关的RTP/RTCP包了。抓到包后可以看某个具体包的RTP/RTCP属性,比如sequence number/time stamp等,从而去分析定位问题等。Wireshark也可以分析丢包率等,还可以播放codec 为g711的语音包,当然还有其他用途,这里就不一一说了,有需求的可以到网上看具体的文章。

3)mediainfo

Mediainfo主要用于音乐场景,用它可以看到一个音乐文件(例如MP3)的属性,有采样率/声道数/codec类型/码率等。如果在log中看到的打印值和mediainfo中显示的值对不上,说明读取音乐文件属性的代码有问题。

4)GoldWave

GoldWave也主要用于音乐场景,用它来做采样率/codec/码率等的转换。支持的采样率、codec、码率都特别多,对调试有不少帮助。例如某个系统要支持采样率为11025HZ的音乐文件,但是市面上的音乐文件一般为44.1KHZ或者48KHZ的,这就需要专门的工具去做转换,从而得到想要的文件。然后拿这个文件去调试测试看系统是否支持采样率为11025HZ的音乐文件。

关于音频debug的方法和工具暂时就先谈这么多,以后想到了被遗忘的以及有新的会及时补充。也欢迎大家补充,形成一个好的debug方法和工具集,对大家都是益处多多。谢谢!

音频软件开发中的debug方法和工具的更多相关文章

  1. Maven——软件开发中一个神奇的项目管理工具

    由于本人是从c++转入从事JAVA工作的 所以很多东西要从头学起,相信有很多跟我一样的人吧,那么我们一起来学习. 今天我们一起来认识下Maven这个工具,很多人可能会问题了,为什么说是工具呢?不是写代 ...

  2. Atitit 软件开发中 瓦哈比派的核心含义以及修行方法以及对我们生活与工作中的指导意义

    Atitit 软件开发中 瓦哈比派的核心含义以及修行方法以及对我们生活与工作中的指导意义 首先我们指明,任何一种行动以及教派修行方法都有他的多元化,只看到某一方面,就不能很好的评估利弊,适不适合自己使 ...

  3. 关于软件开发中兼容win7注册表的解决方案

    关于软件开发中兼容win7注册表的解决方案   编写人:CC阿爸 2014-3-14 l  近来在开发一winform程序时,发现在xp 系统访问注册表一切正常.可偏这个时候,微软又提醒大家.Xp今年 ...

  4. IOS开发中重写init方法使用需谨慎

    IOS开发中重写init方法使用需谨慎 今天在写一个小软件的时候出现一点问题,这个软件的功能是搜索全国学校,首页就是搜索输入框,在框中输入完要查询的学校所在省份,点击buttom后就会跳转到对应的视图 ...

  5. 编写高质量代码:改善Java程序的151个建议(第一章:JAVA开发中通用的方法和准则)

    编写高质量代码:改善Java程序的151个建议(第一章:JAVA开发中通用的方法和准则) 目录 建议1: 不要在常量和变量中出现易混淆的字母 建议2: 莫让常量蜕变成变量 建议3: 三元操作符的类型务 ...

  6. 浅谈传统语音通信和APP语音通信音频软件开发之不同点

    本人在传统的语音通信公司做过手机和IP电话上的语音软件开发,也在移动互联网公司做过APP上的语音软件开发.现在带实时语音通信功能的APP有好多,主流的有微信语音.QQ电话.钉钉等,当然也包括我开发过的 ...

  7. 软件开发中 SQL SERVER 任务的用法

    在软件开发中,经常性会用到定时任务.这个时候你可能会想到线程.但是事实中,线程方法比较麻烦.容易出错,资源竞争等问题,设计起来让你很头痛. 现在给大家提供一个新的思路,用SQL SERVER 的任务管 ...

  8. Atitit. 软件开发中的管理哲学--一个伟大的事业必然是过程导向为主 过程导向 vs 结果导向

    Atitit. 软件开发中的管理哲学--一个伟大的事业必然是过程导向为主    过程导向 vs 结果导向 1. 一个伟大的事业必然是过程导向为主 1 1.1. 过程的执行情况(有明确的执行手册及标准) ...

  9. 软件开发中的完整测试所包括的环节UT、IT、ST、UAT

    软件开发中的完成测试环境所包括的环节包括:UT.IT.ST.UAT UT = Unit Test 单元测试 IT = System Integration Test 集成测试ST = System T ...

随机推荐

  1. Java通过Axis2发布WebService

    参考文档: http://blog.csdn.net/ghsau/article/details/12714965 http://www.iteye.com/topic/1135747 http:// ...

  2. RabbitMQ知多少

    1.引言 RabbitMQ--Rabbit Message Queue的简写,但不能仅仅理解其为消息队列,消息代理更合适.RabbitMQ 是一个由 Erlang 语言开发的AMQP(高级消息队列协议 ...

  3. curl学习之curl_setopt参数设置大总结

    CURL函数库里最重要的函数是curl_setopt(),它可以通过设定CURL函数库定义的选项来定制HTTP请求使用方法:bool curl_setopt (int ch, string optio ...

  4. php与MySQL(基本操作)

    PHP连接 MySQL 在我们访问 MySQL 数据库前,我们需要先连接到数据库服务器,连接服务器,我们使用mysqli_connect()函数. 在使用这个函数之前,我们首先来看一下这个函数的语法: ...

  5. ubuntu14.04_CUDA8.0_cudnn5.1_Tensorflow配置

    深度学习框架tensorflow相比与caffe抽象层做的更好,即使用tensorflow的人不需要关心底层的实现,做底层实现的人不需要关心上层的模型和算法;caffe耦合比较紧凑,若想caffe用的 ...

  6. nopCommerce 3.9 大波浪系列 之 NUnit 配置调试环境

    官网:http://nunit.org/ GitHub:https://github.com/nunit 本文只介绍NUnit在VS中的配置使用,进一步学习 NUnit 请参考官方文档. nopCom ...

  7. pc端的企业网站(IT修真院test9)详解一个响应式完成的pc端项目

    一:引入bootstrap框架 昨天一直被bootstrap栅格系统折磨. why? 我本来想一边码字,一边学习栅格布局的.but不成功.这时我头脑已经昏了. 下午,我查看了bootstrap的官网, ...

  8. fzu 2257 saya的小熊饼干

    https://vjudge.net/problem/FZU-2257 题意:略 思路: 看题解补的题.正难则反的思想求概率. 首先,由于各维数之间是独立的.所以以x为例.首先,计算可以取到(i,j) ...

  9. Java 9 揭秘(16. 虚拟机栈遍历)

    Tips 做一个终身学习的人. 在本章中,主要介绍以下内容: 什么是虚拟机栈(JVM Stack)和栈帧(Stack Frame) 如何在JDK 9之前遍历一个线程的栈 在JDK 9中如何使用Stac ...

  10. eclipse 打包 jar 到 Linux上运行

    1.选择需要打包的项目,右键 Export 2.选择Runnable JAR file,然后点击 Next 3.选择jar包运行的main类,以及定义jar包的名字,保存的地方 4.将 导出来的 ja ...