[ 工具 ] ___ Library : ALSA

一、引言


ALSA(Advanced Linux Sound Architecture)是 Linux 操作系统上的音频驱动程序架构,旨在提供全面支持音频和 MIDI 功能。ALSA 架构的诞生填补了早期音频系统在支持现代音频硬件和音频功能上的空白,为 Linux 系统带来了更优越的音频体验。

(一)发展历程


在 Linux 的早期阶段,音频支持相对简单,存在一些限制。当时的音频系统主要依赖于 OSS(Open Sound System)作为音频驱动程序架构和用户空间音频接口。

OSS 最初由 Hannu Savolainen 开发,为 Linux 系统提供标准音频接口。它允许应用程序直接访问音频硬件,从而直接控制音频设备。这种直接的访问方式在早期的 Linux 系统中得到广泛采用,因其相对简单和直观。

然而随着时间的推移和对音频功能需求的增加,人们开始意识到 OSS 在满足现代音频需求方面存在局限性。这促使了对 Linux 音频系统的进一步发展和改进,以满足更复杂的音频处理需求。

在这个背景下,ALSA 的出现成为了 Linux 音频系统发展的重要转折点,致力于解决早期音频系统的局限性,并为 Linux 提供了灵活、功能更强大的音频架构。透彻了解早期音频系统的限制,可以更好地理解 ALSA 的诞生及其在 Linux 音频系统中的重要性。

(二)最初动机


早期的 Linux 音频系统存在一系列问题和限制,这些问题成为 ALSA 架构诞生的原因。

早期的 Linux 音频系统在支持多声道音频方面存在限制。多声道音频处理对于专业音频工作站、游戏和多媒体应用至关重要。然而在早期的 Linux 系统中,对于多声道音频的完全支持并不容易实现。

随着音频硬件的不断发展,特别是在 PC 音频领域,早期的 Linux 音频系统面临对现代音频硬件的适配性挑战,包括对新型音频接口、高清晰度音频格式以及音频处理能力的支持。专业音频应用、实时音频处理和游戏等领域对低延迟和高性能的需求不断增加,然而早期的 Linux 音频系统在这方面的表现并不理想。

早期,Linux 音频系统缺乏一个统一的、全面的音频架构,这导致了不同的音频驱动程序和接口之间的不兼容性,使得音频设备的配置和管理变得复杂。ALSA 的最初动机是解决这些问题,提供一个更灵活、功能更强大的音频架构。ALSA 的设计目标包括:

  1. 提供全面支持多声道音频,包括5.1、7.1等多声道配置。
  2. 适配现代音频硬件,包括支持新型音频接口、高清晰度音频格式等。
  3. 实现低延迟和高性能的音频处理能力,满足实时音频处理等需求。
  4. 提供统一的音频架构,使不同的音频设备和驱动程序能更好地协同工作,并简化音频设备的配置和管理。

通过解决这些问题,ALSA 成为了 Linux 音频系统的主流架构,并为 Linux 提供了强大的音频支持,使得 Linux 在音频领域得以迅速发展和应用。

(三)重要作用


ALSA 作为 Linux 标准音频架构的确立是一个漫长而渐进的过程。在早期,Linux 的音频支持是通过 OSS(Open Sound System)来实现的,但是 OSS 在处理某些现代音频硬件和高级功能上存在一些限制。随着时间的推移,Linux 内核开发者意识到了这些限制,并开始寻求更先进的解决方案。ALSA 的出现填补了这一空白,并逐渐成为 Linux 标准音频架构。

ALSA 首次被合并到 Linux 内核中是在 2.5 版本。作为 Linux 内核的一部分,它提供了对音频硬件的驱动支持和音频功能的抽象接口。随着内核的不断演进,ALSA 也在内核中得到了持续的改进和优化,以适应新的硬件和需求。

ALSA 的出现推动了 Linux 音频系统的整体发展。它为 Linux 带来了更先进的音频功能,包括对多声道音频、低延迟音频处理、音频效果处理等方面的支持。ALSA 的灵活性和功能丰富性为 Linux 音频应用的发展提供了更多可能性,也吸引了更多开发者和厂商加入到 Linux 音频生态系统中。

ALSA 在 Linux 生态系统中的地位和影响日益增强。它不仅为 Linux 提供了强大的音频支持,也成为了许多应用程序和框架的基础。同时,由于 ALSA 的开放性和灵活性,它也促进了许多音频相关的开源项目和社区的发展,为 Linux 用户提供了丰富多样的音频应用选择。

