Alsa中PCM参数设置⭐⭐

时间:2021-12-19 23:03:33

1) PCM设备的句柄.
2) 指定同时可供回放或截获的PCM流的方向
3) 提供一些关于我们想要使用的设置选项的信息,比如缓冲区大小,采样率,PCM数据格式等
4) 检查硬件是否支持设置选项.
   4.1) 初始化PCM变量
   4.2) 分配hwparams结构
   4.3) 打开PCM设备
   4.4) 以声卡的全部设置选项空间来初始化hwparams结构
   4.5) 指定访问类型,采样格式,采样率,声道号码,周期数目以及周期大小
        a) 访问类型 :指定了哪一个多声道数据储存在缓冲区的方法.
             *对于交错访问,缓冲区里的每一个帧为声道容纳连续的采样数据.
             *对于非交错访问,每一个周期为第一个声道容纳所有采样数据接着是第二个声道的采样数据
        b) 缓冲区尺寸的单元依赖于函数.一些时候是字节,一些时候是必须指定的帧的数目.
           一个帧是对所有声道的采样数据数组.对于16位立体声数据,一个帧的长度是4个字节.(一个信道2字节,1帧两个通道(可以更多通道))
           如果你的硬件不支持2的N次方的缓冲区大小,你可以使用snd_pcm_hw_params_set_buffer_size_near函数.这个函数工作起来与snd_pcm_hw_params_set_rate_near相似.
5) 为PCM设备申请由pcm_handle指向的设置选项

样本长度(sample):样本是记录音频数据最基本的单位,常见的有8位和16位。

通道数(channel):该参数为1表示单声道,2则是立体声。

桢(frame):桢记录了一个声音单元,其长度为样本长度与通道数的乘积。

采样率(rate):每秒钟采样次数,该次数是针对桢而言。

周期(period):音频设备一次处理所需要的桢数,对于音频设备的数据访问以及音频数据的存储,都是以此为单位。

交错模式(interleaved):是一种音频数据的记录方式,在交错模式下,数据以连续桢的形式存放,即首先记录完桢1的左声道样本和右声道样本(假设为立体声格式),再开始桢2的记录。而在非交错模式下,首先记录的是一个周期内所有桢的左声道样本,再记录右声道样本,数据是以连续通道的方式存储。不过多数情况下,我们只需要使用交错模式就可以了。

备注资料:

设备命名
API 库使用逻辑设备名而不是设备文件。设备名字可以是真实的硬件名字也可以是插件名字。硬件名字使用hw:i,j这样的格式。其中i是卡号,j是这块声卡上的设备号。第一个声音设备是hw:0,0.这个别名默认引用第一块声音设备并且在本文示例中一真会被用到。插件使用另外的唯一名字。比如 plughw:,表示一个插件,这个插件不提供对硬件设备的访问,而是提供像采样率转换这样的软件特性,硬件本身并不支持这样的特性。

声音缓存和数据传输
每个声卡都有一个硬件缓存区来保存记录下来的样本。当缓存区足够满时,声卡将产生一个中断。内核声卡驱动然后使用直接内存(DMA)访问通道将样本传送到内存中的应用程序缓存区。类似地,对于回放,任何应用程序使用DMA将自己的缓存区数据传送到声卡的硬件缓存区中。
这样硬件缓存区是环缓存。也就是说当数据到达缓存区末尾时将重新回到缓存区的起始位置。ALSA维护一个指针来指向硬件缓存以及应用程序缓存区中数据操作的当前位置。从内核外部看,我们只对应用程序的缓存区感兴趣,所以本文只讨论应用程序缓存区。

应用程序缓存区的大小可以通过ALSA库函数调用来控制。缓存区可以很大,一次传输操作可能会导致不可接受的延迟,我们把它称为延时(latency)。为了解决这个问题,ALSA将缓存区拆分成一系列周期(period)(OSS/Free中叫片断fragments).ALSA以period为单元来传送数据。
一个周期(period)存储一些帧(frames)。每一帧包含时间上一个点所抓取的样本。对于立体声设备,一个帧会包含两个信道上的样本。
Alsa中PCM参数设置⭐⭐

-

Alsa中PCM参数设置⭐⭐

周期若干帧,每帧若干通道(交错),每一通道数据即是当前时刻该电压值对应的二进制数据(采样深度的位数);

图1展示了分解过程:一个缓存区分解成周期,然后是帧,然后是样本。图中包含一些假定的数值。图中左右信道信息被交替地存储在一个帧内。这称为交错 (interleaved)模式。在非交错模式中,一个信道的所有样本数据存储在另外一个信道的数据之后。

period(周期):硬件中中断间的间隔时间。它表示输入延时每一个时间T给hardware传输一次,当然数据大小为一个period时间内的buf;
声卡接口中有一个指针来指示声卡硬件缓存区中当前的读写位置。只要接口在运行,这个指针将循环地指向缓存区中的某个位置
frame size = sizeof(one sample) * nChannels
alsa中配置的缓存(buffer)和周期(size)大小在runtime中是以帧(frames)形式存储的
period_bytes = frames_to_bytes(runtime, runtime->period_size);
bytes_to_frames()

The period and buffer sizes are not dependent on the sample format because they are measured in frames; you do not need to change them.

Over and Under Run
当一个声卡活动时,数据总是连续地在硬件缓存区和应用程序缓存区间传输。但是也有例外。在录音例子中,如果应用程序读取数据不够快,循环缓存区将会被新的数据覆盖。这种数据的丢失被称为overrun.在回放例子中,如果应用程序写入数据到缓存区中的速度不够快,缓存区将会"饿死"。这样的错误被称为"underrun"。在ALSA文档中,有时将这两种情形统称为"XRUN"。适当地设计应用程序可以最小化XRUN并且可以从中恢复过来。

http://blog.csdn.net/maopig/article/details/8667859