MS的Wave Driver也同样采用了分层结构,应用程序开发人员可以通过调用Wave API来操作声音驱动,下面以一个API为例来简单了解一下Wave驱动。
Wave API也有几个层面,分别如下:
>> 最上层的API:sndPlaySound or PlaySound,其实操作的是默认设备Device0
>> 中间层的API:当需要指定特定的设备的时候,可以使用下面的API来播放音频数据:WaveOutOpen, WaveOutPrepareHeader, WaveOutWrite, WaveOutClose, and others. Setting uDeviceID of WaveOutOpen
更近一步的来说,微软上层的WAV API分为waveOut和waveIn两套,表一中,我只列了部分的wave out API。由于wave In相对于wave Out比较简单,wave In就不做讲解了。
waveOutGetNumDevs |
Retrieves the number of waveform output devices present in the system. |
waveOutGetPitch |
Queries the current pitch setting of a waveform output device. |
waveOutGetPlaybackRate |
Queries the current playback rate setting of a waveform output device. |
waveOutGetPosition |
Retrieves the current playback position of the specified waveform output device. |
waveOutGetProperty |
Queries the value of a specific property in a property set for waveform audio output. |
waveOutGetVolume |
Queries the current volume setting of a waveform output device. |
waveOutMessage |
Sends messages to the waveform output device drivers. |
waveOutOpen |
Opens a specified waveform output device for playback. |
下面以中间层的一个API-WaveOutOpen来简单的描述一下驱动中间的部分处理过程:
在WaveApi中的工作就是把waveOutOpen中的参数封装起来,然后发到Wave驱动中想要的结构,下面是waveOutOpen的调用流程。
1. W ave Api中封装结构
2. 调用Wavedev2的 WAV_IOControl 函数,调用 IOCTL_WAV_MESSAGE 分支。
3. 调用 HandleWaveMessage 的 WODM_OPEN 分支
HandleWaveMessage 需要传入两个参数,其中一个是 PMMDRV_MESSAGE_PARAMS ,另一个是函数执行的结果pdwResult,见 HandleWaveMessage 原型和 MMDRV_MESSAGE_PARAMS 结构体定义。
BOOL HandleWaveMessage(PMMDRV_MESSAGE_PARAMS pParams, DWORD *pdwResult)
其 中参数dwUser指向Wavedev2驱动的StreamContext对象指针,如果调用的是waveOutOpen,则dwUser做出传出参数, 来保存StreamContext对象,否则就是作为传入参数。waveOutMessage的uMsg会传入驱动变成 MDRV_MESSAGE_PARAMS 中的uMsg, 同样的dw1变dwParam1,dw2变dwParam2,所以的上层调用都是调用 waveOutMessage 这个函数实现的。