APP下载

基于ARM 嵌入式系统的高保真无损音乐播放器设计

2012-08-09陈自龙周书杰汤勇明

电子器件 2012年6期
关键词:高保真开发板播放器

陈自龙,周书杰,汤勇明

(东南大学电子科学与工程学院,南京 210096)

嵌入式系统播放MP3 等有损压缩格式音乐的技术已经比较成熟[1~3],但是对于播放无损压缩音乐却鲜有报道。

本次设计选择基于ARM11 处理器核心的TINY6410 开发板进行,其良好的计算能力可满足对高压缩率音乐软解码的需求。针对开发板硬件资源和软件设计要求,本设计裁剪Linux 内核并对大容量存储器做了支持工作,研究了Linux 内核的ALSA音频架构,移植FLAC 解码库和APE 解码库,设计了音乐播放器的用户界面,使用Qt/Embedded 开发工具完成了播放器的软件开发工作。

1 高保真音乐

1.1 WAV 格式

WAV 是微软公司开发的一种音频文件格式,用于保存WINDOWS 平台的音频信息资源。该格式支持MSADPCM、CCITT A LAW 等多种采样压缩算法,支持多种音频位数、采样频率和声道,标准格式的WAV 文件和CD 格式一样,也是44.1 kHz 的采样频率,速率88 kbyte/s,16 bit 量化位数。

WAV 格式的优点是:编/解码简单(几乎直接存储来自模/数转换器(ADC)的信号)、多系统支持以及无损压缩。

其主要缺点是需要较大的音频存储空间。

1.2 FLAC 格式

FLAC 是Free Lossless Audio Codec 的缩写,即无损音频压缩编码,是一套著名的自由音频压缩编码,其特点是无损压缩,即音频数据以FLAC 编码压缩后不会丢失任何信息。

FLAC 解码只需整数运算,相对于大多数音频编码方式而言,对计算速度要求不高。

FLAC 编码有很多优点:可以定位、便于对CD进行备份、抗损伤、富于弹性的Metadata 等等。而且,FLAC 是开源项目,其文件格式对公众完全开放,其文件格式和编/解码的实现方式都不受任何已知专利的限制。FLAC 解码库所有的源代码都可在开放源代码的授权方式下得到。

1.3 APE 格式

APE 格式的音乐是流行的数字音乐格式之一,由Monkey's Audio 推出的一套无损音乐压缩算法压缩而成,该压缩算法针对音频数据进行了专门的优化,因而压缩率相对比较高,而且解压之后的音频数据没有任何损失。按照Monkey's Audio 官方的说法,同样一首歌曲的APE 格式仅是WAV 格式文件大小的一半左右,比FLAC 格式文件也要小。由于APE 格式音乐的解码涉及到浮点运算,而FLAC 格式只需要整数运算,所以通常FLAC 的解码速度比APE 快30%。而且,APE 格式使用了对称算法[4],在解压缩时还需要进行一些编码工作,这也消耗了部分CPU和内存资源,相比之下,FLAC 的格式则没有这个问题。

2 硬件系统

TINY6410 开发板的硬件系统由主控制器ARM11(S3C6410)、触摸显示屏、大容量存储设备(移动硬盘、SD 卡和优盘)、高品质音频解码芯片(WM9714)和功放输出组成。其中除大容量存储设备和触摸显示屏为外接设备外,其余都集成在开发板上。

图1 硬件系统框图

S3C6410 处理器采用ARM11 架构,主频533 MHz,最高667 MHz。

S3C6410 的高主频特性保证了对各音频格式软解码时的要求,特别是压缩率很高的APE 音乐。

丰富的外接存储接口满足了挂载多种存储器的需求。

开发板自带的4.3 吋TFT 真彩色触摸显示屏可满足用户的交互控制需求。

本嵌入式高保真音乐播放软件系统需要消耗可观的内存,主要原因包括:

(1)程序运行需要加载大量且必要的动态链接库到内存;

(2)播放器程序的界面设计中使用了很多PNG格式的图片以达到美观的目的,但是加载图片需要消耗内存;

(3)挂载外接大容量存储设备(特别是大容量移动硬盘)也需要消耗内存。

TINY6410 自带的128M DDR RAM 可以满足上述所有的内存消耗。

3 软件系统

本项目软件开发部分工作从底层到上层可以依次为:操作系统内核裁剪、程序库移植和编程应用、应用程序开发。图2 给出了该软件系统的框架结构。

图2 软件系统架构

3.1 Linux 内核裁剪

为了支持多种处理器和设备,Linux 内核庞大而复杂。就嵌入式高保真音乐播放器来说,内核的很多功能均未使用,将这些不必要的功能模块从内核裁减掉,有助于提高内核的运行效率,降低内存使用率[5]。主要被裁剪的模块有:

