前几天收拾地下室,翻出一块十年前的达芬奇DM365开发板,朋友看见了打趣说这玩意儿现在连个智能灯泡都跑不过,我没反驳,但脑子里突然蹦出个念头——能不能用它做个网络音频服务器?反正闲着也是闲着,说干就干。
先说清楚一个事,很多人一听到"音频服务器"这四个字就觉得得是那种专业的流媒体机架设备,动不动几千上万,其实音频服务器的本质就是个能接收声音、处理声音、再通过网络把声音送出去的小电脑,DM365当年可是TI专为视频监控打造的芯片,内置了强大的ARM9核心和DSP协处理器,处理音频对它来说简直就是用牛刀杀鸡。
DM365这颗芯片到底有什么料
费曼学习法告诉我,想讲明白一件事,就得用最朴素的话从头说起,DM365本质上是一块集合了ARM926EJ-S处理器内核和C64x+ DSP的双核芯片,你可以把它想象成一个人的左右脑——ARM核负责逻辑控制和网络通信,就像管着日常起居的左脑;DSP核专攻数字信号处理,像右脑一样负责艺术创作,专门搞定音频编解码这种计算密集型任务。
这颗芯片在当年可是风光过的,2010年前后,市面上多少网络摄像机的内核都是它,现在虽然老了,但它的VPSS视频处理子系统里其实藏着音频接口,McASP(多通道音频串行端口)能直接对接音频编解码芯片,我手头这块板子上就焊着一颗TI自家的TVL320AIC3106音频Codec,简直是瞌睡碰到枕头。
硬件架构搭积木
做这个音频服务器的第一步是把硬件通路理清楚,说穿了不复杂:
- 声音采集端:用板载的麦克风接口或者Line-in接入模拟音频信号
- 模数转换:AIC3106这颗Codec把模拟信号转成I2S格式的数字音频流
- 数据搬运:通过EDMA(增强型直接内存访问)把音频数据从McASP搬到内存,全程不劳ARM费心
- 编码压缩:DSP核从内存里取数据,按需进行G.711、AAC或者MP3编码
- 网络分发:ARM核跑个轻量级的流媒体协议栈,把压缩好的音频打包发出去
这里面有个关键点很多人容易忽略——EDMA的作用,为啥要强调它?因为如果没有EDMA,ARM核就得亲自一趟一趟把数据从外设搬进内存,就跟老板亲自去收发室搬快递一样低效,有了EDMA,ARM只需要说一句"把那边的东西搬过来",就可以继续处理网络请求了。
| 硬件模块 | 在这个项目里的角色 | 选型建议 |
| 主控芯片 | 系统核心,负责调度和网络 | TMS320DM365,二手板约80-150元 |
| 音频Codec | 模数/数模转换,I2S接口 | AIC3106或AIC23,尽量选板载集成 |
| 网络PHY | 有线以太网物理层 | DM365内部集成EMAC,外接PHY即可 |
| 存储 | 存放固件和临时音频缓冲 | NAND Flash + DDR2,128MB以上够用 |
软件层怎么搭
硬件有了,得让软件跑起来,这部分我走了不少弯路,写出来给想复现的人省点时间。
操作系统选了Linux,版本用的是TI官方最后支持的DVSDK 4.02里的那套MontaVista Linux,内核虽然老掉牙(2.6.32),但好处是驱动齐全,McASP和AIC3106的驱动都是现成的,不用从零写,你如果问我为什么不用Buildroot或者Yocto重新构建,坦白说,对一块十几年的老芯片花那个精力不太值当,有现成的就用现成的。
音频处理链路我设计成这个样子:
驱动层
ALSA架构下的McASP驱动负责跟AIC3106通过I2S通信,这一步TI已经写好了,基本是开箱即用,唯一需要改的地方是把I2S接口配置成主模式,采样率定在44.1kHz或者16kHz,看你是偏重音质还是带宽。
中间层
用TI的Codec Engine框架来调用DSP端的音频编码算法,这个框架简单说就是ARM端扔任务给DSP端的一个邮差系统,ARM把PCM数据包寄过去,DSP处理完了送回压缩后的码流,Codec Engine的配置文件(.cfg)里要配好DSP内存段大小,我一开始图省事设小了,结果压48kHz立体声时直接溢出,查了两天才发现是这个地方。

