资源描述
单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,*,*,第,8,章,Linux,下音频设备编程,本章着重阐述了,Linux,下对音频设备的编程方法。读完本章,读者将了解以下内容:,音频信号的数字化和相关概念;,音频总线接口,IIS,的控制原理和控制程序;,Linux,下音频设备编程的特点和操作方法;,MPlayer,媒体播放器在嵌入式,Linux,上的移植实例。,8.1,音频信号基础,音频信号是一种连续变化的模拟信号,但计算机只能处理和记录二进制的数字信号,而由自然音源得到的音频信号必须经过一定的变换,成为数字音频信号之后,才能送到计算机中做进一步的处理。,数字音频信号,模拟音频信号数字化的典型方法是对时间坐标按相等的时间间隔做采样,对振幅做量化,单位时间内的采样次数称为采样频率。这样,一段声波被数字化后就可以变成一串数值,每个数值对应相应抽样点的振幅值,按顺序将这些数字排列起来就是数字音频信号了。这就是模拟,-,数字转化(,ADC,)过程。数字,-,模拟转化(,DAC,)过程则相反,将连续的数字按采样时的频率和顺序转换成对应的电压。通俗一点讲,音频,ADC/DAC,就是录音,/,放音。放音是数字音频信号转换成模拟音频信号,以驱动耳机、功放等模拟设备,而录音则是要将麦克风等产生的模拟音频信号转换成数字音频信号,并最终转换成计算机可以处理的通用音频文件格式。,采样就是每隔一定时间读一次声音信号的幅度,而量化则是将采样得到的声音信号幅度转换为数字值。从本质上讲,采样是时间上的数字化,而量化则是幅度上的数字化。,采样频率的选择应该遵循奈奎斯特(,Nyquist,)采样理论:采样频率高于输入信号最高频率的两倍,就能从采样信号序列重构原始信号。为了保证声音不失真,采样频率应该在,40kHz,左右。常用的音频采样频率有,8kHz,、,11.025kHz,、,22.05kHz,、,16kHz,、,37.8kHz,、,44.1kHz,、,48kHz,等,如果采用更高的采样频率,还可以达到,DVD,的音质。,量化是对模拟音频信号的幅度进行数字化,量化位数决定了模拟信号数字化以后的动态范围,常用的有,8,位、,12,位和,16,位。量化位越高,信号的动态范围越大,数字化后的音频信号就越接近原始信号,但所需要的存储空间也越大。,声道数是反映音频数字化质量的另一个重要因素,它有单声道、双声道和多声道之分。双声道又称为立体声,在硬件中有两条线路,音质和音色都要优于单声道,但数字化后占据的存储空间的大小要比单声道多一倍。多声道能提供更好的听觉感受,不过占用的存储空间也更大。,音频文件格式,1,MP3,MP3,的全称应为,MPEG1 Layer-3,音频文件。,MPEG,(,Moving Picture Experts Group,)在汉语中译为活动图像专家组,特指活动影音压缩标准,,MPEG,音频文件是,MPEG1,标准中的声音部分,也叫,MPEG,音频层,它根据压缩质量和编码复杂程度划分为三层,即,Layer-1,、,Layer-2,、,Layer-3,,且分别对应,MP1,、,MP2,、,MP3,这三种声音文件,并根据不同的用途,使用不同层次的编码。,MPEG,音频编码的层次越高,编码器越复杂,压缩率也越高,,MP1,和,MP2,的压缩率分别为,4:1,和,6:18:1,,而,MP3,的压缩率则高达,10:112:1,,也就是说,一分钟,CD,音质的音乐,未经压缩需要,10MB,的存储空间,而经过,MP3,压缩编码后只有,1MB,左右。不过,MP3,对音频信号采用的是有损压缩方式,为了降低声音失真度,,MP3,采取了“感官编码技术”,即编码时先对音频文件进行频谱分析,然后用过滤器滤掉噪音电平,接着通过量化的方式将剩下的每一位打散排列,最后形成具有较高压缩比的,MP3,文件,并使压缩后的文件在回放时能够达到比较接近原音源的声音效果。,2,WMA,WMA,就是,Windows Media Audio,编码后的文件格式,由微软开发。,WMA,针对的不是单机市场,而是网络。它的竞争对手就是网络媒体市场中著名的,Real Networks,。微软声称,在只有在,64kbps,的码率情况下,,WMA,可以达到接近,CD,的音质。与以往的编码不同,,WMA,支持防复制功能,它支持通过,Windows Media Rights Manager,加入保护,可以限制播放时间和播放次数甚至于播放的机器等。由于,WMA,支持流技术,即一边读一边播放,因此,WMA,可以很轻松的实现在线广播。,WMA,有着优秀的技术特征,在微软的大力推广下,这种格式被越来越多的人所接受。,3,WAV,这是一种古老的音频文件格式,由微软开发。,WAV,文件格式符合,RIFF,(,Resource Interchange File Format,,资源互换文件格式)规范。所有的,WAV,都有一个文件头,这个文件头保存了音频流的编码参数。,WAV,对音频流的编码没有硬性规定,除了,PCM,之外,还有几乎所有支持,ACM,规范的编码都可以为,WAV,的音频流进行编码。在,Windows,平台下,基于,PCM,编码的,WAV,是被支持得最好的音频格式,所有音频软件都能完美支持。由于本身可以达到较高的音质的要求,,WAV,也是音乐编辑创作的首选格式,适合保存音乐素材。因此,基于,PCM,编码的,WAV,被作为一种中介的格式,常常使用在其他编码的相互转换之中,例如,,MP3,转换成,WMA,。,4,Ogg,Vorbis,OGG,是一个庞大的多媒体开发计划的项目名称,涉及视频音频等方面的编码开发。整个,OGG,项目计划的目的就是向任何人提供完全免费的多媒体编码方案,,OGG,的信念就是开源和免费。,Vorbis,是,OGG,项目中音频编码的正式命名,目前,Vorbis,已经开发成功,并且开发出了编码器。,Ogg,Vorbis,是高质量的音频编码方案,官方数据显示:,Ogg,Vorbis,可以在相对较低的数据速率下实现比,MP3,更好的音质,而且它可以支持多声道。多声道音乐的兴起,给音乐欣赏带来了革命性的变化,尤其在欣赏交响时,会带来更多临场感。这场革命性的变化是,MP3,无法适应的,因为,MP3,只能编码,2,个声道。与,MP3,一样,,Ogg,Vorbis,是一种灵活开放的音频编码,能够在编码方案已经固定下来后继续对音质进行明显的调节和新算法的改良。因此,它的声音质量将会越来越好。与,MP3,相似,,Ogg,Vorbis,更像一个音频编码框架,可以不断导入新技术,逐步完善。,5,RA,RA,就是,RealAudio,格式,这是因特网上接触得非常多的一种格式。这种格式完全针对网络上的媒体市场,支持非常丰富的功能。这种格式最大的特点是可以根据听众的带宽来控制码率,在保证流畅的前提下尽可能提高音质。,RA,可以支持多种音频编码,其中包括,ATRAC3,。和,WMA,一样,,RA,不但支持边读边放,也同样支持使用特殊协议来隐匿文件的真实网络地址,从而实现只在线播放而不提供下载的欣赏方式。,6,APE,APE,是,Monkeys Audio,提供的一种无损压缩格式。由于,Monkeys Audio,提供了,Winamp,的插件支持,因此这就意味着压缩后的文件不再是单纯的压缩格式,而是与,MP3,一样可以播放的音频文件格式。这种格式的压缩比远低于其他格式,但由于能够做到真正无损,因此获得了不少发烧用户的青睐。现在有不少无损压缩方案,,APE,是其中有着突出性能的格式,它具有令人满意的压缩比,以及飞快的压缩速度,成为不少朋友私下交流发烧音乐的惟一选择。,7,AAC,AAC,(高级音频编码技术,,Advanced Audio Coding,)是杜比实验室为音乐社区提供的技术,声称最大能容纳,48,通道的音轨,采样率达,96kHz,。,AAC,在,320kbps,的数据速率下能为,5.1,声道音乐节目提供相当于,ITU-R,广播的品质。,AAC,是遵循,MPEG-2,的规格所开发的技术,与,MP3,比起来,它的音质比较好,也能够节省大约,30%,的存储空间与带宽。,8,ATRAC 3,ATRAC3,(,Adaptive Transform Acoustic Coding3,)由日本索尼公司开发,是,MD,所采用的,ATRAC,的升级版,其压缩率(约为,ATRAC,的,2,倍)和音质均与,MP3,相当。压缩原理包括同时掩蔽、时效掩蔽和等响度曲线等,与,MP3,大致相同。,ATRAC3,的版权保护功能采用的是,OpenMG,。目前,对应,ATRAC3,的便携式播放机主要是索尼公司自己的产品。不过,该公司已于,2000,年,2,月与富士通、日立、,NEC,、,Rohm,、三洋和,TI,等半导体制造商签署了制造并销售,ATRAC3,用,LSI,的专利许可协议。,WAVE,文件格式剖析,WAVE,文件作为多媒体中使用的声波文件格式之一,是以,RIFF,格式为标准的。,RIFF,可以看成是一种树形结构,其基本构成单位为,chunk,,犹如树形结构中的节点,每个,chunk,由辨别码、数据大小,以及数据所组成。,WAVE,文件的“,RIFF”,格式辨别码为“,WAVE”,,整个文件由两个,chunk,所组成,辨别码分别是“,fmt,”,和“,data”,。在“,fmt”chunk,下包含了一个,PCM,波形格式的数据结构,在此之后是包含原始声音信息的采样数据,这些数据是可以直接送到,IIS,总线的数字音频信号。,WAVE,文件各部分内容及格式如表,8.1,所示。,常见的声音文件主要有两种,分别对应于单声道和双声道。对于单声道声音文件,采样速率是,11.025kHz,,采样数据为,8,位的短整数(,short,int,);而对于双声道立体声声音文件,采样速率为,44.1kHz,,每次采样数据为一个,16,位的整数(,int,),高,8,位和低,8,位分别代表左右两个声道。,WAVE,文件数据块包含以脉冲编码调制(,PCM,)格式表示的样本。,WAVE,文件是由样本组织而成的。在,WAVE,文件中,声道,0,代表左声道,声道,1,代表右声道。在多声道,WAVE,文件中,样本是交替出现的。例如,对于,8,位双声道的立体声,存储数据格式依次为:,0,声道(左)、,1,声道(右)、,0,声道(左)、,1,声道(右)。对于,16,位立体声,存储数据依次为:,0,声道(左)低字节、,0,声道(左)高字节、,1,声道(右)低字节、,1,声道(右)高字节。,8.2,基于,IIS,接口的音频系统,IIS,接口控制原理,S3C2410X,内置了一个,IIS,总线控制器,该控制器实现到一个外部,8/16,位立体声音频编解码器接口,支持,IIS,总线数据格式和,MSB-justified,数据格式。,S3C2410X,中有两条串行数据线,一条是输入信号数据线,一条是输出信号数据线,以同时发送和接收数据。,IIS,接口有,3,种工作方式:,正常传输模式,正常模式下使用,IISCON,寄存器对,FIFO,进行控制。如果传输,FIFO,缓存为空,,IISCON,的第,7,位被设置为“,0”,,表示不能继续传输数据,需要,CPU,对缓存进行处理。如果传输,FIFO,缓存非空,,IISCON,的第,7,位被设置成“,1”,,表示可以继续传输数据。同样,数据接收时,如果,FIFO,满,标识位是“,0”,,此时,需要,CPU,对,FIFO,进行处理,如果,FIFO,没有满,那么标志位是“,1”,,这个时候可以继续接收数据。,DMA,模式,通过设置,IISFCON,寄存器可以使,IIS,接口工作于这种模式下。在这种模式中,,FIFO,寄存器组的控制权掌握在,DMA,控制器上,当,FIFO,满了,由,DMA,控制器对,FIFO,中的数据进行处理。,DMA,模式的选择由,IISCON,寄存器的第,4,位和第,5,位控制。,传输,/,接收模式,这种模式下,,IIS,数据可以同时接收和发送音频数据。,IIS,总线控制器结构如图,8.2,所示,各功能说明如下:,两个,5,比特预除器,IPSR,,,IPSA_A,用于产生,IIS,总线接口的主时钟,,IPSA_B,用做外部,CODEC,时钟产生器。,16,字节,FIFO,,在发送数据时数据被写进,TxFIFO,,在接收数据时数据从,RxFIFO,中读取。,主,IISCLK,产生器,SCLKG,,在主模式下,有主时钟产生串行位时钟。,通道产生器和状态机,CHNC,,,IISCLK,和,IISLRCK,有通道状态机产生并控制。,16,比特移位寄存器(,SFTR,),在发送数据时,并行数据经由,SFTR,变成串行数据输出;在数据接收时,串行数据由,SFTR,转变成并行数据。,音频接口电路设计,音频接口程序设计,1,放音,放音程序代码如下:,#include 2410addr.h,#include 2410lib.h,#include,def.h,“,#include 2410iis.h,void ChangeDMA2(void);,void,IIS_PortSetting(void,);,void _WrL3Addr(U8 data);,void _WrL3Data(U8,data,int,halt);,void _,irq,DMA2_Done(void);,void _,irq,DMA2_Rec_Done(void);,void _,irq,RxInt(void,);,void _,irq,Muting(void,);,#define L3C(14)/GPB4=L3CLOCK,#define L3D(13)/GPB3=L3DATA,#define L3M(12)/GPB2=L3MODE,#define PLAY 0,#define RECORD 1,/#define REC_LEN 0 x50000 /327,680 Bytes,#define REC_LEN 0 x100000 /1,048,576 Bytes,#define,DataCount,0 x10000 /IIS Master/Slave Data Rx/,Tx,Count,#define,DataDisplay,0 x100 /IIS Master Data Display Count,#define PollMode 0 /1:Polling Mode,#define DMA2Mode 1 /1:DMA2 Mode,#define,MICGain_Amp_Sel,0/0:Input channel 2 Amp.1:MIC Amp.,unsigned char *,Buf,*_temp;,unsigned short*,rec_buf,;,volatile unsigned,int,size=0;,volatile unsigned,int,fs,=0;,volatile char,which_Buf,=1;,volatile char,Rec_Done,=0;,volatile char mute=1;,void,PlayTest_Iis(void,),unsigned,int,save_B,save_E,save_PB,save_PE,;,Uart_TxEmpty(0);,由于,IIS,时钟从系统分频得到,下面的代码将系统,PCLK,降到,33MHz,,而且降频后必须对串口重新进行初始化。,ChangeClockDivider(1,1);/1:2:4,ChangeMPllValue(0 x96,0 x5,0 x1);/FCLK=135.428571MHz(PCLK=33.857142MHz),Uart_Init(33857142,115200);,Uart_Printf,(IIS test(Play)using UDA1341 CODEC n);,然后将用到的端口保存起来,并进行端口初始化。,save_B,=,rGPBCON,;,save_E,=,rGPECON,;,save_PB,=,rGPBUP,;,save_PE,=,rGPEUP,;,IIS_PortSetting,();,IIS,采用,DMA,方式进行录音和播放,因此需要进行,DMA,中断的注册。,pISR_DMA2 =(unsigned)DMA2_Done;,然后获取语音数据及其大小、采样频率。,rINTSUBMSK,=(BIT_SUB_RXD0);,rINTMSK,=(BIT_EINT0|BIT_UART0|BIT_DMA2);,/Non-cacheable area=0 x31000000 0 x33feffff,Buf,=(unsigned char*)0 x31000000;,_temp=,Buf,;,Uart_Printf(Download,the,PCM(no,ADPCM)file by,DNW(With,header)!n);,size=*(,Buf,)|*(,Buf,+1)8|*(,Buf,+2)16|*(,Buf,+3)24;,Uart_Printf(nNow,Downloading.,size);,rINTSUBMSK,|=BIT_SUB_RXD0;,size=*(,Buf,+0 x2c)|*(,Buf,+0 x2d)8|*(,Buf,+0 x2e)16|*(,Buf,+0 x2f)1)1;,fs,=*(,Buf,+0 x1c)|*(,Buf,+0 x1d)8|*(,Buf,+0 x1e)16|*(,Buf,+0 x1f)24;,接着初始化,UDA1341,,设置为放音模式:,Init1341(PLAY);,接着进行,DMA,初始化:,rDISRC2 =(,int)(Buf,+0 x30);/0 x31000030(Remove header),rDISRCC2=(01)+(00);/,源地址位于系统总线,AHB,,地址递增,rDIDST2 =(U32)IISFIFO);/IISFIFO,rDIDSTC2=(11)+(10);/,目的地址位于外设总线,APB,,地址固定,rDCON2 =(131)+(030)+(129)+(028)+(027)+(024)+,(123)+(022)+(120)+(size/4);,/1010 0000 1001,xxxx,xxxx,xxxx,xxxx,xxxx,/Handshake31,Sync PCLK30,CURR_TC Interrupt Request29,/Single Tx28,Single service27,/I2SSDO26:24,DMA source selected23,Auto-reload22,/Half-word21:20,size/219:0,rDMASKTRIG2=(02)+(11)+(00);/No-stop2,DMA2 channel On1,No-,sw,trigger0,IIS,初始化:,if(fs,=44100)/11.2896MHz(256fs),rIISPSR,=(25)+2;/,Prescaler,A,B=2-FCLK 135.4752MHz(1:2:4),else /,fs,=22050,5.6448MHz(256fs),rIISPSR,=(55)+5;/,Prescaler,A,B=5-FCLK 135.4752MHz(1:2:4),rIISCON,=(15)+(12)+(11);/Tx DMA enable5,Rx idle2,Prescaler,enable1,/Master mode8,Tx mode7:6,Low for Left Channel5,IIS format4,16bit ch.3,CDCLK 256fs2,IISCLK 32fs1:0,rIISMOD,=(08)+(26)+(05)+(04)+(13)+(02)+(10);,rIISFCON,=(115)+(1 start piling.,启动,IIS,。,IIS,启动后,将采用,DMA,方式播放语音数据,播放完毕后将引发中断,并重新播放语音数据。可通过按任意键,决定播放是否结束。,/IIS,Tx,Start,Uart_Printf(nPress,any key to exit!n);,rIISCON,|=0 x1;/IIS Interface start,while(!Uart_GetKey,(),if(rDSTAT2&0 xfffff)(size/6),ChangeDMA2();,其中,,ChangeDMA2(),函数根据标志位,which_Buf,决定是否重新播放,标志位,which_Buf,在中断服务函数,DMA2_Done(),中设置。,语音播放结束后,通知,IIS,,并恢复寄存器。,Delay(10);/For end of H/W,Tx,rIISCON,=0 x0;/IIS Interface stop,rDMASKTRIG2 =(12);/DMA2 stop,rIISFCON,=0 x0;/For FIFO flush,size=0;,rGPBCON,=,save_B,;,rGPECON,=,save_E,;,rGPBUP,=,save_PB,;,rGPEUP,=,save_PE,;,最后关闭中断,并恢复系统时钟:,rINTMSK,=(BIT_DMA2|BIT_EINT0);,ChangeMPllValue(0 xa1,0 x3,0 x1);/FCLK=202.8MHz,Uart_Init(0,115200);,mute=1;,2,录音,录音程序在初始化等动作上与放音类似,代码如下:,void,Record_Iis(void,),unsigned,int,save_B,save_E,save_PB,save_PE,;,Uart_TxEmpty(0);,ChangeClockDivider(1,1);/1:2:4,ChangeMPllValue(0 x96,0 x5,0 x1);/FCLK=135428571Hz,PCLK=3.385714MHz,Uart_Init(33857142,115200);,Uart_Printf,(Record test using UDA1341 n);,save_B,=,rGPBCON,;,save_E,=,rGPECON,;,save_PB,=,rGPBUP,;,save_PE,=,rGPEUP,;,IIS_PortSetting,();,录音数据保存在,rec_buf,中:,rec_buf,=(unsigned short*)0 x31000000;,pISR_DMA2 =(unsigned)DMA2_Rec_Done;,pISR_EINT0=(,unsigned)Muting,;,rINTMSK,=(BIT_DMA2);,Init1341(RECORD);,rDISRCC2=(11)+(10);/APB,Fix,rDISRC2 =(U32)IISFIFO);/IISFIFO,rDIDSTC2=(01)+(00);/AHB,Increment,rDIDST2 =(,int)rec_buf,;/0 x31000000,rDCON2 =(131)+(030)+(129)+(028)+(027)+(124),+(123)+(122)+(120)+REC_LEN;,/Handshake,sync PCLK,TC,int,single,tx,single service,/I2SSDI,I2S Rx request,/Off-reload,half-word,0 x50000 half word.,rDMASKTRIG2=(02)+(11)+0;/No-stop,DMA2 channel on,No-,sw,trigger,/,Master,Rx,L-ch,=low,IIS,16bit,ch,CDCLK,=256fs,IISCLK=32fs,rIISMOD,=(08)+(16)+(05)+(04)+(13)+(02)+(10);,rIISPSR,=(25)+2;/,Prescaler_A,/B=2-FCLK,135.4752MHz(1:2:4),11.2896MHz(256fs),44.1KHz,rIISCON,=(05)+(14)+(13)+(02)+(11);,/,Tx,DMA,disable,Rx,DMA,enable,Tx,idle,Rx,not,idle,prescaler,enable,stop,rIISFCON,=(114)+(1 start piling.,开始录音:,/Rx start,rIISCON,|=0 x1;,录音完毕将引发,DMA2,中断,如下代码等待录音结束:,while(!Rec_Done,);,rINTMSK,=BIT_DMA2;,Rec_Done,=0;,/IIS Stop,Delay(10);/For end of H/W Rx,rIISCON,=0 x0;/IIS stop,rDMASKTRIG2=(12);/DMA2 stop,rIISFCON,=0 x0;/For FIFO flush,录音完毕,然后播放声音:,Uart_Printf(End,of Record!n);,Uart_Printf(Press,any key to play recorded datan);,Uart_Printf(If,you want to mute or no mute push the EIN0 key,repeatedlyn);,Uart_Getch,();,size=REC_LEN*2;,Uart_Printf(Size,=%,dn,size,);,Init1341(PLAY);,pISR_DMA2=(unsigned)DMA2_Done;,rINTMSK,=(BIT_DMA2|BIT_EINT0);,/DMA2 Initialize,rDISRCC2=(01)+(00);/AHB,Increment,rDISRC2 =(,int)rec_buf,;/0 x31000000,rDIDSTC2=(11)+(10);/APB,Fixed,rDIDST2 =(U32)IISFIFO);/IISFIFO,rDCON2 =(131)+(030)+(129)+(028)+(027)+(024),+(123)+(022)+(120)+(size/2);,/Handshake,sync PCLK,TC,int,single,tx,single service,I2SSDO,I2S request,/Auto-reload,half-word,size/2,rDMASKTRIG2=(02)+(11)+0;/No-stop,DMA2 channel on,No-,sw,trigger,/IIS Initialize,/,Master,Tx,L-ch,=low,iis,16bit,ch.,CDCLK,=256fs,IISCLK=32fs,rIISMOD,=(08)+(26)+(05)+(04)+(13)+(02)+(10);,/,rIISPSR,=(45)+4;/,Prescaler_A,/B=4 for 11.2896MHz,rIISCON,=(15)+(04)+(03)+(12)+(11);,/,Tx,DMA,enable,Tx,DMA,disable,Tx,not,idle,Rx,idle,prescaler,enable,stop,rIISFCON,=(115)+(1 start piling.,Uart_Printf(Press,any key to exit!n);,rIISCON,|=0 x1;/IIS,Tx,Start,while(!Uart_GetKey,();,/IIS,Tx,Stop,Delay(10);/For end of H/W,Tx,rIISCON,=0 x0;/IIS stop,rDMASKTRIG2=(12);/DMA2 stop,rIISFCON,=0 x0;/For FIFO flush,size=0;,rGPBCON,=,save_B,;,rGPECON,=,save_E,;,rGPBUP,=,save_PB,;,rGPEUP,=,save_PE,;,rINTMSK,=(BIT_DMA2|BIT_EINT0);,ChangeMPllValue(0 xa1,0 x3,0 x1);/FCLK=202.8MHz,Uart_Init(0,115200);,mute=1;,8.3,音频设备程序的实现,在,Linux,下,音频设备程序的实现与文件系统的操作密切相关。,Linux,将各种设备以文件的形式给出统一的接口,这样的设计使得对设备的编程与对文件的操作基本相同,对,Linux,内核的系统调用也基本一致,从而简化了设备编程。,如何对各种音频设备进行操作是在,Linux,上进行音频编程的关键,通过内核提供的一组系统调用,应用程序能够访问声卡驱动程序提供的各种音频设备接口,这是在,Linux,下进行音频编程最简单也是最直接的方法。,声卡不是,Linux,控制台的一部分,它是一个特殊的设备。声卡主要提供,3,个重要的特征:,数字取样输入,/,输出;,频率调制输出;,MIDI,接口。,这,3,个特征都有它们自己的设备驱动程序接口,数字取样的接口是,/dev/,dsp,,频率调制的接口,/dev/sequencer,,而,MIDI,接口是,/dev/midi,。混音设备(如音量、平衡或者贝斯)可以通过,/dev/mixer,接口来控制。为了满足兼容性的需要,还提供了一个,/dev/audio,设备,该设备可用于读,SUN_law,的声音数据,但它是映射到数字取样设备的。,音频编程接口,程序员可以使用,ioctl,(),来操作这些设备,,ioctl,(),请求是在,linux/soundcard.h,中定义的,它们以,SNDCTL_,开头。首先使用,open,系统调用建立起与硬件间的联系,此时返回的文件描述符将作为随后操作的标识;接着使用,read,系统调用从设备接收数据,或者使用,write,系统调用向设备写入数据,而其他所有不符合读,/,写这一基本模式的操作都可以由,ioctl,系统调用来完成;最后,使用,close,系统调用告诉,Linux,内核不会再对该设备做进一步的处理。,1,open,系统调用,系统调用,open,可以获得对声卡的访问权,同时还能为随后的系统调用做好准备,其函数原型如下所示:,int,open(const,char*pathname,int,flags,int,mode);,参数,pathname,是将要被打开的设备文件的名称,对于声卡来讲一般是,/dev/,dsp,。参数,flags,用来指明应该以什么方式打开设备文件,它可以是,O_RDONLY,、,O_WRONLY,或者,O_RDWR,,分别表示以只读、只写或者读写的方式打开设备文件;参数,mode,通常是可选的,它只有在指定的设备文件不存在时才会用到,指明新创建的文件应该具有怎样的权限。如果,open,系统调用能够成功完成,它将返回一个正整数作为文件标志符,在随后的系统调用中需要用到该标志符。如果,open,系统调用失败,它将返回,1,,同时还会设置全局变量,errno,,指明是什么原因导致了错误的发生。,2,read,系统调用,read,用来从声卡读取数据:,int,read(int,fd,char*,buf,size_t,count);,参数,fd,是设备文件的标志符,它是通过之前的,open,系统调用获得的;参数,buf,是指向缓冲区的字符指针,它用来保存从声卡获得的数据;参数,count,则用来限定从声卡获得的最大字节数。如果,read,系统调用成功完成,它将返回从声卡实际读取的字节数,通常情况会比,count,的值小一些;如果,read,系统调用失败,它将返回,1,,同时还会设置全局变量,errno,,来指明是什么原因导致了错误的发生。,3,write,系统调用,write,用来向声卡写入数据,其函数原型如下所示:,size_t,write(int,fd,const char*,buf,size_t,count);,系统调用,write,和系统调用,read,在很大程度是类似的,差别只在于,write,是向声卡写入数据,而,read,则是从声卡读入数据。参数,fd,同样是设备文件的标志符,它也是通过之前的,open,系统调用获得的;参数,buf,是指向缓冲区的字符指针,它保存着即将向声卡写入的数据;参数,count,则用来限定向声卡写入的最大字节数。,如果,write,系统调用成功完成,它将返回向声卡实际写入的字节数;如果,write,系统调用失败,它将返回,1,,同时还会设置全局变量,errno,,来指明是什么原因导致了错误的发生。无论是,read,还是,write,,一旦调用之后,,Linux,内核就会阻塞当前应用程序,直到数据成功地从声卡读出或者写入为止。,4,ioctl,系统调用,系统调用,ioctl,可以对声卡进行控制,凡是对设备文件的操作不符合读,/,写基本模式的,都是通过,ioctl,来完成的,它可以影响设备的行为,或者返回设备的状态,其函数原型如下所示:,int,ioctl(int,fd,int,request,.);,参数,fd,是设备文件的标志符,它是在设备打开时获得的;如果设备比较复杂,那么对它的控制请求相应地也会有很多种,参数,request,的目的就是用来区分不同的控制请求;通常说来,在对设备进行控制时还需要有其他参数,这要根据不同的控制请求才能确定,并且可能是与硬件设备直接相关的。,5,close,系统调用,当应用程序使用完声卡之后,需要用,close,系统调用将其关闭,以便及时释放占用的硬件资源,其函数原型如下所示:,int,close(int,fd,);,参数,fd,是设备文件的标志符,它是在设备打开时获得的。一旦应用程序调用了,close,系统调用,,Linux,内核就会释放与之相关的各种资源,因此建议在不需要的时候尽量及时关闭已经打开的设备。,音频设备文件,/dev/,sndstat,设备文件,/dev/,sndstat,是声卡驱动程序提供的最简单的接口,通常它是一个只读文件,作用也仅仅只限于汇报声卡的当前状态。一般说来,,/dev/,sndstat,是提供给最终用户来检测声卡的,不宜用于程序当中,因为所有的信息都可以通过,ioctl,系统调用来获得。,/dev/,dsp,声卡驱动程序提供的,/dev/,dsp,是用于数字采样和数字录音的设备文件,它对于,Linux,下的音频编程来讲非常重要。向该设备写数据即意味着激活声卡上的,D/A,转换器进行放音,而从该设备读数据则意味着激活声卡上的,A/D,转换器进行录音。目前,许多声卡都提供有多个数字采样设备,它们在,Linux,下可以通过,/dev/,dsp,等设备文件进行访问。,/dev/audio,/dev/audio,类似于,/dev/,dsp,,它兼容于,Sun,工作站上的音频设备,使用的是,mu,-law,编码方式。由于设备文件,/dev/audio,主要出于对兼容性的考虑,所以在新开发的应用程序中最好不要尝试用它,而应该以,/dev/,dsp,进行替代。对于应用程序来说,同一时刻只能使用,/dev/audio,或者,/dev/,dsp,其中之一,因为它们是相同硬件的不同软件接口。,/dev/mixer,在声卡的硬件电路中,混音器(,mixer,)是一个很重要的组成部分,它的作用是将多个信号组合或者叠加在一起,对于不同的声卡来说,其混音器的作用可能各不相同。运行在,Linux,内核中的声卡驱动程序一般都会提供,/dev/mixer,这一设备文件,它是应用程序对混音器进行操作的软件接口。,/dev/sequencer,目前大多数声卡驱动程序还
展开阅读全文