通过深入了解 ALSA 在 Linux 发展中的角色,读者可以更好地理解 ALSA 对 Linux 音频系统发展的推动作用,以及它在不断发展的 Linux 生态系统中的地位和影响。

(四)应对局限


ALSA已完全集成到 Linux 内核中,不再作为一个外部模块,而是成为 Linux 内核的一部分。这种融合使得 ALSA 能够更好地与 Linux 内核的其他组件交互,提供更高效、更稳定的音频支持。此举也为 Linux 发行版提供了一个统一的音频架构,使得用户无需额外安装第三方驱动程序或框架即可享有完整的音频功能。

ALSA的引入和发展推动了 Linux 音频系统的整体进步。它为 Linux 用户带来了更卓越的音频体验,使得 Linux 在音频处理能力上能够与其他操作系统媲美。ALSA 的全面支持现代音频硬件和提供更多高级音频功能的特性,为 Linux 用户提供了更多选择和灵活性,使得 Linux 在音频领域的应用范围更加丰富。

作为 Linux 标准音频架构,ALSA 在 Linux 生态系统中扮演着重要角色。其稳定性、可靠性以及对现代音频硬件的广泛支持,使得 ALSA 成为了众多 Linux 发行版的首选音频架构。同时,ALSA 为其他音频框架和工具提供了良好的基础,使得整个 Linux 音频生态系统更加丰富和多样化。

在早期的音频系统中存在对于现代音频硬件的支持局限性,例如对高保真音频、多声道音频以及特定音频接口的支持。ALSA 凭借其先进的架构设计和灵活的驱动程序模型,能够更好地支持各种现代音频硬件,包括内置音频芯片、外部 USB 音频接口、专业音频设备等。这使得用户能够更加方便地在 Linux 系统上使用各种音频设备。

ALSA 还全面支持高级音频功能,包括多声道音频、低延迟音频处理、实时音频流处理等。这些功能对于专业音频制作、音频编辑、游戏开发等领域至关重要。ALSA 的架构设计和强大的驱动程序模型使得它能够满足这些领域对音频处理性能和功能的要求,为 Linux 用户提供了更广泛的音频应用场景。

二、体系结构


(一)组成部分


ALSA(Advanced Linux Sound Architecture)是 Linux 操作系统中用于处理音频的声音体系结构。它由多个组件组成,包括驱动程序、库、工具和应用程序。

1. 驱动程序


ALSA 驱动程序是与硬件设备交互的组件,它负责控制和管理音频设备的输入和输出。在 Linux 系统中,每个音频设备都需要特定的驱动程序来与操作系统进行通信。这些驱动程序允许操作系统识别和与音频设备进行交互,包括声卡、USB 音频设备、蓝牙音频设备等。

2. 库


ALSA 库是一组函数和工具,用于开发音频应用程序。它提供了一系列的 API,使开发者能够访问和控制音频设备的功能。ALSA库为开发者提供了一种标准的接口,使他们能够轻松地开发音频应用程序,并与各种音频设备进行交互。

3. 工具


ALSA 提供了一些命令行工具,用于配置和测试音频设备。这些工具可以用于调整音量、设置音频输入和输出等。一些常用的 ALSA 工具包括alsamixer(用于调整音量和其他音频设置)、aplay(用于播放音频文件)、arecord(用于录制音频)、apulse(用于PulseAudio的ALSA兼容层)等。

4. 应用程序


ALSA 还提供了一些应用程序,如混音器和音频播放器,用于处理和播放音频数据。这些应用程序提供了用户友好的界面,允许用户对音频设备进行控制和管理,以及播放和处理音频数据。

除了上述模块之外,ALSA还提供了一些辅助工具和库,例如alsa-utilsalsa-lib等,用于简化音频设备的配置和管理,以及开发音频应用程序,当前要移植的是一个使用插件系统与Linux内核中的Alsa和虚拟设备接口的库:alsa-lib

(二)层次结构


  1. 硬件层:包括音频设备的驱动程序,用于与硬件设备进行通信。这些驱动程序位于操作系统内核中,负责管理和控制音频设备的输入和输出。
  2. 核心层:包括 ALSA 的核心组件,如核心驱动程序、库和工具。这些组件提供了对音频设备的控制和管理功能,以及对音频数据的处理和传输能力。
  3. 应用层:由开发者使用 ALSA 库和工具开发的应用程序。这些应用程序可以实现音频数据的处理、播放和录制等功能,通过 ALSA 库与音频设备进行交互。

