一.声音参数基本概念:
声音是连续模拟量,计算机将它离散化之后用数字表示,就有了以下几个名词术语。
样本长度(sample):样本是记录音频数据最基本的单位,计算机对每个通道采样量化时数字比特位数,常见的有8位和16位。
通道数(channel):该参数为1表示单声道,2则是立体声。
帧(frame):帧记录了一个声音单元,其长度为样本长度与通道数的乘积,一段音频数据就是由苦干帧组成的。
采样率(rate):每秒钟采样次数,该次数是针对帧而言,常用的采样率如8KHz的人声,44.1KHz的mp3音乐, 96Khz的蓝光音频。
周期(period):音频设备一次处理所需要的桢数,对于音频设备的数据访问以及音频数据的存储,都是以此为单位。
交错模式(interleaved):是一种音频数据的记录方式
在交错模式下,数据以连续桢的形式存放,即首先记录完桢1的左声道样本和右声道样本(假设为立体声格式),再开始桢2的记录。
而在非交错模式下,首先记录的是一个周期内所有桢的左声道样本,再记录右声道样本,数据是以连续通道的方式存储。
不过多数情况下,我们只需要使用交错模式就可以了。
period(周期):硬件中中断间的间隔时间。它表示输入延时。
比特率(Bits
Per Second):比特率表示每秒的比特数,比特率=采样率×通道数×样本长度
二.ALSA介绍
1.ALSA简介
ALSA表示高级Linux声音体系结构(Advanced Linux Sound Architecture)。ALSA是一个完全开放源代码的音频驱动程序集,除了像OSS那样提供了一组内核驱动程序模块之外,ALSA还专门为简化应用程序的编写提供了相应的函数库,与OSS提供的基于ioctl的原始编程接口相比,ALSA函数库使用起来要更加方便一些。利用该函数库,开发人员可以方便快捷的开发出自己的应用程序,细节则留给函数库内部处理。当然ALSA也提供了类似于OSS的系统接口,不过ALSA的开发者建议应用程序开发者使用音频函数库而不是驱动程序的API。
2.ALSA版本支持
Linux内核2.5在开发过程中,ALSA被合并到了官方的源码树中。在发布内核2.6后,ALSA已经内建在稳定的内核版本中并将广泛地使用。在内核设备驱动层,ALSA提供了alsa-driver,同时在应用层,ALSA为我们提供了alsa-lib,应用程序只要调用alsa-lib提供的API,即可以完成对底层音频硬件的控制。
3.ALSA基础
ALSA由许多声卡的声卡驱动程序组成,同时它也提供一个称为libasound的API库。应用程序开发者应该使用libasound而不是内核中的ALSA接口。因为libasound提供最高级并且编程方便的编程接口。并且提供一个设备逻辑命名功能,这样开发者甚至不需要知道类似设备文件这样的低层接口。
用户空间的alsa-lib对应用程序提供统一的API接口,这样可以隐藏了驱动层的实现细节,简化了应用程序的实现难度。内核空间中,alsa-soc其实是对alsa-driver的进一步封装,他针对嵌入式设备提供了一些列增强的功能。
4.ALSA体系结构:
ALSA API可以分解成以下几个主要的接口:
1控制接口:提供管理声卡注册和请求可用设备的通用功能
2 PCM接口:管理数字音频回放(playback)和录音(capture)的接口。它是开发数字音频程序最常用到的接口。
3 Raw MIDI接口:支持MIDI(Musical Instrument Digital Interface),标准的电子乐器。这些API提供对声卡上MIDI总线的访问。这个原始接口基于MIDI事件工作,由程序员负责管理协议以及时间处理。
4定时器(Timer)接口:为同步音频事件提供对声卡上时间处理硬件的访问。
5时序器(Sequencer)接口
6混音器(Mixer)接口设备命名API库使用逻辑设备名而不是设备文件。
5.伪代码
一个典型的声音程序使用PCM的程序通常类似下面的伪代码:
1.打开回放或录音接口
2.设置硬件参数(访问模式,数据格式,信道数,采样率,等等)
2.while有数据要被处理:读PCM数据(录音)或写PCM数据(回放)
3.关闭接口
三.ALSA编译安装
1.ALSA相关库下载
官方主页http://www.alsa-project.org/
主要跟编程相关是
·alsa-lib. ALSA应用库(最常用)
·ftp://ftp.alsa-project.org/pub/lib/alsa-lib-1.0.22.tar.bz2
·alsa-driver一些常见芯片的ALSA驱动代码,一般内核会集成.
·ftp://ftp.alsa-project.org/pub/driver/alsa-driver-1.0.22.1.tar.bz2
·alsa-firmware一些DSP或ASIC的专用的微码(运在芯片之上,启动时由LINUX装入到硬件中).
·ftp://ftp.alsa-project.org/pub/firmware/alsa-firmware-1.0.20.tar.bz2
·alsa-utils一般ALSA小的测试工具.如aplay/arecord播放和录音小程序.
·ftp://ftp.alsa-project.org/pub/utils/alsa-utils-1.0.22.tar.bz2
·alsa-oss用alsa接口模拟旧的oss接口.
·ftp://ftp.alsa-project.org/pub/oss-lib/alsa-oss-1.0.17.tar.bz2
其中alsa-driver,alsa-firwware是内核开发者所接触的东西,对于已经正常运行硬件,通常意味着这一部分已经整合到内核当中,无需修改.
而alsa-utils主要是测试一些小工具.
因此对于一个应用程序开发者,或者嵌入式应用开发者,接触到主要是alsa-lib编译出来的库libasound.
2.ALSA驱动测试
cat
/proc/asound/devices驱动测试
ls -l/dev/snd设备测试
aplay –h工具alsa-utils测试
3.嵌入式linuxALSA移植
·ALSA driver移植
·ALSA lib移植.
解压tar xvjf alsa-lib-1.0.22.tar.bz2
cd alsa-lib-1.0.22
生成Makefile
./configure --host=arm-linux --prefix=$PWD/../../output/arm-linux --enable-static --enable-shared --disable-python --with-configdir=/usr/local/share --with-plugindir=/usr/local/lib/alsa_lib
在这里要注意--with--configdir的选项.它将影响include/config.h中的ALSA_CONFIG_DIR目录.
它默认是你的--prefix目录.这样在嵌入式交叉编译将是一个桌面机的路径,在libasoud.so运行.会提示,如果出来这个提示,一般都是ALSA_CONFIG_DIR路径错误造成的.
ALSA lib pcm.c:2145:(snd_pcm_open_noupdate) Unknown PCM default
aplay: main:546: audio open error: No such file or directory
--with-plugindir也是同样道理了.它是设为ALSA_PLUGIN_DIR宏.
编译make
安装make install
开发板发布注意:
在开发板上发布alsa库.除了libasound.so库以外,必须还要把alsa.conf发布到板上--with-configdir所指向目录下的alsa目录,否则还是会报"audio open error: No such file ordirectory".
这个文件可以在make install后在你安装目录下的share找到alsa目录,把这个目录整个拷贝到开发板即可.
·ALSA utils移植
解压:tar xvjf alsa-utils-1.0.22.tar.bz2
cdalsa-utils-1.0.22
生成Makefile
./configure --host=arm-linux --prefix=$PWD/../../output/arm-linux --enable-static --enable-shared --with-configdir=/usr/local/share --with-libiconv-prefix=$PWD/../../output/arm-linux CFLAGS="-I$PWD/../../output/arm-linux/include" LDFLAGS="-L$PWD/../../output/arm-linux/lib -lasound -liconv" --disable-alsamixer --disable-xmlto
注意这里LDFLAGS是必须,否则会找不到libasound.另外alsamixer是一个ncurses程序,基本上在嵌入式终端上很难移植.所以这里取消掉.--disable-xmlto也是因为找不到库.
编译make
安装make install
四.ALSA录音demo
#include
#include
#include
main (int argc, char *argv[])
{
int i;
int err;
short buf[128];
snd_pcm_t *capture_handle; // PCM设备句柄
snd_pcm_hw_params_t *hw_params;//硬件信息和PCM流配置
//1.打开PCM,最后一个参数0为标准配置
if ((err = snd_pcm_open (&capture_handle,argv[1], SND_PCM_STREAM_CAPTURE, 0)) < 0) {
fprintf (stderr, "cannot open audiodevice %s (%s)\n",
argv[1],
snd_strerror (err));
exit (1);
}
//2.分配snd_pcm_hw_params_t结构体
if ((err = snd_pcm_hw_params_malloc(&hw_params)) < 0) {
fprintf (stderr, "cannot allocatehardware parameter structure (%s)\n",
snd_strerror (err));
exit (1);
}
//3.初始化hw_paraws
if ((err = snd_pcm_hw_params_any (capture_handle,hw_params)) < 0) {
fprintf (stderr, "cannot initializehardware parameter structure (%s)\n",
snd_strerror (err));
exit (1);
}
//4.初始化访问权限
if ((err = snd_pcm_hw_params_set_access(capture_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
fprintf (stderr, "cannot set accesstype (%s)\n",
snd_strerror (err));
exit (1);
}
//5.初始化采样格式SND_PCM_FORMAT_U8,16位
if ((err = snd_pcm_hw_params_set_format(capture_handle, hw_params, SND_PCM_FORMAT_S16_LE)) < 0) {
fprintf (stderr, "cannot set sampleformat (%s)\n",
snd_strerror (err));
exit (1);
}
1.//6.设置采样率,如果硬件不支持我们设置的采样率,将使用最接近的
2.//val = 44100,有些录音采样频率固定为8KHz
if ((err = snd_pcm_hw_params_set_rate_near(capture_handle, hw_params, 44100, 0)) < 0) {
fprintf (stderr, "cannot set samplerate (%s)\n",
snd_strerror (err));
exit (1);
}
//7.设置通道数量
if ((err = snd_pcm_hw_params_set_channels(capture_handle, hw_params, 2)) < 0) {
fprintf (stderr, "cannot set channelcount (%s)\n",
snd_strerror (err));
exit (1);
}
//8.设置hw_params
if ((err = snd_pcm_hw_params (capture_handle,hw_params)) < 0) {
fprintf (stderr, "cannot setparameters (%s)\n",
snd_strerror (err));
exit (1);
}
snd_pcm_hw_params_free (hw_params);
if ((err = snd_pcm_prepare (capture_handle)) <0) {
fprintf (stderr, "cannot prepareaudio interface for use (%s)\n",
snd_strerror (err));
exit (1);
}
//读取数据
for (i = 0; i < 10; ++i) {
if ((err = snd_pcm_readi (capture_handle,buf, 128)) != 128) {
fprintf (stderr, "read fromaudio interface failed (%s)\n",
snd_strerror (err));
exit (1);
}
}
//10.关闭PCM设备句柄
snd_pcm_close (capture_handle);
exit (0);
}
Alsa编译安装:http://blog.csdn.net/liu_chunhai/article/details/6582090
http://blog.csdn.net/shui1025701856/article/details/7646197
http://www.cnblogs.com/cslunatic/p/3677729.html
http://blog.csdn.net/zd394071264/article/details/8300045
http://blog.csdn.net/ropenyuan/article/details/9344299
slsa编译
http://blog.chinaunix.net/uid-23065002-id-3884658.html
https://www.oschina.net/news/72059/alsa-lib-1-1-1
http://www.360doc.com/content/11/0613/13/168576_126609790.shtml