WINCE声音驱动模型概述
2010-05-18 09:59
295 查看
1.1 WINCE的声音模型
标准的WINDOWS CE下的声音处理模型。
1) 声音应用在使用WAVE接口函数的时候被COREDLL模块分了类:如果是简单的PCM数据,则直接进入ADM模块,进行SoftWare Mixer或者连Mixer也省了,直接调用Driver放音;如果是压缩模式的数据则进入ACM模块进行解压处理后(比如:GSM/G7XX等等…)再次进入ADM模块。 此外,如果DRIVER支持硬件的Mixer,则应用层直接Bypass掉ACM和ADM,直接进入到驱动进行软件或者硬件进行混音和放音。
2) ACM、Software Mixer都是可选配单元,可以通过注册表或者CE内核配置参数添加或者删除。
1.2 WINCE的声音驱动模型
l 分层模型
这是一个标准的分层 MDD-PDD 流式接口模型。 应用层的WAVEAPI都使用WaveAPI Manager(WaveApi.DLL)通过DeviceIOControl映射成为WAV_IOControl函数进行处理。
MDD层是微软的标准实现,通过DDSI (device driver service-provider interface )和PDD层实现进行连接。MDD通过消息来通知PDD层(PDD_WaveProc处理)
MDD层接口函数
· WAV_Close
· WAV_Deinit
· WAV_Init
· WAV_IOControl
· WAV_Open
· WAV_PowerDown
· WAV_PowerUp
· WAV_Read
· WAV_Seek
· WAV_Write
DDSI接口函数
· PDD_AudioDeinitialize
· PDD_AudioGetInterruptType
· PDD_AudioInitialize
· PDD_AudioMessage
· PDD_AudioPowerHandler
· PDD_WaveProc
但是分层模型也有一定的限制
· 只支持一个设备
· 不支持多个流
· 对循环支持的不好
· 对多个流数据支持的不是很好
l 单片模型
对于单片模型,WINCE是希望过渡到这个方案上的。该模型下,驱动的移植
还是很简单的。同时,该模型也客服了以前只能通过内核的MIXER来支持多个流的局限,在驱动层面即支持输入和输出多个流的混音操作。
l 分层模型的基本运转
分层模型支持同时放音和录音操作。MDD层管理着一个中断处理程序和多个
DMA BUFFERS,一般放音和录音都使用双DMA 缓冲。
比如,放音的时候,应用通过WAVEAPI传递过来一些数据,MDD层通过 PDD_WaveProc 函数发送 WPDM_START消息给PDD,PDD层将数据拷贝到DMA缓冲,并启动硬件放音。当DMA完成一个BUFFER的数据传送后,会产生一个硬件中断,PDD层会设定一个 AUDIO_STATE_OUT_PLAYING标志 。如果MDD发现有更多的数据要传送就会通过WPDM_CONTINUE.消息让PDD层继续负责填充DMA缓冲,否则就发送一个WPDM_ENDOFDATA.消息让PDD层停止DMA。
WINCE WAVE接口模型详解
1、标准的WAVE流式驱动程序接口
WAVE的驱动程序提供标准的流式接口给高层,但真正产生关键作用的是
WAV_IOControl这个函数。该函数的以下两个参数最重要:
dwCode
具体的IO控制命令,包括:
IOCTL_WAV_MESSAGE (处理放音和录音相关的所有操作)
IOCTL_DSDVR_MESSAGE (DirectSound 动作处理)
IOCTL_MIX_MESSAGE. (MIXER的操作)
pBufIn
指向了MMDRV_MESSAGE_PARAMS结构,该结构如下:
Struct {
UINT uDeviceId;
UINT uMsg;
DWORD dwUser;
DWORD dwParam1;
DWORD dwParam2;
}MMDRV_MESSAGE_PARAMS;
uDeviceId: 0,1,2 。。。 如果是0代表全局或者缺省的设备
uMsg :用作(WIDM_*),(WODM_*), (MXDM_*)三种消息
dwUser:实例的具体标识
通过这个函数传递的高层命令,最终导致驱动的具体动作,放音、录音或者混音。
2、关键的数据结构
WAVE OPEN时候使用的数据结构:
WAVEFORMATEX{
WORD wFormatTag;
WORD wChannels;
DWORD nSamplesPerSec;
DWORD nAvgBytesPerSec;
WORD nBlockAlign;
WORD nBitsPerSample;
WORD cbSize;
}
该数据结构定义了一个Audio Stream所需要的大部分信息,当做WAVE OPEN的时候可能应用可能会首先尝试打开,这个时候WAVE_IO_CONTROL 就会传递一个WAVE_FORMAT_QUERY 给驱动,而驱动只是简单的检查是否真正的支持请求的格式,而不真正打开设备。
每次应用添加声音数据的时候会使用如下数据结构:
Struct {
LPSTR lpData;
DWORD dwBufferLength;
DWORD dwBytesRecorded;
DWORD dwUser;
DWORD dwFlags;
DWORD dwLoops;
Struct wavehdr_tag *lpNext;
DWORD Reserved;
}
其中dwFlags定义了几个标志:
WHDR_BEGINLOOP :指明这个BUFFER是否要求被自动重放 (APP设)
WHDR_DONE :指明这个BUFFER已经处理完毕(驱动设)
WHDR_ENDLOOP :指明这个BUFFER是否结束重放(APP设)
WHDR_INQUEUE :指明这个BUFFER入队列(驱动设)
WHDR_PREPARED:指明这个BUFFER的确准备好(APP或驱动设)
这几个标志是应用和驱动通信的关键,也是对队列操作的关键。应用和驱动通过设定这些标志位,让数据不断在驱动和应用之间流动,从而完成录放的各种操作。当然,这个过程还要配合一些WAVE 消息。
放音的消息解析
WINCE的声音驱动模型在放音的工作中定义了21个消息(懒了,不再列举了),但在具体实现中并不是每个消息都必须实现。
消息很多,特别是在具体实现中需要和DMA操作模型配合使用,因此理解消息的用途和推敲它们之间的关系就显得格外重要了!
通过仔细推敲它们之间的关系,我们可以将放音的整个过程规划成如下一些状态,并用状态迁移图来理解消息的使用,整个过程的操作就非常简单了。
混音的处理
如果要WINDOWS CE的声音驱动模型支持混音,则要考虑如下问题:
1) 声音设备是否支持硬件混音
2) 声音设备需要工作在同一种采样频率下
3) 声音设备要能够同时支持录音和放音操作
而声音的驱动要负责完成声音采集的混音和声音放音的混音。其基本原理如下:
1) 将声音设备设定在一个频率下,比如:44.1KHZ,16BIT
2) 驱动允许打开多个音频流,每个音频流可以允许不同的采样率,比如: (A:8KHZ,8BIT B: 44.1KHZ,16BIT)
3) 放音的混音在最后的数据准备阶段(即放入到DMA前),用合成算法将所有的流进行数学运算,得出声音设备采样频率下(44.1KHZ,16BIT)的数据。数据通过DMA发送到CODEC中。
4) 录音的混音操作,都是从声音设备采样频率下(44.1KHZ,16BIT)下得到采样的基本数据,然后通过数学运算分配到不同的频率下的音频流上。
5) 要注意的就是合成的时候要注意数据不溢出;分开的时候要注意数据速率的匹配和数据宽度的匹配。
中断和DMA驱动模型
声音系统一般都使用DMA作为数据传输的基本手段,因此DMA的操作模型对于
声音子系统的处理有着特别关键的作用。DMA的声音操作一般都是用双BUFFER作为
数据缓冲(录和放)都如此,一个BUFFER在被DMA占用的时候,另一个BUFFER
就可以被CPU占用,从而提高效率。显而易见,声音子系统的硬件操作是一个典型的
生产者消费者模式,因此,对共享资源的控制就特别重要。
DMA的硬件实现,不同的CPU略有不同。有的嵌入式芯片做的简单,不支持DMA地址的链式连接,有的则支持,但不影响具体实现。他们相同的点是:
l 一般一个DMA有N个子CHANNEL
l 每一个CHANNEL都可以互不干扰的独立运转或者停机,自有一个状态机
l DMA使用一个总的DMA 中断通知CPU,然后由软件负责查找具体某个CHANNEL。
如果一个系统中很多驱动都需要用到DMA,那么就需要一个DMA ENGINE来总
协调DMA的运作,否则就会出现驱动争用DMA的问题。如果只有一个驱动使用DMA系统,则实现起来的障碍会小不少。
双声道系统中的声音驱动,DMA运作都是采用两个通道独立完成录、放的操作,并且每个通道都采用双BUFFER的策略,来保证DMA和CPU可以近乎同时的工作,互不影响。而且,一个在高层支持多个流的声音驱动也要注意对DMA这个硬件设备的操作要保持互斥。
在实际驱动的实现过程中,这种双通道、双BUFFER的驱动有很多细节要注意,要注意处理好几大类关系:
1) 硬件 DMA和硬件CODEC之间的关系
在整个放音声音数据传输系统中有:
APP buffer ßà DMA buffer ßà I2S(AC97) FIFO ßà CODEC
APP负责提供数据,DMA负责数据传输,其实就是要把数据搬运到类似I2S或者AC97间的FIFO中,I2S负责成帧传递数据,最后由CODEC还原。录音则反之。
一般来讲,I2S和CODEC要在DMA启动前准备好,而启动DMA和I2S的顺序,往往会导致一些数据的丢失,这是关注的一点。
2) DMA与APP buffer之间的关系
还原处理时: APP 往往提供很大的数据包,比如16K,而DMA由于设计的需要,一般取到4K,就比较大了。
启动DMA开始工作的条件是:
---填充完毕两个DMA BUFFER
---I2S准备好
当DMA完成搬运后,会产生DMA的中断,而在中断处理中,要注意一下问题:
---启动第二个BUFFER,继续让DMA工作,如果不能启动就要DMA停机了。
---CPU负责检查是否还有足够的数据给DMA,如果有,够填充几个DMA BUFFER
DMA停机的条件是:
---没有更多的BUFFER可供搬运
---强制停机
在实践过程中,要拿捏好DMA启动和停机的条件,因为驱动一般都是多线程运转的,一定要注意对DMA操作时的互斥,防止出现异常或者死锁。
另外,DMA BUFFER的大小,直接关系到采样的频率,对于一些实时应用很重要。比如:VOIP中需要20ms 的打包周期,就需要限制DMA BUFFER的大小,从而控制中断时间,及时为VOIP提供周期打包数据。
3) DMA多CHANNEL之间的关系
如果同时启动录音和放音CHANNEL,那么在DMA的中断处理中要注意区分是谁的数据,并且要及时启动各自CHANNEL的第二个BUFFER,防止采集数据丢失或者放音停顿。
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/cnhighway/archive/2009/05/15/4188016.aspx
标准的WINDOWS CE下的声音处理模型。
1) 声音应用在使用WAVE接口函数的时候被COREDLL模块分了类:如果是简单的PCM数据,则直接进入ADM模块,进行SoftWare Mixer或者连Mixer也省了,直接调用Driver放音;如果是压缩模式的数据则进入ACM模块进行解压处理后(比如:GSM/G7XX等等…)再次进入ADM模块。 此外,如果DRIVER支持硬件的Mixer,则应用层直接Bypass掉ACM和ADM,直接进入到驱动进行软件或者硬件进行混音和放音。
2) ACM、Software Mixer都是可选配单元,可以通过注册表或者CE内核配置参数添加或者删除。
1.2 WINCE的声音驱动模型
l 分层模型
这是一个标准的分层 MDD-PDD 流式接口模型。 应用层的WAVEAPI都使用WaveAPI Manager(WaveApi.DLL)通过DeviceIOControl映射成为WAV_IOControl函数进行处理。
MDD层是微软的标准实现,通过DDSI (device driver service-provider interface )和PDD层实现进行连接。MDD通过消息来通知PDD层(PDD_WaveProc处理)
MDD层接口函数
· WAV_Close
· WAV_Deinit
· WAV_Init
· WAV_IOControl
· WAV_Open
· WAV_PowerDown
· WAV_PowerUp
· WAV_Read
· WAV_Seek
· WAV_Write
DDSI接口函数
· PDD_AudioDeinitialize
· PDD_AudioGetInterruptType
· PDD_AudioInitialize
· PDD_AudioMessage
· PDD_AudioPowerHandler
· PDD_WaveProc
但是分层模型也有一定的限制
· 只支持一个设备
· 不支持多个流
· 对循环支持的不好
· 对多个流数据支持的不是很好
l 单片模型
对于单片模型,WINCE是希望过渡到这个方案上的。该模型下,驱动的移植
还是很简单的。同时,该模型也客服了以前只能通过内核的MIXER来支持多个流的局限,在驱动层面即支持输入和输出多个流的混音操作。
l 分层模型的基本运转
分层模型支持同时放音和录音操作。MDD层管理着一个中断处理程序和多个
DMA BUFFERS,一般放音和录音都使用双DMA 缓冲。
比如,放音的时候,应用通过WAVEAPI传递过来一些数据,MDD层通过 PDD_WaveProc 函数发送 WPDM_START消息给PDD,PDD层将数据拷贝到DMA缓冲,并启动硬件放音。当DMA完成一个BUFFER的数据传送后,会产生一个硬件中断,PDD层会设定一个 AUDIO_STATE_OUT_PLAYING标志 。如果MDD发现有更多的数据要传送就会通过WPDM_CONTINUE.消息让PDD层继续负责填充DMA缓冲,否则就发送一个WPDM_ENDOFDATA.消息让PDD层停止DMA。
WINCE WAVE接口模型详解
1、标准的WAVE流式驱动程序接口
WAVE的驱动程序提供标准的流式接口给高层,但真正产生关键作用的是
WAV_IOControl这个函数。该函数的以下两个参数最重要:
dwCode
具体的IO控制命令,包括:
IOCTL_WAV_MESSAGE (处理放音和录音相关的所有操作)
IOCTL_DSDVR_MESSAGE (DirectSound 动作处理)
IOCTL_MIX_MESSAGE. (MIXER的操作)
pBufIn
指向了MMDRV_MESSAGE_PARAMS结构,该结构如下:
Struct {
UINT uDeviceId;
UINT uMsg;
DWORD dwUser;
DWORD dwParam1;
DWORD dwParam2;
}MMDRV_MESSAGE_PARAMS;
uDeviceId: 0,1,2 。。。 如果是0代表全局或者缺省的设备
uMsg :用作(WIDM_*),(WODM_*), (MXDM_*)三种消息
dwUser:实例的具体标识
通过这个函数传递的高层命令,最终导致驱动的具体动作,放音、录音或者混音。
2、关键的数据结构
WAVE OPEN时候使用的数据结构:
WAVEFORMATEX{
WORD wFormatTag;
WORD wChannels;
DWORD nSamplesPerSec;
DWORD nAvgBytesPerSec;
WORD nBlockAlign;
WORD nBitsPerSample;
WORD cbSize;
}
该数据结构定义了一个Audio Stream所需要的大部分信息,当做WAVE OPEN的时候可能应用可能会首先尝试打开,这个时候WAVE_IO_CONTROL 就会传递一个WAVE_FORMAT_QUERY 给驱动,而驱动只是简单的检查是否真正的支持请求的格式,而不真正打开设备。
每次应用添加声音数据的时候会使用如下数据结构:
Struct {
LPSTR lpData;
DWORD dwBufferLength;
DWORD dwBytesRecorded;
DWORD dwUser;
DWORD dwFlags;
DWORD dwLoops;
Struct wavehdr_tag *lpNext;
DWORD Reserved;
}
其中dwFlags定义了几个标志:
WHDR_BEGINLOOP :指明这个BUFFER是否要求被自动重放 (APP设)
WHDR_DONE :指明这个BUFFER已经处理完毕(驱动设)
WHDR_ENDLOOP :指明这个BUFFER是否结束重放(APP设)
WHDR_INQUEUE :指明这个BUFFER入队列(驱动设)
WHDR_PREPARED:指明这个BUFFER的确准备好(APP或驱动设)
这几个标志是应用和驱动通信的关键,也是对队列操作的关键。应用和驱动通过设定这些标志位,让数据不断在驱动和应用之间流动,从而完成录放的各种操作。当然,这个过程还要配合一些WAVE 消息。
放音的消息解析
WINCE的声音驱动模型在放音的工作中定义了21个消息(懒了,不再列举了),但在具体实现中并不是每个消息都必须实现。
消息很多,特别是在具体实现中需要和DMA操作模型配合使用,因此理解消息的用途和推敲它们之间的关系就显得格外重要了!
通过仔细推敲它们之间的关系,我们可以将放音的整个过程规划成如下一些状态,并用状态迁移图来理解消息的使用,整个过程的操作就非常简单了。
混音的处理
如果要WINDOWS CE的声音驱动模型支持混音,则要考虑如下问题:
1) 声音设备是否支持硬件混音
2) 声音设备需要工作在同一种采样频率下
3) 声音设备要能够同时支持录音和放音操作
而声音的驱动要负责完成声音采集的混音和声音放音的混音。其基本原理如下:
1) 将声音设备设定在一个频率下,比如:44.1KHZ,16BIT
2) 驱动允许打开多个音频流,每个音频流可以允许不同的采样率,比如: (A:8KHZ,8BIT B: 44.1KHZ,16BIT)
3) 放音的混音在最后的数据准备阶段(即放入到DMA前),用合成算法将所有的流进行数学运算,得出声音设备采样频率下(44.1KHZ,16BIT)的数据。数据通过DMA发送到CODEC中。
4) 录音的混音操作,都是从声音设备采样频率下(44.1KHZ,16BIT)下得到采样的基本数据,然后通过数学运算分配到不同的频率下的音频流上。
5) 要注意的就是合成的时候要注意数据不溢出;分开的时候要注意数据速率的匹配和数据宽度的匹配。
中断和DMA驱动模型
声音系统一般都使用DMA作为数据传输的基本手段,因此DMA的操作模型对于
声音子系统的处理有着特别关键的作用。DMA的声音操作一般都是用双BUFFER作为
数据缓冲(录和放)都如此,一个BUFFER在被DMA占用的时候,另一个BUFFER
就可以被CPU占用,从而提高效率。显而易见,声音子系统的硬件操作是一个典型的
生产者消费者模式,因此,对共享资源的控制就特别重要。
DMA的硬件实现,不同的CPU略有不同。有的嵌入式芯片做的简单,不支持DMA地址的链式连接,有的则支持,但不影响具体实现。他们相同的点是:
l 一般一个DMA有N个子CHANNEL
l 每一个CHANNEL都可以互不干扰的独立运转或者停机,自有一个状态机
l DMA使用一个总的DMA 中断通知CPU,然后由软件负责查找具体某个CHANNEL。
如果一个系统中很多驱动都需要用到DMA,那么就需要一个DMA ENGINE来总
协调DMA的运作,否则就会出现驱动争用DMA的问题。如果只有一个驱动使用DMA系统,则实现起来的障碍会小不少。
双声道系统中的声音驱动,DMA运作都是采用两个通道独立完成录、放的操作,并且每个通道都采用双BUFFER的策略,来保证DMA和CPU可以近乎同时的工作,互不影响。而且,一个在高层支持多个流的声音驱动也要注意对DMA这个硬件设备的操作要保持互斥。
在实际驱动的实现过程中,这种双通道、双BUFFER的驱动有很多细节要注意,要注意处理好几大类关系:
1) 硬件 DMA和硬件CODEC之间的关系
在整个放音声音数据传输系统中有:
APP buffer ßà DMA buffer ßà I2S(AC97) FIFO ßà CODEC
APP负责提供数据,DMA负责数据传输,其实就是要把数据搬运到类似I2S或者AC97间的FIFO中,I2S负责成帧传递数据,最后由CODEC还原。录音则反之。
一般来讲,I2S和CODEC要在DMA启动前准备好,而启动DMA和I2S的顺序,往往会导致一些数据的丢失,这是关注的一点。
2) DMA与APP buffer之间的关系
还原处理时: APP 往往提供很大的数据包,比如16K,而DMA由于设计的需要,一般取到4K,就比较大了。
启动DMA开始工作的条件是:
---填充完毕两个DMA BUFFER
---I2S准备好
当DMA完成搬运后,会产生DMA的中断,而在中断处理中,要注意一下问题:
---启动第二个BUFFER,继续让DMA工作,如果不能启动就要DMA停机了。
---CPU负责检查是否还有足够的数据给DMA,如果有,够填充几个DMA BUFFER
DMA停机的条件是:
---没有更多的BUFFER可供搬运
---强制停机
在实践过程中,要拿捏好DMA启动和停机的条件,因为驱动一般都是多线程运转的,一定要注意对DMA操作时的互斥,防止出现异常或者死锁。
另外,DMA BUFFER的大小,直接关系到采样的频率,对于一些实时应用很重要。比如:VOIP中需要20ms 的打包周期,就需要限制DMA BUFFER的大小,从而控制中断时间,及时为VOIP提供周期打包数据。
3) DMA多CHANNEL之间的关系
如果同时启动录音和放音CHANNEL,那么在DMA的中断处理中要注意区分是谁的数据,并且要及时启动各自CHANNEL的第二个BUFFER,防止采集数据丢失或者放音停顿。
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/cnhighway/archive/2009/05/15/4188016.aspx
相关文章推荐
- WINCE声音驱动模型概述
- WINCE声音驱动模型概述(1)
- WINCE声音驱动模型概述(2)--WINCE WAVE接口模型详解
- WINCE声音驱动模型概述 - 4
- WINCE声音驱动模型概述(3)--放音的消息解析
- WINCE声音驱动模型概述 - 3
- WINCE声音驱动模型概述(4)
- WINCE声音驱动模型概述 - 2
- WINCE声音驱动模型概述 - 1
- 领域模型驱动设计(Domain Driven Design)入门概述
- 领域模型驱动设计(Domain Driven Design)入门概述
- WinCE驱动模型
- WINCE 音频驱动之二:驱动模型
- 领域模型驱动设计(Domain Driven Design)入门概述 -----DDD 解释
- 领域模型驱动设计(Domain Driven Design)入门概述
- WINCE 音频驱动之二:驱动模型
- 使用 Rational Software Architect 进行模型驱动和基于模式的开发,第 1 部分: 使用模式的模型驱动开发范例的概述
- Freescale WINCE 6.0休眠唤醒后声音消失,原因居然是驱动线程优先级不够
- ALSA概述--高级linux声音驱动基本介绍和应用
- 领域模型驱动设计(Domain Driven Design)入门概述