(三)架构


  1. 内核模块:在内核中运行的驱动程序,用于与硬件设备进行通信。这些内核模块负责管理和控制音频设备,以及提供对音频设备的底层访问能力。
  2. 用户态库:开发者用于开发音频应用程序的库,提供了一系列的API。这些库允许开发者访问和控制音频设备的功能,以及处理和传输音频数据。

(四)模块


  1. PCM 模块:负责音频数据的输入和输出,包括硬件参数和软件参数的配置。PCM模块提供了对音频数据的处理和传输,允许应用程序读取和写入音频数据到声卡。它还负责处理音频数据的采样率、位深度和通道数等参数,以确保音频数据能够正确地传输和处理。
  2. Mixer 模块:用于控制音频设备的音量、平衡、通道选择等。它允许用户调整声卡的各项参数,以便实现对音频输出的控制。通过 Mixer 模块,用户可以调整音频设备的音量大小、左右声道的平衡、以及选择不同的音频输入和输出通道,从而实现对音频输出的个性化控制。
  3. Timer 模块:提供高精度的定时器功能,用于音频数据处理和同步。在音频应用程序中,精确的时间控制对于音频数据的处理和同步非常重要。Timer 模块允许应用程序精确地控制音频数据的处理时间,确保音频数据能够按照预期的时间进行处理和传输。
  4. MIDI 模块:用于 MIDI 音乐合成和控制,支持多种 MIDI 设备和音色库。MIDI 模块允许应用程序与 MIDI 设备进行交互,包括发送和接收 MIDI 消息,控制音乐合成器的音色和音高等参数,以及实现对 MIDI 设备的实时控制和管理。
  5. DSP 模块:用于数字信号处理,包括音频效果处理、滤波器、均衡器等。它提供了对音频数据的实时处理能力,允许应用程序对音频数据进行各种数字信号处理,如实时音频效果处理、音频滤波、均衡器调节等,以实现音频数据的增强和改进。
  6. Sequencer 模块:用于音频序列处理和控制,支持多通道音频输入和输出。它允许应用程序对音频数据进行序列处理,包括录制、播放、编辑和合成多通道音频数据,以实现对音频序列的精确控制和处理。
  7. RawMidi模块:提供原始 MIDI 数据的输入和输出,用于 MIDI 设备的低级访问。通过 RawMidi 模块,应用程序可以直接读取和写入原始的MIDI数据,以实现对 MIDI 设备的底层访问和控制。
  8. Control 模块:用于音频设备的控制和管理,包括音频设备的状态查询和设置。它提供了对音频设备状态的查询和设置功能,允许应用程序对音频设备进行状态监控和控制,以确保音频设备能够按照预期的方式进行工作。
  9. PCM Plugins 模块:提供多种音频效果插件,例如重采样、声像定位、混响等。这些插件允许对音频数据进行实时处理,以实现各种音频效果。PCM Plugins 模块为应用程序提供了丰富的音频处理功能,允许应用程序对音频数据进行各种效果处理,以实现更加丰富和多样化的音频效果。

三、构建


  1. 访问官网进行获取源代码,并创建安装目录,解压源码包,进入目录进行配置
localhost@linux:~$ tar jxvf alsa-lib-x.y.z.tar.bz2
localhost@linux:~$ cd ~/alsa-lib-x.y.z/
localhost@linux:~/alsa-lib-x.y.z$ ./configure --host=arm-none-linux-gnueabi --prefix=${HOME}/alsa2arm --with-configdir=/usr/local/share --with-plugindir=/usr/local/lib  --with-softfloat --with-gnu-ld --disable-python --enable-dependency-tracking CC=$(which arm-none-linux-gnueabi-gcc) RANLIB=$(which arm-none-linux-gnueabi-ranlib) 
  1. 编译并安装
localhost@linux:~/alsa-lib-x.y.z$ make
localhost@linux:~/alsa-lib-x.y.z$ sudo make install
  1. 查看文件格式是否符合所属平台
localhost@linux:~/alsa2arm$ ls -la
total 0
drwxrwxrwx 1 linux linux 4096 Dec 13 01:03 .
drwxr-xr-x 1 linux linux 4096 Dec 13 01:03 ..
drwxrwxrwx 1 linux linux 4096 Dec 13 01:03 bin
drwxr-xr-x 1 linux linux 4096 Dec 13 01:03 include
drwxrwxrwx 1 linux linux 4096 Dec 13 01:03 lib
drwxrwxrwx 1 linux linux 4096 Dec 13 01:03 share
localhost@linux:~/alsa2arm/lib$ cd lib
localhost@linux:~/alsa2arm/lib$ file libasound.so.2.0.0
libasound.so.2.0.0: ELF 32-bit LSB shared object, ARM, EABI5 version 1 (SYSV), dynamically linked, with debug_info, not stripped

