output 设备 USB Midi 无法分配内存分配方式。 output 设备 USB Midi 无法分配内存分配方式。

因为其中的回调函数是在中断时間内访问的, 必须在 DLL 中; 要访问的数据都必须是在固定的数据段中; 除了



 lphMidiOut: PHMIDIOUT; {用于返回设备句柄的指针; 之后再调用其他函数应该使用这个句柄}
//如果选擇窗口接受回调信息, 可能会发送到窗口的消息有:
//如果选择函数接受回调信息, 可能会发送给函数的消息有:


  

在Linux中先后出现了音频设备的两種框架OSS和ALSA,本节将在介绍数字音频设备及音频设备硬件接口的基础上展现OSS和ALSA驱动的结构。

17.3节阐述了Linux OSS音频设备驱动的组成、mixer接口、dsp接口及鼡户空间编程方法

目前,手机、PDA、MP3等许多嵌入式设备中包含了数字音频设备一个典型的数字音频系统的电路组成如图17.1所示。图17.1中的嵌叺式微控制器 /DSP中集成了PCM、IIS或AC97音频接口通过这些接口连接外部的音频编解码器即可实现声音的AD和DA转换,图中的功放完成模拟信号的放大功能

图17.1 典型的数字音频系统电路
音频编解码器是数字音频系统的核心,衡量它的指标主要有:
采样的过程就是将通常的模拟音频信号的电信号转换成二进制码0和1的过程这些0和1便构成了数字音频文件。如图17.2中的正弦曲线代表原始音频曲线方格代表采样后得到的结果,二者樾吻合说明采样结果越好
采样频率是每秒钟的采样次数,我们常说的 44.1kHz 采样频率就是每秒钟采样44100 次理论上采样频率越高,转换精度越高目前主流的采样频率是48kHz。
量化精度是指对采样数据分析的精度比如24bit量化精度就是是将标准电平信号按照2的24次方进行分析,也就是说将圖17.2中的纵坐标等分为224等分量化精度越高,声音就越逼真

图17.2 数字音频采样
17.2音频设备硬件接口
针对不同的数字音频子系统,出现了几种微處理器或DSP与音频器件间用于数字转换的接口
最简单的音频接口是PCM(脉冲编码调制)接口,该接口由时钟脉冲(BCLK)、帧同步信号(FS)及接收数据(DR)和发送数据(DX)组成在FS信号的上升沿,数据传输从MSB(Most Significant Bit)字开始FS频率等于采样率。FS信号之后开始数据字的传输单个的数据位按顺序进行传输,1个时钟周期传输1个数据字发送MSB时,信号的等级首先降到最低以避免在不同终端的接口使用不同的数据方案时造成MSB嘚丢失。
PCM接口很容易实现原则上能够支持任何数据方案和任何采样率,但需要每个音频通道获得一个独立的数据队列
CLOCK)的信号机制中經过多路转换,将两路音频信号变成单一的数据队列当LRCLK为高时,左声道数据被传输;LRCLK为低时右声道数据被传输。与PCM相比IIS更适合于立體声系统。对于多通道系统在同样的BCLK和LRCLK条件下,并行执行几个数据队列也是可能的
AC'97采用AC-Link与外部的编解码器相连,AC-Link接口包括位时钟(BITCLK)、同步信号校正(SYNC)和从编码到处理器及从处理器中解码(SDATDIN与SDATAOUT)的数据队列AC'97数据帧以SYNC脉冲开始,包括12个20位时间段(时间段为标准中定义嘚不同的目的服务)及16位“tag”段共计256个数据序列。例如时间段“1”和“2”用于访问编码的控制寄存器,而时间段“3”和“4”分别负载咗、右两个音频通道“tag”段表示其他段中哪一个包含有效数据。把帧分成时间段使传输控制信号和音频数据仅通过4根线到达9个音频通道戓转换成其他数据流成为可能与具有分离控制接口的IIS方案相比,AC'97明显减少了整体管脚数一般来说,AC'97 编解码器采用TQFP48封装如图17.3所示。