(1)网络设备支持(以太网控制器驱动和无线网卡驱动)

(2)多媒体支持(Video for Linux 图像采集框架以及相应的视频采集卡驱动)

(3)输入设备支持(鼠标和键盘)

(4)各种USB 设备支持(除了USB 大容量存储器支持)

(5)不必要的文件系统支持(Network File Systems、Ext3 Journaling File System 等)

(6)TINY6410 开发板自带的外接设备驱动(LED、蜂鸣器、按键驱动等)

经过裁剪之后的内核镜像大小为2 519 036 byte,相比未裁剪之前的3 689 004 byte,体积减小了约三分之一。

内核除了必要的裁剪,还需要添加对外接大容量存储器挂载支持[6]。

无损音乐文件体积大,开发板自带的存储空间不能满足需求,需要外接大容量存储设备。

不管是优盘、SD 卡还是移动硬盘,连接到开发板后都会有相应的内核信息产生,利用Linux 内核的热插拔机制(本系统利用Mdev 机制,Linux 内核还有其他热插拔机制),运行相应的存储分区挂载命令就可以挂载外部存储设备到开发板上。不过,NTFS 格式的移动硬盘挂载还需要在编译Linux 内核的时候添加NTFS 文件系统支持选项。

3.2 程序库移植和编程应用

3.2.1 ALSA 库移植和应用

对Linux 内核进行音频编程的本质是要使用音频驱动程序提供的编程接口,完成对声卡的各种操作。目前Linux 内核中声卡驱动程序主要是ALSA 架构。

ALSA 是Advanced Linux Sound Architecture 的缩写,即高级Linux 声音架构,它为Linux 内核提供了音频驱动和应用程序音频编程接口。其主要特性包括:

(1)高效地支持从消费类入门级声卡到专业级音频设备所有类型的音频接口;

(2)完全模块化的设计;

(3)支持对称多处理(SMP)和线程安全;

(4)对OSS(Open Sound System,Linux 内核早期的音频子系统架构)的兼容;

(5)提供了用户空间的ALSA-Lib 库来简化应用程序的开发。

图3 给出了ALSA 的层次结构示意。

图3 ALSA 层次结构图

可以看出ALSA 架构包括驱动包(ALSADriver),开发包(ALSA-Libs),开发包插件(ALSALib-Plugins),设置管理工具包(ALSA-Utils),其他声音相关处理小程序包(ALSA-Tools)),特殊音频固件支持包(ALSA-Firmware),OSS 接口兼容模拟层工具(ALSA-OSS)共7个子项目,其中驱动包是必须的。

ALSA-Driver 指内核驱动程序,包括硬件相关的代码和一些公共代码,非常庞大。ALSA-Libs 指用户空间编程的函数库。ALSA-Utils 包含一些基于ALSA 的用于控制声卡的应用程序。

在ALSA 的官网上下载ALSAlib 的源码包,使用如下命令编译ALSA 库:

完成编译配置之后,进行编译:

从上面的编译配置可以看出,指定的交叉编译平台是ARM,采用静态编译并且禁用了Python 组件,指定了ALSA Config Files和ALSA Plugin Files 路径。

将生成的库文件复制到板载系统对应的路径中,尤其Lib和Share 文件夹需要拷贝到/usr/local/lib和/usr/share/路径下。

3.2.2 ALSA 音频播放编程

ALSA 架构能够实现音频的回放、录音和混音等绝大多数音频处理相关的功能,这里只讨论音频回放功能。

ALSA 架构播放音频的一般编程步骤是:

(1)打开ALSA 的音频播放接口;

(2)设置硬件参数(访问模式、数据格式、声道数和采样率等);

(3)循环分次将所有PCM 数据送入声卡设备进行播放;

(4)播放完毕,关闭播放接口。

编写高保真音乐播放程序的思路是:先将FLAC和APE 音乐解码(WAV 无需解码),然后将所得音频数据送入声卡设备即可实现播放,其流程如图4所示。

图4 音频数据播放流程图

3.3 FLAC 格式解码支持

FLAC 的官方网站提供了一个开源的跨平台FLAC 编解码库,使用这个库的API 可以实现对FLAC 格式音乐的解码工作。

3.3.1 FLAC 解码库的移植

在FLAC 官网下载FLAC 编解码库的最新版本flac-1.2.1.tar.gz,解压后需要先修改flac-1.2.1/examples/cpp/encode/file/main.cpp 文件,否则编译的时候会出错。打开main.cpp,然后在开头添加一行#include <cstring>即可。接下来进行交叉编译的配置,执行命令:

配置结束后就可以编译和安装了:

这样FLAC 库就被安装到宿主机的/opt/embedded/libflac 路径下,将此路径下编译好的FLAC 运行库复制到开发板上的系统里,并设置LD_LIBRARY_PATH 变量就可以让运行的程序调用这个库的API。

