CE目前有3种音频模式:MDD/PDD、WaveDev2和UAM。这些模式的存在是有历史原因的,它们的功能有些许不同。下面具体说明一下。
首先,这3个模式是使用同一套WaveAPI的驱动接口。在系统中以驱动形式存在,都会导出WAV_Open、WAV_Close等接口。通过IoControl带入IOCTL_WAV_MESSAGE,与waveapi的子系统配合使用。对下是控制硬件。它们不同之处在于内部的设计。
MDD/PDD:
CE的旧驱动模型,也是最常用的模式。MDD/PDD把驱动分成2块,sort-of hardware independent的MDD层和really hardware dependent的PDD层。MDD部分是通用的、公开出来的(public/COMMON/oak/drivers/wavedev/mdd),生成wavemdd.lib的库。PDD必须是OEM自己编写的(public/COMMON/oak/drivers/wavedev/pdd)。这2部分静态的链接起来,才形成一个完整的驱动。PDD和MDD之间的接口,定义在public/common/oak/inc/waveddsi.h。
Waveapi驱动已经把硬件依赖关系给分割开来。MDD和PDD把驱动分成硬件相关的和硬件无关的。为了把驱动分割成硬件无关的,MDD层要设想好硬件的工作流程和功能。
下面是MDD和PDD需要设定的内容:
1、 只有一个设备(waveOutGetNumDevs始终返回1)
2、 每个设备只有1个流(1个输入流和1个输出流)。Waveapi包含了一个软件混音器(software mixer),在应用层把多个流合并成一个流。
3、 输入输出DMA共享一个中断
由此,此模式把PDD层大大简化了,使得音频设备比较容易的被移植和更改。但如果你的设备是比较特殊的,或者需要添加特别的功能,那就需要自己修改MDD的代码。这可能与此模式的接口设计有较大冲突,需要做的比较复杂。
WaveDev2:
2000年开始smartphone开发时候,增添了对音频的许多需求,而MDD/PDD模式不能不做改动。在CE 3.0时候,还没有waveapi的软件混音提供,不可以同时播放多个音乐。那就需要一个新的设计,WaveDev2诞生了。
WaveDev2的所有文件都在一个目录下。移植WaveDev2驱动,只需要把样例的所有文件复制过来,再进行修改就可以了。主要修改hwctxt.h和hwctxt.cpp。这样会有助于OEM的修改,不需要考虑多个目录多个文件的改动。
CE6发布时候带有WaveDev2的样例(public/common/oak/drivers/wavedev/wavedev2/ensoniq)
最新的WaveDev2驱动有以下新特性:
1、 MIDI合成器。手机上需要播放MIDI音乐。
2、 输入输出流的采样率转换。驱动可以把多个不同采样率的输出流,合并成一个流。也可以把一个输入流,分成多个应用程序需要的采样率输入流(这个应用比较特殊,很少见)。
3、 Gain class接口。每个输出流都有自己的class(音量),当应用创建一个新的流时候,它的class是0。应用可以通过waveOutMessage让驱动改变流的class,系统可以通过不同的waveOutMessage来控制每个class的音量等级。这接口让shell做静音等功能,如电话进来时候,后天播放的音乐要静音。
4、 Forcespeaker,shell可以让设备即使没有打开免提,也能强行在speaker输出声音。主要是电话进来时候,让speaker播放铃声。
5、 支持S/PDIF接口,让WMAPro流通过S/PDIF进行压缩。
如果是开发一个电话设备,最好使用WaveDev2的模式,系统需要依赖WaveDev2的扩展功能。如果是CE设备,也能通过WaveDev2做一些新功能。
UAM:
CE 4.2开始,需要为新增的DirectSound提供驱动。设计手机功能时,MDD/PDD模式已经做了许多改动。新的设计会利用WaveDev2的一部分改变,增加了使用硬件来混合2个音频流。虽然UAM和WaveDev2看起来差不多,实际内部设计上还是有许多差别的。
但是真正使用硬件做混音的需求,是在太少。所以在CE5上,DirectSound才被加入。这个设计并不是很有价值,因此许多OEM还是使用以前的音频驱动设计。