确认无误后,即可将对应的库文件和相关的配置文件上传到开发板libusr目录中,当然也可以配合其他库文件进行相关的移植。

  1. 整合相关配置文件
localhost@linux:~/alsa-lib-x.y.z$ cd src/conf
localhost@linux:~/alsa-lib-x.y.z$ mkdir usr/local/share -p
localhost@linux:~/alsa-lib-x.y.z$ cp pcm cards ctl alsa.conf usr/local/share -r
localhost@linux:~/alsa-lib-x.y.z$ mv usr ${HOME}/alsa2arm
localhost@linux:~/alsa-lib-x.y.z$ rm -rf ${HOME}/alsa2arm/usr/cards/Makefile* ${HOME}/alsa2arm/usr/pcm/Makefile* ${HOME}/alsa2arm/usr/ctl/Makefile*
  1. 在目标板上,以下文件必须被拷贝至对应位置:
  • 库文件,放在/lib中;
  • 配置文件,应放在/usr/local/share中,与编译时指定的目录相同;
  • 实用程序,util能产生aplayamixerarecord等许多实用程序,这些文件可放在系统的环境变量的所指定的目录中,例如:/bin
  • 必须保证有/dev/snd目录中,此目录下应包含以下几个设备文件(驱动):controlC0pcmC0D0cpcmC0D0ptimer...
localhost@linux:~# cat snd.sh
#! /bin/sh

mkdir /dev/snd    
cd /dev/snd										 
mknod dsp c 14 3                                 
mknod audio c 14 4                               
mknod mixer c 14 0                               
mknod controlC0 c 116 0                          
mknod seq c 116 1                                
mknod pcmC0D0c c 116 24                          
mknod pcmC0D0p c 116 16                          
mknod pcmC0D1c c 116 25                          
mknod pcmC0D1p c 116 17                           
mknod timer c 116 33 
root@arm:~# chmod +x snd.sh
root@arm:~# ./snd.sh

注:如果以上文件已经在/dev下,可拷贝到/dev/snd目录中,如果没有则可以使用以下脚本创建:

四、PCM 例程


ALSAPCM 配置步骤通常如下:

  • 打开 PCM 设备:使用 ALSA 库函数 snd_pcm_open 打开 PCM 设备。需要指定 PCM 设备的名称、设备类型、访问方式和打开模式等参数。
  • 设置硬件参数:使用 ALSA 库函数 snd_pcm_hw_params_* 配置 PCM 设备的硬件参数,包括采样率、通道数、位深度等音频格式参数,以及缓冲区大小和周期大小等传输参数;
  • 设置软件参数:使用 ALSA 库函数 snd_pcm_sw_params_* 配置 PCM 设备的软件参数,包括音频格式转换、混音、音量控制、信号处理等功能;
  • 分配缓冲区:使用ALSA库函数 snd_pcm_malloc 分配 PCM 设备所需的缓冲区。需要根据缓冲区大小和周期大小等参数进行分配;
  • 写入数据:使用 ALSA 库函数 snd_pcm_writeisnd_pcm_writenPCM 设备写入音频数据。写入数据前需要将数据存储在缓冲区中,并设置正确的缓冲区位置和数据大小等参数;
  • 读取数据:使用 ALSA 库函数 snd_pcm_readisnd_pcm_readnPCM 设备读取音频数据。读取数据后需要将数据存储在缓冲区中,并设置正确的缓冲区位置和数据大小等参数;
  • 关闭 PCM 设备:使用 ALSA 库函数 snd_pcm_close 关闭 PCM 设备,释放相关资源。

需要注意的是,不同的音频设备和应用场景可能需要不同的 PCM 配置参数。因此,在进行PCM配置之前,需要根据具体的需求和硬件性能进行参数设置和优化。

同时,在 PCM 数据输入和输出过程中,需要根据数据大小、传输速率等参数进行缓冲区的调整和管理,以确保音频数据的稳定和质量。

(一)程序编译


编译时请添加 -lasound 参数,且确保你已包含了:

#include <alsa/asoundlib.h>

(二)流程框图


  1. 典型音频应用程序:
粗略结构
打开 `PCM` 设备 : snd_pcm_open
配置 `PCM` 设备的参数
配置 `PCM` 设备的硬件参数
配置 `PCM` 设备的软件参数
`PCM` 数据处理
常规访问
直接通信
关闭 `PCM` 设备 : snd_pcm_close