3.3.2 FLAC 解码库的编程使用

FLAC 的解码库提供了C 语言接口和C++语言接口,本系统使用C 语言接口。对一个FLAC 格式音乐文件解码分为以下几个步骤:

(1)申请解码对象;

(2)初始化解码对象;

(3)MD5值检查(可选);

(4)FLAC 数据帧解码;

(5)删除解码对象。

对应的函数分别是:

每解码一帧数据,都有一个回调函数执行,这个回调函数将解码后的PCM 数据做适当调整后送入声卡设备播放。

至于音频参数信息的获取则需要FLAC__Metadata_SimpleIterator 这个结构体获得。通过FLAC__Metadata_SimpleIterator 从FLAC 文件中得到id为METADATA_BLOCK_STREAMINFO 的数据块,然后从这个数据块可以解析出具体的音频参数信息对声卡设备进行参数设置。

3.4 APE 格式解码支持

APE 格式的官方网站Monkey's Audio 提供了一个Monkey's Audio SDK 开发者工具包,使用其中的API 编程可以实现对APE 格式音乐的编解码工作。

3.4.1 Monkey's Audio SDK 的移植

Monkey's Audio 官方目前只是针对Windows 平台做了支持,不过一些开源爱好者已经将Monkey's Audio SDK 移植到Linux 平台,我们要对这个移植版本进行编译和安装,使用下列命令:

从上述配置可以看出,汇编被禁用,目标平台是ARM,并且编译好的库被安装到宿主机的/opt/embedded/libape 路径下。将这些编译好的库复制到开发板上的系统里,并设置LD_LIBRARY_PATH 变量就可以让应用程序使用Monkey's Audio SDK 了。

3.4.2 Monkey's Audio SDK 的编程

由于只需要进行解码工作,所以这里只涉及到解码API 的使用。Monkey's Audio SDK 使用C++语言编写,要解码APE 格式音乐,使用其解码类“IAPEDecompress”即可。APE 的解码接口只需调用“IAPEDecompress”类的“GetData()”函数、“Seek()”函数、“GetInfo()”函数即可,所有的数据同步和缓冲都由解码库自动完成。

3.5 播放器应用程序开发

本设计中的应用程序采用C++开发语言在Qt/Embedded 开发平台上实施。它是一个用于桌面系统和嵌入式开发的跨平台应用程序框架,包括一个直观的应用接口程序函数(API)和一个丰富的类库,以及用于GUI 开发和国际化的集成工具。

3.5.1 程序功能描述

本项目软件旨在实现一个功能完善的高保真无损音乐播放系统。

当用户按下电源按钮启动系统后,系统第一个执行的用户程序就是高保真音乐播放器程序。此程序扫描所有外接存储器中的无损压缩音乐文件,并生成一个音乐列表,保存扫描结果。这样以后再启动程序时,程序只需要读取这个音乐列表得到所有的歌曲信息。如果外接存储器发生变更或改动后,用户可以启动播放器的更新音乐库线程来更新音乐列表。这种设计在保持音乐文件同步的同时,减少扫描等待时间,提升用户体验。

用户可以进行播放、暂停、停止、上一曲、下一曲、播放进度调节和音量调节的控制等操作。歌曲的选择通过一个简洁、美观的播放列表实现,同时,对某一首歌曲的详细信息(如专辑、歌手、音乐流派等)也可以进一步查看。

作为一个完整的系统设计,播放器主界面还提供了时间日期显示和设置、关机和更新本地音乐库等系统服务和功能。

3.5.2 界面设计

随着软件设计水平的提升,用户不仅关注软件的实用性,对软件界面设计的美观性和易用性也有着较高的要求。

本嵌入式高保真音乐播放器界面设计以简约、美观为主,配合以阴影、半透明和动画等效果,在实现系统完整功能的基础上,带给用户良好的人机交互体验。

主界面、播放列表界面、单曲信息查看界面等设计如图5~7所示,其它一些界面元素设计如图8所示。

3.5.3 应用程序设计

本应用程序涉及到Qt 界面编程、多线程处理、Linux 内核音频编程以及无损压缩音频软解码等,其程序模块化设计如图9所示。

图5 播放器主界面

图6 音乐列表界面

图7 单曲信息查看界面

图8 播放器界面元素综合图

图9 程序模块划分图

可以将上述模块粗略地划分为:

(1)界面显示模块;

(2)音乐播放控制模块;

(3)音频解码模块;

(4)系统设置和服务模块。

界面显示模块是播放器人机交互的接口。通过继承Qt 的QWidget 类,并实现相应的绘图函数和消息处理,可以实现各种界面元素和控件,有了这些最基本的界面元素和控件,同时利用Qt 特有的“信号/槽”机制作为中间“通信”工具,不难构造出完整的程序界面[7]。

