作者:北京中科红旗软件技术有限公司 孔伟
Alsa是Linux高级音频接口。面对众多的音频设备,Alsa为Linux音频开发人员提供了一套标准的访问机制,使得音频开发变得十分容易。不信?下面我们就利用它编写一个简单的录音/播音程序,不过这需要你有一定的计算机语言基础。
一个典型的音频程序应该具有以下结构:
打开音频设备
为设备设置读写参数
向音频设备读/写音频数据
关闭设备
Alsa库为我们实现这些操作提供了丰富的接口。
首先让我们封装一个打开音频设备的函数:
1.
2.
3.
4.
5.
6.
7.
snd_pcm_open是Alsa库提供的打开设备调用函数,这里我们指定打开缺省的音频设备,并根据参数mode将设备置为录音或是播放状态,如果设备打开成功,pcm_handle便指向该设备句柄,我们用全局变量保存起来,方便以后使用。
第二步是设置参数,参数设置不当将会导致音频设备无法正常工作。在设置参数前,我们需要了解一下各个参数的含义以及一些基本概念。
样本长度(sample):样本是记录音频数据最基本的单位,常见的有8位和16位。
通道数(channel):该参数为1表示单声道,2则是立体声。
桢(frame):桢记录了一个声音单元,其长度为样本长度与通道数的乘积。
采样率(rate):每秒钟采样次数,该次数是针对桢而言。
周期(period):音频设备一次处理所需要的桢数,对于音频设备的数据访问以及音频数据的存储,都是以此为单位。
交错模式(interleaved):是一种音频数据的记录方式,在交错模式下,数据以连续桢的形式存放,即首先记录完桢1的左声道样本和右声道样本(假设为立体声格式),再开始桢2的记录。而在非交错模式下,首先记录的是一个周期内所有桢的左声道样本,再记录右声道样本,数据是以连续通道的方式存储。不过多数情况下,我们只需要使用交错模式就可以了。
明白了各参数含义及关系后,我们开始设置参数:
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.snd_pcm_hw_params_malloc
11.snd_pcm_hw_params_any
12.snd_pcm_hw_params_set_access
13.
14.snd_pcm_hw_params_set_format(
15.
16.snd_pcm_hw_params_set_rate_near(
17.
18.snd_pcm_hw_params_set_channels(
19.snd_pcm_hw_params_get_period_size(
20.bit_per_sample
21.
22.chunk_byte
23.//计算周期长度(字节数(bytes)
24.snd_pcm_hw_params(
25.params
26.snd_pcm_hw_params_free(
27.return
28.
29.}
这里先使用了Alsa提供的一系列snd_pcm_hw_params_set_函数为参数变量赋值。最后才通过snd_pcm_hw_params将参数传递给设备。需要说明的是正式的开发中需要处理参数设置失败的情况,这里仅做为示例程序而未作考虑。
设置好参数后便可以开始录音了。录音过程实际上就是从音频设备中读取数据信息并保存。
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.r
11.if
12.else
13.return
14.}
15.return
16.}
形参dtime用来确定录音时间,根据录音时间分配数据空间,再调用snd_pcm_readi从音频设备读取音频数据,存放到wave_buf中。
同样的原理,我们再添加一个播放函数,向音频设备写入数据:
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.return
11.}
最后我们给这个示例程序加上main函数
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.int
11.int
12.int
13.snd_pcm_hw_params_t
14.
15.int
16.//录音
17.if
18.if
19.if
20.snd_pcm_close(
21.
22.//播放
23.if
24.if
25.if
26.snd_pcm_close(
27.
28.return
29.}
这样,我们便完成了一个具有录音,播音的功能的音频程序,因为使用了alsa库,如果你使用的是gcc编译器,最后链接时记得要带上参数——lasound 。
限于篇幅,Alsa接口提供的强大功能不仅于此,有兴趣的读者可以参阅ALSA HOWTO,那上面你一定能够发现Alsa的强大之处。