ALSAPCMPulse Code Modulation)模块是用于音频输入和输出的重要组件。在使用PCM模块之前,需要配置硬件参数和软件参数,以确保音频可以正确地传输和处理。

配置`PCM`设备的参数
硬件参数
分配硬件参数结构体
snd_pcm_hw_params_alloca
初始化硬件参数
snd_pcm_hw_params_any
配置硬件参数 : snd_pcm_hw_params_set_*
设置硬件重采样
snd_pcm_hw_params_set_rate_resample
设置访问权限类型
snd_pcm_hw_params_set_access
设置样本采样格式
snd_pcm_hw_params_set_format
设置通道个数
snd_pcm_hw_params_set_channels
设置采样率
snd_pcm_hw_params_set_rate_near
设置缓冲大小
snd_pcm_hw_params_set_buffer_size_near
设置周期大小
snd_pcm_hw_params_set_period_size_near
设置硬件参数
snd_pcm_hw_params
软件参数
使用标准分配软件配置空间容器
snd_pcm_sw_params_alloca
初始化`PCM`设备的软件参数
snd_pcm_sw_params_current
配置各项软件参数
设置启动阈值
snd_pcm_sw_params_set_start_threshold
设置停止阈值
snd_pcm_sw_params_set_stop_threshold
设置可用最小值
snd_pcm_sw_params_set_avail_min
设置时间戳类型
snd_pcm_sw_params_set_tstamp_type
设置时间戳模式
snd_pcm_sw_params_set_tstamp_mode
设置静默阈值
snd_pcm_sw_params_set_silence_threshold
设置静音大小
snd_pcm_sw_params_set_silence_size
设置周期事件
snd_pcm_sw_params_set_period_event
应用软件参数设置
snd_pcm_sw_params

硬件参数包括采样率、通道数、位深度等音频格式参数,以及缓冲区大小和周期大小等传输参数。硬件参数需要与实际的音频硬件相匹配,以确保音频数据可以正确地传输和处理。如果硬件参数设置不正确,可能会导致音频质量下降、延迟增加、噪音和断续声等问题。

软件参数包括音频格式转换、混音、音量控制、信号处理等功能。这些功能可以在PCM模块中通过软件实现,以提高音频的质量和功能。软件参数可以根据具体的应用场景进行配置,以满足不同的需求和要求。

需要注意的是,硬件参数和软件参数之间存在一定的权衡关系。较小的缓冲区和周期可以降低延迟,但可能会增加音频中断的风险;较大的缓冲区和周期可以提高稳定性,但会增加延迟。因此,在配置PCM模块时,需要根据具体的应用场景和硬件性能进行权衡,以达到最佳的音频效果。

PCM数据处理:

`PCM`数据处理
常规访问
直接通信
获取周期大小
snd_pcm_hw_params_get_period_size
准备`PCM`以供使用
snd_pcm_prepare
获取`PCM`设备状态
snd_pcm_state
返回准备捕获/回放的帧数
snd_pcm_avail_update
启动`PCM`设备
snd_pcm_start
等待`PCM`设备准备就绪
snd_pcm_wait
返回准备捕获/回放的帧数
snd_pcm_avail_update
获取存储样本的位置
snd_pcm_mmap_begin
从`PCM`读取一帧的数据
交错帧 : snd_pcm_mmap_readi
非交错帧 : snd_pcm_mmap_readn
将一帧的数据写入`PCM`
交错帧 : snd_pcm_mmap_writei
非交错帧 : snd_pcm_mmap_writen
已完成对请求的区域的访问
snd_pcm_mmap_commit
从`PCM`读取一帧的数据
交错帧 : snd_pcm_readi
非交错帧 : snd_pcm_readn
停止`PCM`设备并删除挂起的帧
snd_pcm_drop
将一帧的数据写入`PCM`
交错帧 : snd_pcm_writei
非交错帧 : snd_pcm_writen
停止保留挂起帧的`PCM`
snd_pcm_drain
获取周期时间
snd_pcm_hw_params_get_period_time
欠运行和暂停恢复
欠载状态
从运行不足中恢复 准备`PCM`以供使用
snd_pcm_prepare
挂起状态
从挂起中恢复 不会丢失任何样本
snd_pcm_resume
准备`PCM`以供使用
snd_pcm_prepare

(三)函数详解


1. 打开 PCM 设备;

snd_pcm_openALSA库函数之一,用于打开PCM设备并获取PCM设备的句柄(handle)。以下是snd_pcm_open()函数的详解:

  • 函数原型:
