Waveform Audio 驱动(Wavedev2)之:WAV API模拟
来源:互联网 发布:淘宝衣服卖点模板 编辑:程序博客网 时间:2024/05/12 21:45
http://blog.csdn.net/guopeixin/article/details/5613943
Waveform Audio 驱动(Wavedev2)之:WAV API模拟
Waveform 驱动对Windows Mobile来说是一个非常重要的驱动,控制着所有有关声音的操作,包括喇叭、耳机、麦克、听筒等。
要想对驱动的整个架构和流程都非常的了解,我们必须从上层来入手,需要知道上层的API是如何调用到驱动的,其数据结构是如何封装的。由于微软不提供中间层的代码,只能只是自己去猜测。这篇文章就是去模仿WAV API的实现方法的。顺便提及下,之前几个开发人员还讨论过微软的半开放模式和Android的完全开源模式哪个更好。先做个总结。
完全开源优点:
1. 添加新功能容易:比如做Android双卡双待就比Windows Mobile容易的多,之前做Windows Mobile双卡的项目时,那真是非常的痛苦,微软没有接口,只能自己想尽一起方法往微软原有的程序中去插入新的功能,想COM接口,Dll注入,窗口Hook等等,能用的变态方法都用上了。花的时间的很大部分都是在寻找插入功能的方法上,而不是实现另一张卡的功能上。而Android就十分简单了,直接在原有的代码上增加代码就行。
2. 开发人员很容易了解整个架构和流程
微软的半开放模式优点:
1. 易维护: 由于微软的中间层都是以dll形式封装好的,开发人员不能去修改,只能按照微软的接口去做,当微软从Windows Mobile 5.0升级到 Windows Mobile 6.0的时候,BSP不需要做任何修改就可以在新的系统上用,软件也是如此。而Android的完全开源模式,开发人员会去修改中间层,Android的版本号从1.5,1.6,2.0再到2.1,不断的进行升级,其中间层也在改变中,添加了某些功能,优化了某些部分。像我们公司做Android的从1.5升级到1.6就花了很长的时间。不仅驱动要修改,应用也都需要做修改。
先不谈这个,回到正题。
微软上层的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.
表一:WaveOut部分函数
Wave Out API是如何调用的驱动部分的呢?现在就来一步步的模拟来实现wave Out API。先看下waveOutOpen的函数参数
其中phwo是我们要返回的WAVEOUT对象的句柄,uDeviceID指设置的ID号,一般情况下设置为0就可以,pwfx是声音格式的描述,dwCallback的通知,可以是回调函数,也可以是事件或者窗体消息,主要通过fdwOpen来指定其类型。具体看waveOutOpen的SDK帮助文档。
在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 这个函数实现的。
好了,现在我们来开始显示吧。HWAVEOUT要么直接指向对象,要么是对象的在数组中的索引。我们只是模拟,所以把HWAVEOUT 直接指向对象。
先定义一个CWAVEOut对象,来保存必要的数据,其他几个参数就不做解释了,我们看m_hWave和m_pStream,m_hWave是来保存打开Wave驱动CreateFile返回的句柄,而m_pStream是保存创建的StreamContext对象的。
好,现在我们来模拟waveOutOpen的实现。在waveOutOpen中,只是新建一个CWAVEOut对象,然后把外部传入的数据保存到这个对象中,最后调用open来打开音频设备。代码如下:
Open函数封装WAVEOPENDESC作为waveOutMessage的第一个传入参数,第二个参数是m_fdwOpen。
waveOutMessage的工作就是只要把uMsg,dw1,dw2封装到MMDRV_MESSAGE_PARAMS结构体,然后调用DeviceIoControl调用驱动的IO Control。这里有一点需要注意,如果uMsg是WODM_OPEN,也就是打开音频流的操作的时候,把& pWaveOut-> m_pStream 作为参数传入,因为在底层通过调用 OpenStream,传入指针的指针,来保存对象的。
pDeviceContext->OpenStream((LPWAVEOPENDESC)dwParam1, dwParam2, (StreamContext **)dwUser);
我们现在模拟实现了waveOutMessage,那么其他一些函数的实现要比waveOutOpen更加的简单。如WaveOutReset和waveOutSetVolume,只要调用下waveOutMessage就可以了。
对于上层来说,只是简单的进行了下封装。当然我的封装里面还没有考虑到具体的一些东西,如callback函数是怎么返回的,如函数调用是hwo为空,是怎么样的,也没有对错误进行处理。
下面是播放一个wave声音的函数,从代码中去解析
先调用waveOutOpen初始化音频流。在调用waveOutPrepareHeader准备好数据头,告诉驱动要播放多大的数据,在驱动中waveOutPrepareHeader 调用 WODM_PREPARE 分支,一般情况下驱动没有去实现WODM_PREPARE,直接返回MMSYSERR_NOTSUPPORTED 。准备好Header后,调用waveOutWrite写出buffer。
好了,就写到这里,如有错误之处,请更正。
- Waveform Audio 驱动(Wavedev2)之:WAV API模拟
- Waveform Audio 驱动(Wavedev2)之:WAV API模拟
- Waveform Audio 驱动(Wavedev2)之:WAV API模拟
- Waveform Audio 驱动(Wavedev2)之:WAV API模拟
- Waveform Audio 驱动(Wavedev2)之:WAV API模拟
- Waveform Audio 驱动(Wavedev2)之:WAV 驱动解析
- Waveform Audio 驱动(Wavedev2)之:WAV 驱动解析
- Waveform Audio 驱动(Wavedev2)之:WAV 驱动解析
- Waveform Audio 驱动(Wavedev2)之:WAV 驱动解析
- Waveform Audio 驱动(Wavedev2)之:WAV 驱动解析
- Waveform Audio 驱动(Wavedev2)之:WAV 驱动解析
- Waveform Audio
- Managing Waveform-Audio Recording
- Waveform Audio[译]
- Waveform Audio[译]
- Waveform Audio[译]
- Recording with a Waveform-Audio Device
- recording and play using Waveform audio interface
- Python 过滤列表
- 高级进阶DB2(第2版)——内部结构、高级管理与问题诊断
- 跟Google学习Android开发-起始篇-用碎片构建一个动态的用户界面(4)
- Android ---Check System Version at Runtime(在软件运行时检查判断系统版本)
- Android排错:has leaked window com.android.internal.policy.impl.PhoneWindow$ that was originally added
- Waveform Audio 驱动(Wavedev2)之:WAV API模拟
- python解决乱码问题
- 波士顿矩阵的局限
- AS3有效组件库
- JS修改css样式style浅谈(转)
- struts2的配置和使用
- springMvc,Mybatis,velocity 的整合
- iOS 在自己的app中控制系统的 屏幕亮度
- Source Insight 常用设置和快捷键大全