一、认识OSS

一、OSS介绍

1.1 什么是OSS

OSS:Open Sound System。它是UNIX平台上一个一个可选的声音架构,定义了统一的音频接口API,可以在不同的平台之间移植代码,不需要重新修改代码,重新编译就可以使用原程序

OSS的层次结构非常简单,主要有两个基本装置,Mixer和CODEC,应用程序通过API访问OSS driver,然后由OSS driver控制声卡。Mixer用来控制输入音量的大小,对应的设备文件为/dev/mixer,CODEC用来实现录音(模拟信号转变为数字信号)和播放声音(数字信号转变为模拟信号)的功能,对应的设备文件为/dev/dsp

1.2 OSS框架

在Unix系统中,所有的设备都被统一成文件,通过对文件的访问方式(先open,再read/write,使用ioctl读取/设置参数,最后close)来访问设备。在OSS中,主要有以下的几种设备文件:

/dev/mixer:访问声卡中内置的mixer,调整音量大小,选择音源
/dev/sndstat:测试声卡,执行cat /dev/sndstat会显示声卡驱动的信息
/dev/dsp 、/dev/dspW、/dev/audio:读这个设备就相当于录音,写这个设备就相当于放音。/dev/dsp与/dev/audio之间的区别在于采样的编码不同,/dev/audio使用μ律编码,/dev/dsp使用8-bit(无符号)线性编码,/dev/dspW使用16-bit(有符号)线形编码
/dev/sequencer:访问声卡内置的,或者连接在MIDI接口的synthesizer

命令cat /dev/dsp >xyz可用来录音,录音的结果放在xyz文件中;命令cat xyz >/dev/dsp播放声音文件xyz

数字音频:也称CODEC、PCM、DSP、ADC/DAC设备,用来实现录音和播放声音功能
主要参数:采样频率、通道数目(单声道,立体声)、采样位深(8-bit,16-bit)

声卡中主要有两个基本装置:Mixer和CODEC

Mixer用来控制输入音量的大小,对应的设备文件为/dev/mixer

CODEC用来实现录音和播放声音功能,对应的设备文件为/dev/dsp

1.3 OSS驱动接口

OSS 标准中有2 个最基本的音频设备:mixer(混音器)和DSP(数字信号处理器)

1.3.1 mixer

mixer(混频器)接口:用来控制多个输入、输出的音量,也控制输入(microphone,line-in,CD)之间的切换,对应的设备文件为/dev /mixer

1.3.2 synthesizer

synthesizer(合成器)接口:通过一些预先定义好的波形来合成声音,有时用在游戏中声音效果的产生

1.3.3 MIDI

MIDI(Musical Intrument Data Interface)接口:MIDI接口是为了连接舞台上的synthesizer、键盘、道具、灯光控制器的一种串行接口

1.3.4 DSP

DSP 也称为编解码器,实现录音和放音,其对应的设备文件是/dev/dsp或/dev/sound/dsp

需要指出的是,声卡采样频率是由内核中的驱动程序所决定的,而不取决于应用程序从声卡读取数据的速度。如果应用程序读取数据的速度过慢,以致低于声卡的采样频率,那么多余的数据将会被丢弃(即overflow);如果读取数据的速度过快,以致高于声卡的采样频率,那么声卡驱动程序将会阻塞那些请求数据的应用程序,直到新的数据到来为止。在向DSP 设备写入数据时,数字信号会经过D/A 转换器变成模拟信号,然后产生出声音。应用程序写入数据的速度应该至少等于声卡的采样频率,过慢会产生声音暂停或者停顿的现象(即underflow)。如果用户写入过快的话,它会被内核中的声卡驱动程序阻塞,直到硬件有能力处理新的数据为止

二、OSS开发

开发OSS应用程序的一般流程是:
  1)包含OSS头文件:#include
  2)打开设备文件,返回文件描述符
  3)使用ioctl设置设备的参数,控制设备的特性
  4)对于录音,从设备读(read)
  5)对于播放,向设备写(write)
  6)关闭打开的设备

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

2.1 open系统调用

系统调用open可以获得对声卡的访问权,同时还能为随后的系统调用做好准备
其函数原型是:`int open(const char *pathname, int flags, int mode);
其中,具体参数:

pathname:将要被打开的设备文件的名称,对于声卡来讲一般是/dev/dsp
flags:指明应该以什么方式打开设备文件,它可以是O_RDONLY、O_WRONLY或者O_RDWR,分别表示只读、只写或者读写
mode:可选的,它只有在指定的设备文件不存在时才会用到,指明新创建的文件应该具有怎样的权限

调用成功:返回一个正整数作为文件标识符,调用失败,返回-1,设置全局变量errno,指明是什么原因导致了错误的发生

2.2 read系统调用

系统调用read用来从声卡读取数据,其函数原型是:int read(int fd, char *buf, size_t count);
其中,具体参数:

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

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

2.3 write系统调用

系统调用write用来向声卡写入数据,其函数原型是示:size_t write(int fd, const char *buf, size_t count);
其中,具体参数:

fd:设备文件的标识符,它也是通过之前的open系统调用获得的
buf:指向缓冲区的字符指针,它保存着即将向声卡写入的数据
count:则用来限定向声卡写入的最大字节数

调用成功:返回向声卡实际写入的字节数;如果调用失败,返回-1,设置全局变量errno,来指明是什么原因导致了错误的发生

系统调用write和系统调用read在很大程度是类似的,差别只在于write是向声卡写入数据,而read则是从声卡读入数据。无论是read还是write,一旦调用之后Linux内核就会阻塞当前应用程序,直到数据成功地从声卡读出或者写入为止

2.4 ioctl系统调用

系统调用 ioctl 可以对声卡进行控制,凡是对设备文件的操作不符合读/写基本模式的,都是通过ioctl来完成的,它可以影响设备的行为,或者返回设备的状态,其函数原型是:int ioctl(int fd, int request, ...);
其中,具体参数:

fd:设备文件的标识符,它是在设备打开时获得的
request:区分不同的控制请求;通常说来,在对设备进行控制时还需要有其它参数,这要根据不同的控制请求才能确定,并且可能是与硬件设备直接相关的。

2.5 close系统调用

当应用程序使用完声卡之后,需要用 close 系统调用将其关闭,以便及时释放占用的硬件资源
其函数原型是:int close(int fd);
其中,具体参数:

fd:是设备文件的标识符,它是在设备打开时获得的。

一旦应用程序调用了close系统调用,Linux内核就会释放与之相关的各种资源

猜你喜欢

转载自blog.csdn.net/future_sky_word/article/details/126414045
oss