int snd_pcm_open(snd_pcm_t **pcm, const char *name, snd_pcm_stream_t stream, int mode);
  • 参数说明:
参数说明
snd_pcm_t **pcm指向 PCM 设备句柄(handle)的指针,函数将根据打开的 PCM 设备返回句柄
const char *name即将要打开的PCM设备名字
snd_pcm_stream_t streamPCM 数据流的类型
int mode当前为模式参数,用于指定打开PCM设备的模式:
1. (0,默认模式:阻塞模式)
2. (SND_PCM_NONBLOCK,非阻塞模式)
3. (SND_PCM_ASYNC,异步模式)

PCM流(方向)有两种,一种是回放流,一种是捕获流,可以自行填写对应参数进行设置:

/** PCM 流 (方向) */
typedef enum _snd_pcm_stream {
	/** 回放流 */
	SND_PCM_STREAM_PLAYBACK = 0,
	/** 捕获流 */
	SND_PCM_STREAM_CAPTURE,
	SND_PCM_STREAM_LAST = SND_PCM_STREAM_CAPTURE
} snd_pcm_stream_t;

name 表示 PCM 设备的名称,可以填写以下参数,通过指定不同的 name 参数,可以打开不同的 PCM 设备:

  • "default":表示使用默认的 PCM 设备,即系统默认音频设备;
  • "hw:card,device":表示使用指定的硬件设备。其中 card 表示声卡编号,device 表示设备编号。例如,strdup("hw:0,0")表示使用第一个声卡的第一个设备;
  • "plughw:card,device":表示使用指定的硬件设备,并使用默认的音频格式进行转换。该选项会自动使用一个软件插件来转换音频格式,从而允许应用程序使用与PCM设备不同的音频格式进行输入和输出。
  • "hw:card,subdev":表示使用指定的硬件设备的子设备。其中card表示声卡编号,subdev表示子设备编号。

一般情况下,应用程序会使用默认的 PCM 设备进行音频输入和输出,而不需要显式地指定 name 参数。

2. 配置硬件参数;

