上文: 【音频驱动】Linux之ALSA声卡、WAV文件相关概念

Linux之ALSA音频应用编程

使用alsa-libs和alsa-utils实现.wav格式文件的播放与录制,了解Linux中声卡的应用层设备节点。介绍了使用alsa-libs应用编程步骤。

一、ALSA架构

高级Linux声音体系结构(ALSA)为Linux操作系统提供音频和MIDI功能。

ALSA具有以下显著特征:

  • 高效支持所有类型的音频接口,从消费类声卡到专业多通道音频接口。

  • 完全模块化的声音驱动程序。

  • SMP和线程安全设计。

  • 用户空间库(alsa-lib),以简化应用程序编程并提供高级功能。

  • 支持旧的开放声音系统(OSS) API,为大多数OSS程序提供二进制兼容性。

ALSA系统包括7个子项目:

  • 驱动包alsa-driver

  • 开发包alsa-libs

  • 开发包插件alsa-libplugins

  • 设置管理工具包alsa-utils

  • OSS接口兼容模拟层工具alsa-oss

  • 特殊音频固件支持包alsa-finnware

  • 其他声音相关处理小程序包alsa-tools

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tVm5tcyU-1682084270719)(image/Linux之ALSA声卡应用驱动/1681615020116.png)]

​ alsa-libs 为一套 Linux 应用层的 C 语言函数库, 为音频应用程序开发提供了一套统一、标准
的接口,应用程序只需调用这一套 API 即可完成对底层声卡设备的操控 。

二、alsa-libs移植

首先需要在ALSA的官网上下载官网http://www.alsa-project.org下载alsa-lib和alsa-utils。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-K9o1Fqhz-1682084270721)(image/Linux之ALSA声卡应用驱动/1681615443264.png)]

具体步骤参考:

alsa-lib和alsa-utils移植_移植alsa-utils库_风雨兼程8023的博客-CSDN博客

三、ALSA设备文件结构

/dev/snd

在 Linux 内核设备驱动层、基于 ALSA 音频驱动框架注册的 sound 设备会在/dev/snd 目录下生成相应的
设备节点文件 。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BWnihaaV-1682084270721)(image/Linux之ALSA声卡应用驱动/1681616247600.png)]

我们可以看到以下设备文件:

  • controlC0 :用于声卡的控制,例如通道选择,混音,麦克风的控制等
  • midiC0D0 :用于播放midi音频
  • pcmC0D0c :用于录音的pcm设备
  • pcmC0D0p :用于播放的pcm设备
  • pcmC0D1p :用于播放的pcm设备
  • seq :音序器
  • timer :定时器

C0D0代表的是声卡0中的设备0, pcmC0D0c最后一个c代表capture, pcmC0D0p最后一个p代表
playback,这些都是alsa-driver中的命名规则。 从上面的列表可以看出,我的声卡下挂了7个设备,根据声卡的实际能力,驱动实际上可以挂上更多种类的设备,在include/sound/core.h中,定义了以下设备类型

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bQ2NTLKT-1682084270722)(image/Linux之ALSA声卡应用驱动/1681616672104.png)]

通常,我们更关心的是pcm和control这两种设备。

/proc/asound

在 Linux 系统的/proc/asound 目录下,有很多的文件,这些文件记录了系统中声卡相关的信息

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zP8ZdmXX-1682084270723)(image/Linux之ALSA声卡应用驱动/1681617091453.png)]

  • cards : 查看 cards 文件的内容,可列出系统中可用的、注册的声卡

  • devices : 列出系统中所有声卡注册的设备,

  • pcm : 列出系统中的所有 PCM 设备

  • timers : 定时器设备选型

  • version : ALSA驱动版本

  • card0 :记录了声卡 0 相关的信息,譬如声卡的名字以及声卡注册的 PCM 设备

四、alsa-utils的测试工具

alsa-utils的测试工具

  • aplay

  • arecord

  • alsamixer

  • amixer

  • alsactl

  • alsaloop

aplay
aplay 是一个用于测试音频播放功能程序,可以使用 aplay 播放 wav 格式的音频文件。

常用命令:

aplay xxx.wav 

arecord

arecord 工具是一个用于录音测试的应用程序

常用命令:

arecord -r 20000 -f S16_LE -c 1 -d 10 -D hw:0,1 6.wav

-r 表示采样频率(最小为8000);

-f 表示采样格式,这里指 16 bit little endian(一般为S16_LE、S32_LE);

-c 表示通道数量(1或2);

-d 表示录音时间;

-D 表示使用哪个录音设备(hw:0,1:hw插件,第一个参数表示声卡号,第二个参数表示设备号);

采样频率越高,声音越清晰,.wav文件越大

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HplWZx9E-1682084270724)(image/Linux之ALSA声卡应用驱动/1682049469753.png)]

alsaloop

alsaloop用于回环测试,边录音边播放。

常用命令:

alsaloop -C hw:0,1 -t 100

五、编写ALSA应用程序

基于alsa-lib编写

API和例子参考官网 ALSA project - the C library reference: Index, Preamble and License (alsa-project.org)

1、打开PCM设备

int snd_pcm_open(snd_pcm_t **pcmp, const char *name, snd_pcm_stream_t stream, int mode)

2、设置硬件参数

实例化 snd_pcm_hw_params_t 对象

int snd_pcm_hw_params_malloc(snd_pcm_hw_params_t **ptr);

初始化 snd_pcm_hw_params_t 对象

int snd_pcm_hw_params_any(snd_pcm_t *pcm, snd_pcm_hw_params_t *params);

设置 access 访问类型

int snd_pcm_hw_params_set_access(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_access_t _access);

设置数据格式

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

设置声道数

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

设置采样率大小

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

设置周期大小

int snd_pcm_hw_params_set_period_size(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_uframes_t val, int dir);

设置 buffer 大小

int snd_pcm_hw_params_set_buffer_size(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_uframes_t val);int snd_pcm_hw_params_set_periods(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,unsigned int val,int dir)

安装/加载硬件配置参数

int snd_pcm_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t *params);

3、读/写数据

snd_pcm_sframes_t snd_pcm_writei(snd_pcm_t *pcm, const void *buffer, snd_pcm_uframes_t size);

snd_pcm_sframes_t snd_pcm_readi(snd_pcm_t *pcm, void *buffer, snd_pcm_uframes_t size);

4、释放资源

int snd_pcm_close(snd_pcm_t *pcm);

void snd_pcm_hw_params_free(snd_pcm_hw_params_t *obj)

5、异步接口

int snd_async_add_pcm_handler(snd_async_handler_t **handler, snd_pcm_t *pcm, 
			      snd_async_callback_t callback, void *private_data);

int snd_pcm_poll_descriptors(snd_pcm_t *pcm,struct pollfd *pfds,unsigned int space);

参考资料

正点原子文档
ALSA project - the C library reference: Index, Preamble and License (alsa-project.org)

Logo

更多推荐