Tiny6410声卡驱动——录音与回放


在Linux下,音频设备程序的实现与文件系统的操作密切相关。Linux将各种设备以文件的形式给出统一的接口,这样的设计使得对设备的编程与对文件的操作基本相同,对Linux内核的系统调用也基本一致,从而简化了设备编程。

如何对各种音频设备进行操作是在Linux上进行音频编程的关键,通过内核提供的一组系统调用,应用程序能够访问声卡驱动程序提供的各种音频设备接口,这是在Linux下进行音频编程最简单也是最直接的方法。

声卡不是Linux控制台的一部分,它是一个特殊的设备。声卡主要提供3个重要的特征:

  • 数字取样输入/输出
  • 频率调制输出
  • MIDI接口

这3个特征都有它们自己的设备驱动程序接口

 

 

  • 数字取样的接口是/dev/dsp
  • 频率调制的接口/dev/sequencer
  • MIDI接口是/dev/midi

 

混音设备(如音量、平衡或者贝斯)可以通过/dev/mixer接口来控制。

为了满足兼容性的需要,还提供了一个/dev/audio设备,该设备可用于读SUN_law的声音数据,但它是映射到数字取样设备的。

 

1、音频编程接口

程序员可以使用ioctl()来操作这些设备,ioctl()请求是在linux/soundcard.h中定义的,它们以SNDCTL_开头。

 

  • 首先使用open系统调用建立起与硬件间的联系,此时返回的文件描述符将作为随后操作的标识;
  • 接着使用read系统调用从设备接收数据,或者使用write系统调用向设备写入数据,而其他所有不符合读/写这一基本模式的操作都可以由ioctl系统调用来完成;
  • 最后,使用close系统调用告诉Linux内核不会再对该设备做进一步的处理。

 

 

1.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,指明是什么原因导致了错误的发生。

 

 

1.2.read系统调用

read用来从声卡读取数据,其函数原型如下所示

 

int read(int fd, char *buf, size_t count);

 

  • 参数fd是设备文件的标志符,它是通过之前的open系统调用获得的;
  • 参数buf是指向缓冲区的字符指针,它用来保存从声卡获得的数据;
  • 参数count则用来限定从声卡获得的最大字节数。

 

如果read系统调用成功完成,它将返回从声卡实际读取的字节数,通常情况会比count的值小一些;如果read系统调用失败,它将返回-1,同时还会设置全局变量errno,来指明是什么原因导致了错误的发生。

1.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内核就会阻塞当前应用程序,直到数据成功地从声卡读出或者写入为止。

1.4.ioctl系统调用

系统调用ioctl可以对声卡进行控制,凡是对设备文件的操作不符合读/写基本模式的,都是通过ioctl来完成的,它可以影响设备的行为,或者返回设备的状态,其函数原型如下所示: int ioctl(int fd, int request, ...);
  • 参数fd是设备文件的标志符,它是在设备打开时获得的,如果设备比较复杂,那么对它的控制请求相应地也会有很多种,
  • 参数request的目的就是用来区分不同的控制请求;
通常说来,在对设备进行控制时还需要有其他参数,这要根据不同的控制请求才能确定,并且可能是与硬件设备直接相关的。

1.5.close系统调用

当应用程序使用完声卡之后,需要用close系统调用将其关闭,以便及时释放占用的硬件资源,其函数原型如下所示: int close(int fd);
  • 参数fd是设备文件的标志符,它是在设备打开时获得的。
一旦应用程序调用了close系统调用,Linux内核就会释放与之相关的各种资源,因此建议在不需要的时候尽量及时关闭已经打开的设备。
 

2、音频设备文件

  • /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
目前大多���声卡驱动程序还会提供/dev/sequencer设备文件,用来对声卡内建的波表合成器进行操作,或者对MIDI总线上的乐器进行控制,通常只用于计算机音乐软件中。  

更多详情见请继续阅读下一页的精彩内容:

Tiny6410 简单的交叉编译helloworld

基于Tiny6410的LED驱动程序

写驱动时交叉编译之makefile编写模板(Tiny6410)

Tiny6410开发板上Linux系统的安装

  • 1
  • 2
  • 3
  • 下一页

相关内容