在使ALSAPCM时,有一些硬件参数是必须要设置的,以保证音频数据的传输和处理正常。这些必须要设置的硬件参数包括:

  • 采样率(Sample Rate:指每秒钟采集或播放的音频样本数,通常以赫兹(Hz)为单位表示。必须要设置的原因是,采样率决定了音频信号的带宽和频率响应,如果设置不正确,可能会导致音频失真或不完整;
  • 通道数(Channel:指每个音频样本中包含的声道数,通常有单声道(Mono)和立体声(Stereo)两种。必须要设置的原因是,通道数决定了音频的声音效果和空间定位,如果设置不正确,可能会导致音频声音失衡或空间感不明显;
  • 位深度(Bit Depth:指每个音频样本中包含的位数,通常有8位、16位、24位等多种位深度。必须要设置的原因是,位深度决定了音频信号的动态范围和精度,如果设置不正确,可能会导致音频失真或噪声过大;
  • 缓冲区大小(Buffer Size:指音频数据在内存中的缓冲区大小,通常以字节或采样数为单位表示。必须要设置的原因是,缓冲区大小决定了音频数据的传输速率和延迟时间,如果设置不正确,可能会导致音频数据传输中的丢失和破碎;
  • 周期大小(Period Size:指每次音频数据传输的周期大小,通常以字节或采样数为单位表示。必须要设置的原因是,周期大小决定了音频数据的传输间隔和延迟时间,如果设置不正确,可能会导致音频数据传输中的丢失和破碎。

在设置这些必须要设置的硬件参数时,需要根据具体的音频设备和应用场景进行参数设置和优化,以确保音频数据的传输和处理正常。同时,需要根据缓冲区大小和周期大小等参数进行缓冲区的调整和管理,以避免数据传输中的丢失和破碎等问题。

(1)分配硬件参数对象;

以下两种方式都适用于分配硬件参数对象,但是一个是宏定义,一个是函数:

  • snd_pcm_hw_params_alloca
#define snd_pcm_hw_params_alloca(ptr) __snd_alloca(ptr, snd_pcm_hw_params)
#define __snd_alloca(ptr,type) do { *ptr = (type##_t *) alloca(type##_sizeof()); memset(*ptr, 0, type##_sizeof()); } while (0)
/*
NAME
       alloca - allocate memory that is automatically freed

SYNOPSIS
       #include <alloca.h>

       void *alloca(size_t size);
*/

snd_pcm_hw_params_alloca使用alloca来分配堆栈上的结构,这意味着当你的函数返回时,它会自动释放;

  • snd_pcm_hw_params_mallocsnd_pcm_hw_params_free
int snd_pcm_hw_params_malloc(snd_pcm_hw_params_t **ptr);
void snd_pcm_hw_params_free(snd_pcm_hw_params_t *obj);

snd_pcm_hw_params_malloc使用malloc,您有责任在不再需要时调用snd_pcm_hw_params_free进行资源释放。

参数说明返回值
snd_pcm_hw_params_t **ptr需要填入的是PCM硬件配置空间容器的地址分配参数硬件对象成功与否,成功时返回0,失败返回负错误码
snd_pcm_hw_params_t *obj需要填入的是PCM硬件配置空间容器释放之前分配的硬件对象,无需返回值
(2)初始化硬件参数对象;

PCM的完整配置空间填充默认参数:

函数原型
int snd_pcm_hw_params_any(snd_pcm_t *pcm, snd_pcm_hw_params_t *params);
参数说明
snd_pcm_t * pcmPCM设备的句柄
snd_pcm_hw_params_t *params填入的是需要进行初始化的PCM硬件配置空间容器

需要注意的是,不同的音频设备和应用场景可能需要不同的硬件参数设置。因此,在进行硬件参数配置之前,需要根据具体的需求和硬件性能进行参数设置和优化。同时,为了避免数据传输中的丢失和破碎等问题,需要根据缓冲区大小和周期大小等参数进行缓冲区的调整和管理。

(3)设置硬件重采样;

将配置空间限制为仅包含实际硬件速率(采样率,通道,位深),通俗点讲,所谓硬件改变现有音频参数,只要任一参数发生变换就被叫做重采样。

int snd_pcm_hw_params_set_rate_resample(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int val);
参数说明
unsigned int val0 = 禁用,1 = 启用(默认)速率重采样
(4)指定访问权限类型;

将配置空间params限制为仅包含一种访问类型:

int snd_pcm_hw_params_set_access(snd_pcm_t * pcm, snd_pcm_hw_params_t * params, snd_pcm_access_t access);
参数说明
snd_pcm_access_t accessPCM访问类型设置

PCM的访问类型有五种:

/** PCM 访问类型 */
typedef enum _snd_pcm_access {
	/** mmap访问与简单交错通道,具有交错样本 */
	SND_PCM_ACCESS_MMAP_INTERLEAVED = 0,
	/** mmap访问与简单非交错通道,需要一个通道的连续采样区域 */
	SND_PCM_ACCESS_MMAP_NONINTERLEAVED,
	/** mmap访问与复杂放置,不适合交错和非交错环形缓冲区组织 */
	SND_PCM_ACCESS_MMAP_COMPLEX,
	/** 期望输入时交错样本,交错传输函数有:snd_pcm_readi/snd_pcm_writei */
	SND_PCM_ACCESS_RW_INTERLEAVED,
	/** 期望输入时非交错样本(分离缓冲区的样本),非交错传输函数有:snd_pcm_readn/snd_pcm_writen */
	SND_PCM_ACCESS_RW_NONINTERLEAVED,
	SND_PCM_ACCESS_LAST = SND_PCM_ACCESS_RW_NONINTERLEAVED
} snd_pcm_access_t; 

按照传输样本的方法上进行分类,有两种。第一种方法是常规的读写访问(后两者),第二种方法使用直接音频缓冲区与设备通信(前三者)。前三者皆存在于环形缓冲区内存区域的组织(mmap区域),这种传输有两个功能:

  • 零拷贝功能:应用程序可以通过 snd_pcm_mmap_begin函数访问内存区域。此函数返回包含直接指向存储器的指针的区域,应用程序在内存区域中传输数据后,必须通过snd_pcm_mmap_commit函数确认传输结束,以允许 ALSA 库更新指向环形缓冲区的指针。这种通信也称为"零拷贝",因为设备不需要将样本从应用程序复制到系统内存中的另一个位置。
  • 兼容性功能mmap模式下使用兼容性功能等同于标准读/写传输的读/写例程。使用这些函数会放弃直接访问内存区域的好处。功能分别由snd_pcm_mmap_readisnd_pcm_mmap_writeisnd_pcm_mmap_readnsnd_pcm_mmap_writen函数实现。这些函数在内部使用snd_pcm_areas_copy

按照数字音频信号存储的方式进行分类,有两种:(根本的区别是采样点)

  • 交错模式:即数据以连续帧的方式存放,首先记录第一帧的左声道样本(L)和右声道样本(R),再开始第二帧,以往不断地记录存储,意味着采样点是帧连续的;(LRLRLRLRLRLRLRLR

  • 非交错模式:首先记录存储的是一个周期内所有帧的左声道样本(L),再记录所有右声道样本(R),意味着采样点是通道连续的。(LLLLLLLL RRRRRRRR

(5)指定样本采样格式;

将配置空间params限制为仅包含一种格式:

int int snd_pcm_hw_params_set_format(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_format_t format);

用于向接口和从接口传输数据的示例格式。它可能与硬件直接支持的格式对应,也可能不对应,也就意味着将配置空间容器限制为其中一种格式时有可能会失败,原因是硬件不支持。

参数说明
snd_pcm_format_t formatPCM格式设置

设置样本采样格式时,我们需要关注的是样本数据的采样位数,有无符号位以及字节存储顺序。
采样位数,又称量化位数,常见有8162432等,采样位数越大,声音的振幅范围越大,质量就越高,对模拟信号的描述越真实,对声音的描述也将更加准确,那么捕获和回放的声音就越真实。
有无符号位,在编码的时候也是需要注意的,取值范围越大,说明每一次采样所得到的那个振幅值也越大,大多数格式的PCM样本数据使用整形表示,而在一些对精度要求高的应用方面,使用浮点类型表示PCM样本数据。
字节存储顺序是指数据在主机的存储器中的存放顺序,与CPU有关,当两台主机采用不同字节序通信时,在发送数据之前都必须经过字节序的转换成为网络字节序后再进行传输。
PCM数据格式SND_PCM_FORMAT_S16_LE为例,它表示有符号的16位小端pcm数据,具体的可跳转查看PCM具体示例格式。

(6)指定通道个数;

将配置空间限制为仅包含一个通道计数(音轨数目):

int snd_pcm_hw_params_set_channels(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int val);

常见的有单通道,双通道,双通道能帮我们区分左右耳的声音,单通道的话两只耳朵都是一样的声音。通常我们追求立体感会使用双通道,所以双通道采集的声音也叫立体声。除此之外还有要求更高的2.15.16.17.1,等等通道类型,这些对你捕获音频的麦克风有一定要求,可以说音轨数越多,声音越有层次感。

参数说明
unsigned int valPCM通道数
(7)设置样本采样频率;

将配置空间限制为速率最接近目标:

int snd_pcm_hw_params_set_rate_near(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val, int *dir);

单位时间内对连续的模拟信号提取并组成离散数字信号的采样数目称之为采样频率,它用赫兹(Hz)来表示,采样频率越高,所能描述的声波频率就越高,声音的还原就越真实越自然,当然数据量就越大。

参数说明
unsigned int *val近似目标速率/返回的近似设定速率
int *dir(子单元方向,数值):(<-1),(=0),(>1

常见音频采样频率有8000Hz16000Hz22050Hz32000Hz44100Hz48000Hz96000Hz等。

  • 5kHz:仅能达到人们讲话的声音质量。
  • 11kHz:播放小段声音的最低标准,是CD音质的四分之一。
  • 22kHz:可以达到CD音质的一半,目前大多数网站都选用这样的采样率。
  • 44kHz:标准的CD音质,可以达到很好的听觉效果。
  • 48KHzminiDV、数字电视、DVD、电影和专业音频。

举个栗子CD音质的采样频率44.1kHz,根据香农采样定理,能够反映最大声音的频率是22kHz,恰好是人耳能够听到的声音频率相吻合,所以能够达到很好的听觉效果。

(8)设置缓冲大小;

将配置空间限制为缓冲区大小最接近目标

int snd_pcm_hw_params_set_buffer_size_near(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_uframes_t *val);
参数说明
snd_pcm_uframes_t *val近似目标缓冲区大小(以帧为单位)/返回所选近似目标缓冲区大小(以帧为单位)
(9)设置周期大小;

将配置空间限制为具有最接近目标的周期大小

int snd_pcm_hw_params_set_period_size_near(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_uframes_t *val, int *dir);	
参数说明
snd_pcm_uframes_t *val以帧为单位的近似目标周期大小/返回所选的近似目标周期大小
int *dir(子单元方向,数值):(<-1),(=0),(>1
(10)使能硬件参数。
int snd_pcm_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t *params);	

3. 配置软件参数

4.

  • 关闭PCM设备句柄
int snd_pcm_close(snd_pcm_t *pcm);
参数说明
snd_pcm_t * pcmPCM设备的句柄

(四)捕获示例

(五)播放示例

五、参考


  • 4
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值