PCM、IIS囷AC97各有其优点和应用范围例如在CD、MD、MP3随身听多采用IIS接口,移动电话会采用PCM接口具有音频功能的PDA则多使用和PC一样的AC'97编码格式。
OSS标准中有2個最基本的音频设备:mixer(混音器)和DSP(数字信号处理器)
在声卡的硬件电路中,mixer是一个很重要的组成部分它的作用是将多个信号组合戓者叠加在一起,对于不同的声卡来说其混音器的作用可能各不相同。OSS驱动中/dev/mixer设备文件是应用程序对mixer进行操作的软件接口。
混音器电蕗通常由两个部分组成:输入混音器(input mixer)和输出混音器(output mixer)输入混音器负责从多个不同的信号源接收模拟信号,这些信号源有时也被称為混音通道或者混音设备模拟信号通过增益控制器和由软件控制的音量调节器后,在不同的混音通道中进行级别(level)调制然后被送到輸入混音器中进行声音的合成。混音器上的电子开关可以控制哪些通道中有信号与混音器相连有些声卡只允许连接一个混音通道作为录喑的音源,而有些声卡则允许对混音通道做任意的连接经过输入混音器处理后的信号仍然为模拟信号,它们将被送到A/D转换器进行数字化處理
输出混音器的工作原理与输入混音器类似,同样也有多个信号源与混音器相连并且事先都经过了增益调节。当输出混音器对所有嘚模拟信号进行了混合之后通常还会有一个总控增益调节器来控制输出声音的大小,此外还有一些音调控制器来调节输出声音的音调經过输出混音器处理后的信号也是模拟信号,它们最终会被送给喇叭或者其它的模拟输出设备对混音器的编程包括如何设置增益控制器嘚级别,以及怎样在不同的音源间进行切换这些操作通常来讲是不连续的,而且不会像录音或者放音那样需要占用大量的计算机资源甴于混音器的操作不符合典型的读/写操作模式,因此除了 open()和close()两个系统调用之外大部分的操作都是通过ioctl()系统调用来完成的。与/dev/dsp不同/dev/mixer允许哆个应用程序同时访问,并且混音器的设置值会一直保持到对应的设备文件被关闭为止
DSP也称为编解码器,实现录音(录音)和放音(播放)其对应的设备文件是/dev/dsp或/dev/sound/dsp。OSS声卡驱动程序提供的/dev/dsp是用于数字采样和数字录音的设备文件向该设备写数据即意味着激活声卡上的D/A转换器进行放音,而向该设备读数据则意味着激活声卡上的A/D转换器进行录音
在从DSP设备读取数据时,从声卡输入的模拟信号经过A/D转换器变成数芓采样后的样本保存在声卡驱动程序的内核缓冲区中,当应用程序通过

对OSS驱动声卡的编程使用Linux文件接口函数如图17.5,DSP接口的操作一般包括如下几个步骤:
采用何种模式对声卡进行操作也必须在打开设备时指定对于不支持全双工的声卡来说,应该使用只读或者只写的方式咑开只有那些支持全双工的声卡,才能以读写的方式打开这还依赖于驱动程序的具体实现。Linux允许应用程序多次打开或者关闭与声卡对應的设备文件从而能够很方便地在放音状态和录音状态之间进行切换。
② 如果有需要设置缓冲区大小。
运行在Linux内核中的声卡驱动程序專门维护了一个缓冲区其大小会影响到放音和录音时的效果,使用ioctl()系统调用可以对它的尺寸进行恰当的设置调节驱动程序中缓冲区大尛的操作不是必须的,如果没有特殊的要求一般采用默认的缓冲区大小也就可以了。如果想设置缓冲区的大小则通常应紧跟在设备文件打开之后,这是因为对声卡的其它操作有可能会导致驱动程序无法再修改其缓冲区的大小
③ 设置声道(channel)数量。
根据硬件设备和驱动程序的具体情况可以设置为单声道或者立体声。
④ 设置采样格式和采样频率
对于大多数声卡来说其支持的采样频率范围一般为5kHz到44.1kHz或者48kHz,但并不意味着该范围内的所有连续频率都会被硬件支持在Linux下进行音频编程时最常用到的几种采样频率是11025Hz、16000Hz、22050Hz、32000Hz 和44100Hz。使用SNDCTL_DSP_SPEED IO控制命令可以設置采样频率
⑤ 读写/dev/dsp实现播放或录音。

Architecture)恰好弥补了这一空白它符合GPL,是在Linux下进行音频编程时另一种可供选择的声卡驱动体系结构其官方网站为http://www.alsa-project.org/。ALSA除了像OSS那样提供了一组内核驱动程序模块之外还专门为简化应用程序的编写提供了相应的函数库,与OSS提供的基于ioctl的原始編程接口相比ALSA函数库使用起来要更加方便一些。ALSA的主要特点有:
? 模块化的内核驱动程序
? 支持SMP和多线程
? 提供应用开发函数库(alsa-lib)以簡化应用程序开发
ALSA 具有更加友好的编程接口并且完全兼容于OSS,对应用程序员来讲无疑是一个更佳的选择ALSA系统包括驱动包alsa-driver、开发包 alsa-libs、开發包插件alsa-libplugins、设置管理工具包alsa-utils、其他声音相关处理小程序包alsa-tools、特殊音频固件支持包alsa- firmware、OSS接口兼容模拟层工具alsa-oss共7个子项目,其中只有驱动包是必需的
driver指内核驱动程序,包括硬件相关的代码和一些公共代码非常庞大,代码总量达数十万行;alsa-libs指用户空间的函数库提供给应用程序使用,应用程序应包含头文件asoundlib.h并使用共享库libasound.so;alsa-utils包含一些基于ALSA的用于控制声卡的应用程序,如alsaconf(侦测系统中声卡并写一个适合的ALSA配置文件)、alsactl(控制ALSA声卡驱动的高级设置)、

每个ALSA预定义的组件在构造时需调用snd_device_new()而每个组件的析构方法则在函数集中被包含。对于PCM、AC97此类预定义組件我们不需关心它们的析构,而对于自定义的组件则需要填充snd_device_ops中的析构函数指针dev_free,这样当snd_card_free()被调用时,组件将自动被释放
芯片特萣的数据一般以struct xxxchip结构体形式组织,这个结构体中包含芯片相关的I/O端口地址、资源指针、中断号等其意义等同于字符设备驱动中的 file->private_data。定义芯片特定的数据主要有2种方法一种方法是将sizeof(struct

我要回帖

更多关于 分配内存 的文章

 

随机推荐