音频驱动的3种模式
音频驱动有3种模式:1.MDD/PDD模式.2.Wavedev2模式.3.UAM模式
它们相同的地方很明显:它们公开相同的接口,因为是流驱动!都是透过流接口与上层的waveapi.dll交互.接着,细说它们的差异:
第一种MDD/PDD模式是最早被提供的模式,也是其他驱动常见分层模式.如果我们使用CE提供的MDD(wavemdd.lib)我们会受到一些限制:
Only supports one device ( waveOutGetNumDevs always returns 1)
Only supports one stream per device
No reliable support for looping
Poor support for streaming
当然,源码是提供的,你可以自己修改MDD突破这些限制.
第二种Wavedev2模式是因为2000年的Smartphone项目产生了新的要求,这些需求需要大改MDD/PDD.比如,我们看看上面的限制Only supports one stream per device.根据ce开发历史,此时,waveapi.dll也不支持software mixer.这岂不是说只能同时只能允许一个应用在播放?所以,根据当时情况,ce的多媒体开发团队设计了Wavedev2这个模式.这是一个单体的(不分层)的驱动模式.平台相关的模块都在hwctxt.h和hwctxt.cpp中.此外,还加入了midi支持,software mixer,支持S/PDIF接口,增加'gain class'接口,增加'forcespeaker'接口等等.因此,开发Smartphone或者PPC,这个模式是挺适合的.
第三:统一音频模型(Unified Audio Model)根据历史,在开发WinCE4.2时候,要增加对DirectSound的支持,而且有一些音频设备是支持硬件mixer的,对此,使用UAM是很好的选择.
细说'gain class'
智能手机Smartphone有一种情况不得不被考虑,就是在播放音乐的时候,突然收到来电.在播放来电和通话过程中,要求应用程序调整音量或者静音.显而易见的办法是让所有应用程序去适应这种情况,自行调整音量.但这是好办法吗?肯定不是.
应用程序控制音量是通过waveOutSetVolume这个api.如果第一个参数是DeviceID,那么改变整个设备的音量,如果第一个参数是waveOutOpen返回的handler,那么只是改变这个音频流的音量.
Wavedev2提出了gain class这样的机制.首先,每一个音频流都要自己独立的音量控制,其次就是将音频流进行分类.然后对每一类音频流音量进行统一控制.在Wavedev2中大概分成4种类型:0,1,2,3.普通的应用程序播放都属于默认的0类型.这一类型的音频流在通话过程中被静音.像报警,通话中再次来电通知这些音频属于第2类型.在通话过程中仍然能够播放.而且不受系统音量的影响.应用程序如何把自己注册成为第2类型?
waveOutOpen(&hWaveOut, ...);
...
// Set gain class to 2
waveOutMessage(hWaveOut, MM_WOM_SETSECONDARYGAINCLASS, 2, 0);
细说'ForceSpeaker'
强制选择音频流输出设备为系统speaker.为什么要这个功能?因为Smartphone除了自带一个喇叭,一般还有耳机接口.插上耳机后,所有的音频流都通过耳机发声,但是对于来电通知,以及设备掉电,低电通知等等这样的音频流,更好的选择是通过系统的喇叭发声;况且,有时候,用户插上了耳机,却没有带上耳机这样的情况也会发生.
于是,ce的开发组在Wavedev2上加入了这样的机制.它定义了一个消息MM_WOM_FORCESPEAKER,上层应用程序使用
waveOutMessage(<DeviceID|hWaveOut>,MM_WOM_FORCESPEAKER, bSpeaker, 0)来通知驱动,这个音频流应该通过系统喇叭来发出.