音乐播放控制模块是整个高保真音乐播放器的核心,利用Qt 自带的多线程处理机制,可以实现音乐播放与界面显示的隔离,不会产生界面冻结和卡死问题。

通过继承Qt 的QThread 线程类,并按程序需要完善其“run”函数,可以比较容易的实现多线程处理,例如音乐播放模块的“run”函数代码如下:

上述代码比较简单,就是按要播放的音乐格式,分别调用相应的处理函数,其中对于FLAC 格式的音乐,其播放处理函数“processFlacMusic”代码如下:

这段代码根据不同的播放状态进行处理的过程:在播放状态时不断解码;在暂停状态时不进行解码,并使线程睡眠;在停止状态时复位flac 解码器对象并返回,结束播放线程。对于WAV 格式和APE格式音乐的播放处理完全类似,不再赘述。

音频解码模块是音乐播放模块的基础,能对FLAC 格式和APE 格式音乐进行顺序解码以及随机位置解码,并将解码后的音频采样数据返回给音乐播放模块。顺序解码满足正常的音乐播放功能,随机位置解码可以满足播放进度调节功能。此外,解码模块可以获得音频文件的参数信息(采样率、采样位数、声道数等)和专辑信息(专辑名称、歌手、流派、发行时间等)。播放模块会根据参数信息对声卡设备进行设置,否则音乐无法正确播放,而专辑信息则可以以图文并茂的方式呈现给用户,提升用户体验。

系统设置和服务模块是为了系统的完整性而存在的。由于整个系统运行时只有高保真音乐播放器作为前台程序运行,必须提供必要的关机和时间日期设置功能。同时,为了使程序更加人性化,还提供了时间日期显示功能和关闭屏幕功能。作为嵌入式应用,功耗是重要的设计问题,就整个硬件系统而言,屏幕的功耗占了整个系统功耗的相当一部分,如果在用户不需要查看屏幕时,将屏幕关闭,可有效降低系统功耗。

4 系统验证

在完成系统设计的硬件和软件工作目标后,对该嵌入式高保真无损音乐播放器进行试听验证。对于16 bit或24 bit 采样位数,采样频率上限为48 kHz 的无损高保真音乐均可顺利播放。用户界面操作流畅,没有崩溃或卡死现象发生。播放器顺利加载1TB 移动硬盘中的1600 首无损高保真音乐。

5 结束语

基于ARM11 开发板和嵌入式Linux 内核,本文给出了一个界面美观,功能齐全的高保真音乐播放器设计,实现了WAV、FLAC、APE 三种无损格式高保真音乐的播放,提升了嵌入式系统音乐播放的视听感受。限于S3C6410 芯片的AC'97 音频控制模块最高只支持48 kHz 采样频率的音频,所以造成了高保真无损音乐播放的采样率瓶颈。可以考虑使用S3C6410 芯片的IIS 音频接口(采样位数支持8/16/24 bit,采样率支持从8 kHz 到192 kHz),外接高品质音频解码芯片[8]的方案,获得更好的高保真无损音乐播放体验。

[1]郁峰.基于嵌入式文件系统的MP3 播放器的设计和实现[D].苏州:苏州大学,2009.

[2]於少峰,严菊明,胡晨.基于AC97 标准的嵌入式音频系统设计与实现[J].电子器件,2004,27(4):733-736.

[3]焦正才,樊文侠.基于Qt/Embedded 的MP3 音乐播放器的设计与实现[J].电子设计工程,2012,20(7):148-150.

[4]Theory of Monkey's Audio[online].http://www.monkeysaudio.com/theory.html.

[5]李彬.基于应用程序的嵌入式Linux 内核自动裁剪[D].东南大学:计算机应用专业,2006.

[6]查婧,刘波,曹剑中.Linux 内核在S3C2440 上移植的方法[J].电子器件,2009,32(4):844-845.

[7]Jasmine Blancehette,Mark Summerfield.C++GUI QT4 programming(The second Edition)[M].2004:36-68.

[8]章坚武,董平,马勇.一种嵌入式多媒体播放器的硬件设计与实现[J].电子器件,2006,29(4):1123-1125.

猜你喜欢

高保真开发板播放器
Walkman诞生40周年 索尼适时发布NW-ZX500和NW-A100系列播放器
基于STM32的MP3播放器设计
Moon ACE播放器/放大器一体机
Symmetries in the Sem iosphere:A Typology
电视媒体“走转改”如何做到“高保真”
浅析单片机开发板的设计与制作
高保真色彩管理应用技术综述
利用 PixelGrid 软件实现航空影像高保真高效率DSM 的生产
ARM宣布mbed Enabled Freescale FRDM—K64F开发板通过微软认证
播放器背板注塑模具设计