应用层
起了一个轻量级的HTTP流媒体服务,用libmicrohttpd库实现的,为啥不用Live555或者更重的框架?因为DM365的内存统共就128MB,跑系统已经占了大半,能省一点是一点,客户端通过浏览器或者VLC直接访问开发板的IP地址就能收听实时音频流,格式用OGG或者MP3都行,浏览器基本都支持。
给个流程图就清楚了:
(图1:DM365音频服务器数据流示意——从麦克风到网络的全路径)
文献参考:TI Application Report SPRABY3, "DM365 Audio Encode Using Codec Engine"
几个踩过的坑
说实在的,做这个过程中碰到的问题比预想的多得多,第一个是实时性问题,音频不像视频丢几帧用户可能看不出来,声音卡一下耳朵立刻能察觉,DSP编码那部分必须保证每帧的处理时间小于帧间隔,否则缓冲区就会慢慢堆积最后溢出,我最后把DSP的时钟从默认的270MHz超到了324MHz才勉强稳住,代价是功耗高了那么一丁点——不过反正不用电池供电,无所谓。
第二个是网络抖动,刚开始用简单的TCP直接把音频流往外推,内网还行,一切到WiFi环境就开始断断续续,后来改成先缓冲两秒再播放,客户端加了个小型jitter buffer,问题就解决了,这两秒钟的延迟在监控场景里完全能接受,又不是打游戏需要毫秒级响应。

第三个比较冷门,AIC3106的寄存器配置,这颗Codec的寄存器足足有几十个,增益、偏压、滤波器参数全得手动设,我一开始偷懒直接用默认值,录出来的声音又轻又闷,还以为硬件坏了,后来翻数据手册(SLAS509D,厚厚一本)一个寄存器一个寄存器调,才发现是AGC没开、PGA增益太低、高通滤波器截止频率设太高三个问题叠在一起,调完之后声音立刻清晰了,那一刻的成就感值得之前所有的折腾。
(图2:AIC3106关键寄存器配置表,录播场景下的推荐值)
文献参考:TI Data Sheet SLAS509D, "TVL320AIC3106 Low-Power Stereo Audio Codec"
实测下来什么水平
拿16kHz单声道G.711编码跑,采样到输出的端到端延迟稳定在180毫秒左右,CPU占用率ARM端大约35%,DSP端约40%,换成48kHz立体声AAC-LC编码,延迟会升到300毫秒上下,DSP负载接近70%,但还在安全线以内,功耗整板大概2.8W,用一个5V/2A的旧手机充电头就能带起来,发热量用手摸几乎感觉不到。
声音质量方面,客观讲AIC3106的信噪比数据手册标称92dB,实际我测下来大概在88dB左右——毕竟板子的走线不是按音频设备的标准做的,有点底噪也算正常,但用来听个会议录音或者监控现场声音完全够用,比那些USB麦克风强到不知道哪里去了。
其实做这个项目最大的收获倒不是最后那个能跑的服务器本身,而是把一堆沉睡在数据手册里的技术细节重新激活了一遍,DM365这颗芯片的设计文档写得是真用心,十几年后读起来逻辑依然清晰,TI那帮工程师当年在PDF最后一页标注的修订记录,从2009年到2012年细细碎碎改了十几版——那种认真劲儿,在今天的快餐式开发节奏里已经不太容易见到了。
如果手头恰好有块吃灰的DM365板子,不妨翻出来试试,有些老东西,折腾起来比买现成的新玩具有趣多了。



网友评论