小白快速入门Linuxalsa应用编程

原创 Linux阅码场 2022-07-04 08:00


Ftrace训练营火热报名中:Ftrace训练营:站在设计者的角度来理解ftrace(限50人)。训练营第一期报名已圆满成功,好评如潮。第二期报名正在火爆进行中(咨询小月微信:linuxer2016)。


ARM安全架构训练营火热报名中:阅码场训练营:ARM安全架构之Trustzone-TEE实战。报名咨询客服(小月微信:linuxer2016)。


ARM架构与调优调试训练营火热报名中:阅码场训练营:ARM架构与调试调优。报名咨询客服(小月微信:linuxer2016)。



作者简介

廖威雄 暨大物联专业首批毕业生,手忙脚乱的新手奶爸,憧憬物联未来,为天猫精灵砌砖的逐梦人


1. 背景

网上大多数是 alsa 底层框架、音频驱动的文章,应用开发的入门少得可怜。从业务需求出发,摸索积累了一些 alsa 应用开发心得。出此文以便后来者快速入门。

本文不会涉及底层框架,也不会使用很高级的特性,适合需要做 alsa 应用开发的初学者。毕竟是半路出家,与沉浸多年对 alsa 框架了如指掌的大牛没得比。如果有理解不准确的地方,希望指导共同进步。

  • Alsa 主页:https://www.alsa-project.org/wiki/Main_Page

  • Alsa 文档主页:https://www.alsa-project.org/alsa-doc/alsa-lib/index.html

  • Alsa PCM 接口说明:https://www.alsa-project.org/alsa-doc/alsa-lib/group_pcm.html

  • Alsa HCTL 接口说明:https://www.alsa-project.org/alsa-doc/alsa-lib/group_h_control.html

  • Alsa CTL 接口说明:https://www.alsa-project.org/alsa-doc/alsa-lib/group_control.html

在学习过程中,有两篇前人的分享给了我很多帮助,一并贴上:

  • 《学习Linux操作系统中Alsa音频编程》:https://www.elecfans.com/emb/20190402899220.html

  • 《【转】Alsa音频编程【精华】》:https://www.cnblogs.com/cslunatic/p/3677729.html

2. 基本概念

一些基本的概念还是要有理解的,不然无法理解 API 意义和参数作用。

我们知道声音是靠震动传播的,自然界传播的声音都是连续的模拟信号,经过采样转换成数字信号。其实有不少概念都是在描述怎么采样。

2.1 样本长度 Format

上图中,每一个黑色小球就是采样出来的数值,这个数值是多少比特位的,就是我们说的采样精度,也就是样本长度,常见的有 8 bit 和 16 bit,偶尔也有 32 bit。例如采样值是 3,如果是 8 bit 位采样结果就是 0x03,16 bit位采样结果就是 0x0003。

2.2 通道数 Channels

我们常说的左声道、右声道,可以理解为左右各来一个 mic 采样,左 mic 采样出来的样本就是左声道数据,右边 mic 采样出来的样本就是右声道数据。而一个音频既可以只有1个声道,也可以有左右两个声道,后者也称为立体声。而这个音频究竟有几个声道,就是我们说的通道数

2.3 帧 Frame

我们每一次采样出来的结果,就是一帧。很明显,一帧数据有多大,取决于我们采样的精度以及通道数。

2.4 交错模式 Interleaved

我们每一次采样出的音频帧,怎么保存呢?提供了两种保存思路,也就是我们说的交错模式和非交错模式。我们常用的也是交错模式。

2.5 周期 Period

我们总不可能一次处理1帧数据吧,太低效了,那就做成批量处理吧。而一次处理多少帧就是我们说的周期。

一次周期结束切到下一次周期,都是需要额外处理损耗的,就类似于进程切换。周期大,一次处理数据量就多,每次连续处理时间长,切换损耗就少,但也因为数据要满一个周期后才处理,导致数据处理延时长。反之,如果周期设置的小,延时短了,但周期切换更频繁,损耗就更大,更容易出现卡顿。

2.6 缓存大小 Buffer Size

这里说的是 alsa 底层 DMA 搬运数据的缓存大小,这是一个环形的缓存空间。我们设置 DMA 一次连续搬运 1 个周期的数据,搬运期间如果又来数据怎么办?我们就需要更大的缓存空间来保存更多的数据。缓存空间往往是周期的整数倍,例如设置了缓存 8 个周期,每个周期 6000 帧,那么最多可以缓存 8 * 6000 = 48000 帧的数据。

2.7 采样率 Rate

不同于周期是人为定义的一次处理多少帧,采样率就是固定的 1s 时间内会有多少次采样,同时也表示 1s 播放需要多少帧。常用的采样率如 8KHz 的人声, 44.1KHz 的 mp3 音乐, 96Khz 的蓝光音频。

假设一个周期是 6000 帧,采样率是 48 Khz,那么一个周期的数据能播放 125 ms。

2.8 Xrun

录音的应用中,底层是持续不断采样的,如果应用程序读取数据不够快,底层数据缓存区还没被取走就被新的数据覆盖,导致数据丢失,称为 over run

播放的应用中,底层是持续不断从缓存中获取数据播放的,如果应用程序写入数据慢了,缓存区已经没有有效数据了,导致播放“饿死”,称为 under run

Xrun 是 under run 和 over run 的统称,前者可以理解为播放卡顿,后者则是录音卡顿。

当出现卡顿的时,大多情况调整周期、缓存大小,调整应用进程调度优先级能解决问题。

3. 框架初探与声卡设备

以下是网上优秀的文章:

《ALSA架构简介》:http://t.zoukankan.com/-glb-p-13722212.html

Alsa 的架构包括用户空间的 Alsa Library,也包括内核空间的 Alsa Core 和 ASoC Core,如下图所示:


  • APP:应用程序通过调用 alsa 库 API 来实现声卡播放、录音、控制。此外,官方还提供了一些标准命令行程序,例如aplay/amixer。

  • Alsa-Library:alsa 库封装了底层复杂的系统调用,向上提供更直观的 API。常见的 alsa 库有 alsa-lib 和 tinyalsa。

  • Alsa Core:Alsa 的核心层在内核,向上提供逻辑设备、系统调用,向下驱动硬件设备。

  • ASoC Core:asoc是建立在标准 alsa core 上为更好支持嵌入式系统和移动设备音频 codec 设计的软件体系

Alsa 用户空间的 API 库主要通过 open/read/write/ioctl 操作 /dev/snd/xxx 下的设备文件实现与内核交互,常见的设备文件有:

文件名用途
controlC0第0号声卡的控制设备,例如音量、混音等
pcmC0D0c第0号声卡第0个设备,用于录音(Capture)的设备
pcmC0D0p第0号声卡第0个设备,用于播放(Playback)的设备
seq音序器
timer定时器

命名规则显而易见, pcm表示设备类型, C0 表示声卡0, D0表示设备0, c/p分别表示录音、播放功能。

4. 系统配置与插件

最完整的介绍还是来自于官网原文:

《Asoundrc》配置文件:https://www.alsa-project.org/main/index.php/Asoundrc
《PCM (digital audio) plugins》:https://www.alsa-project.org/alsa-doc/alsa-lib/pcm_plugins.html

alsa-lib 会从 /usr/share/alsa/alsa.conf 开始加载,进而根据 alsa.conf 的记录加载 /etc/asond.conf~/.asoundrc。前者是系统级别的配置,后者是用户级别的配置,两者的语法是一致的。

我们从配置默认声卡开始,以下是一个标准示例:

pcm.!default { type hw card 0}ctl.!default { type hw  card 0}

一般情况下,我们配置的格式 pcm.{...},而关键字 !default 可以理解为保留字。pcm.!default 配置的是默认录播声卡, ctl.!default 配置的是默认控制声卡。如此配置后,我们可以用 "default" 做声卡名指代 "hw:0,0",所以下两个命令就是等效的了。

aplay -D hw:0,0 test.wavaplay -D default test.wav

此时 "default" 声卡不管是播放还是录音,都指向 "hw:0,0" 设备。如果我希望 "default" 录音和播放指向不同(虚拟)声卡,我们可以用 asym 插件,例如:

pcm.!default { type asym playback.pcm "Playback" capture.pcm "Capture"}pcm.Playback { ...}pcm.Capture { ...}

当然,我们可以跳过 "default" 直接用 "Playback" 的虚拟声卡播放,例如

aplay -D Playback test.wav

Alsa 配置的节点是一个个声卡节点串联起来的,例如下面的配置,实现了从插件 A 开始串上插件 B ,用插件实现各种音效功能,最后到物理声卡播放。

pcm.A { type XXX # 下⼀个节点是声卡 B slave.pcm B ...}pcm.B { type XXX # 下⼀个节点是物理声卡 salve.pcm "hw:0,0"}

type 字段就标识此节点使⽤什么插件。我们可以⾃⼰实现插件,也可以⽤官⽹提供的插件,详⻅官⽹ PCM (digital audio) plugins。其中有⼏个⾮常有意思的插件,这⾥简单介绍下。



例如 "default" 声卡⽀持分流,播放时⽀持⾳量调节,且⽀持混⾳。


pcm.!default { type asym playback.pcm "Playback" capture.pcm "..."}pcm.Playback { type softvol slave.pcm PlaybackDmix ...}pcm.PlaybackDmix { type plug # dmix 再套⼀层plug,实现重采样 slave.pcm { type dmix ... slave { pcm "hw:0,0" format S16_LE ... } }}

5. 基本录播


官⽹上有个最最最精简的示例 pcm_mini,其作⽤仅仅是播放⼀段随机数据。

精炼核⼼逻辑如下:


int main(void){ ... /* 打开alsa设备,类型为 PlayBack */ if ((err = snd_pcm_open(&handle, device, SND_PCM_STREAM_PLAYBACK, 0)) < 0) { ... } /* 设置alsa设备基本属性 */ if ((err = snd_pcm_set_params(handle, SND_PCM_FORMAT_U8, SND_PCM_ACCESS_RW_INTERLEAVED, 1, 48000, 1, 500000)) < 0) { ... } /* 播放⾳频数据 */ frames = snd_pcm_writei(handle, buffer, sizeof(buffer)); /* 关闭声卡设备 */ snd_pcm_close(handle); return 0;}


录⾳跟播放⾮常相似,播放调⽤ snd_pcm_writei() ,录⾳则调⽤ snd_pcm_readi()


总的来说,⼀个简单的录播包括以下 4 个步骤:

  • 1. 打开声卡设备

  • 2. 初始化设备

  • 3. 录⾳、播放

  • 4. 关闭声卡设备


围绕这 4 个步骤,介绍下常⽤的 API,更多的介绍请看官⽹:pcm api

5.1 打开声卡设备

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


  • pcmp:声卡设备句柄,类似于⽂件句柄

  • name:声卡设备名,类似于⽂件名,声卡设备名参考第3章节

  • stream:数据流向,指定⽤于录⾳还是播放

  • mode:打开模式,例如nonBlockasync等,⼤多数情况⽤ 0 即可


数据流向有两种,分别指代录⾳ or 播放。



⼀个简单的示例如下,从 default 设备录⾳:

#include snd_pcm_t *snd_handle;err = snd_pcm_open(&snd_handle, "default", SND_PCM_STREAM_CAPTURE, 0)

5.2 初始化设备


alsa 设置声卡参数的接⼝⾮常多,可以分为软件参数(software parameters)和硬件参数(software parameters)两类。上⽂例⼦调⽤的 snd_pcm_set_params() 如官⽹API⽂档所说,只是简单设置软件、硬件参数的⽅法,实际项⽬中很少这么⽤。


5.2.1 设置硬件参数


官⽹有⾮常多的例⼦,以 pcm 为例,设置硬件参数常⻅以下步骤:


int set_hwparams(...){ /* 从栈⾥分配硬件参数对象内存 */ snd_pcm_hw_params_alloca(¶ms); /* 初始化参数对象 */ err = snd_pcm_hw_params_any(handle, params); /* 设置采样率 */ err = snd_pcm_hw_params_set_rate_near(handle, params, &rate, 0); /* 设置交错模式 */ err = snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED); /* 设置采样格式,例如样本⻓度、有⽆符号 */ err = snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE); /* 设置通道数 */ err = snd_pcm_hw_params_set_channels(handle, params, 2); /* 设置缓存⼤⼩ */ err = snd_pcm_hw_params_set_buffer_time_near(handle, params, &buffer_time, &dir); /* 设置周期⼤⼩ */ err = snd_pcm_hw_params_set_period_time_near(handle, params, &period_time, &dir); /* 把上述设置值写⼊设备 */ err = snd_pcm_hw_params(handle, params);}


不妨回顾章节2的基本概念,可以发现硬件参数基本都是围绕这些概念设置的。不管是交错模式、采样率,还是样本⻓度、通道数都⽐较直观,如果设置错⼤概率⽆法正常运⾏。⽽缓存⼤⼩和周期⼤⼩往往跟卡顿、延时有关,且有好⼏种设置维度,值得展开介绍。


调整卡顿、延时参数时,我们需要记住⼀个核⼼的关系:

缓存⼤⼩ = 周期⼤⼩ * 周期数,即 buffer size = period size * periods

3 个参数知其2 就可以换算出另外⼀个参数。例如我们可以设置 周期⼤⼩ 和 周期数,alsa 会⾃动换算出 缓存⼤⼩。同理,我们可以设置缓存⼤⼩和周期⼤⼩,alsa 也能⾃动换算出周期数。在上述的例⼦中,就是设置了缓存⼤⼩和周期⼤⼩。


在⼀定的采样率下,缓存⼤⼩也可以换算成时间,毕竟有些⼈需要从时间维度设置缓存。

播放时间 = 缓存⼤⼩ / 采样率

因此我们可以发现,除了 set_buffer/period_size() 之外,我们还可以set_buffer/period_time() ,他们是等效的。


更多的 pcm 硬件参数设置API,可以看官⽹ hw参数API⽂档,这⾥再补充⼀点。


同样是设置周期⼤⼩,我们可以⽤ snd_pcm_hw_params_set_period_size() ,但更多会选择⽤

snd_pcm_hw_params_set_period_size_near() 。这⾥的 near 后缀表示就近设置,因为不管是缓存⼤⼩还是周期⼤⼩、周期数,有时候会受其他配置制约,这时候就采⽤可⽤的接近的值。例如声卡设备在系统配置中限制了周期⼤⼩不超过 1024 帧,此时如果设置 6000 帧,就会就近复位为1024


5.2.2 设置软件参数


同样在 pcm 的例⼦中提取软件参数设置步骤:

int set_swparams(...){ /* 从栈⾥分配软件参数对象内存 */ snd_pcm_sw_params_alloca(¶ms); /* 获取当前的软件参数配置以初始化对象 */ err = snd_pcm_sw_params_current(handle, swparams); /* 设置起播阈值 */ err = snd_pcm_sw_params_set_start_threshold(...); /* 设置最⼩可⽤ */ err = snd_pcm_sw_params_set_avail_min(...); /* 把上述设置值写⼊设备 */ err = snd_pcm_sw_params(handle, swparams);}


软件参数设置我⽤的也不多,更多时候⼲脆不设置软件参数采⽤默认值。为了不误⼈⼦弟,每个参数的具体作⽤不展开介绍。以下是相关的⽂档链接,请读者辨证分析。

https://blog.csdn.net/weixin_39560924/article/details/110569666

https://blog.csdn.net/zz2862625432/article/details/101787316

https://www.cnblogs.com/cslunatic/p/3677729.html

5.3 录音与播放


本⽂只讲常⽤的读写,不展开 mmap 等⽅法。

交错模式和⾮交错模式⽤的读(录⾳)和写(播放)接⼝不⼀样。

# 交错模式snd_pcm_sframes_t snd_pcm_readi (snd_pcm_t *pcm, void *buffer, snd_pcm_uframes_t size)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_readn (snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size)snd_pcm_sframes_t snd_pcm_writen (snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size)
  • pcm:声卡设备句柄

  • buffer:读/写的buffer指针

  • size:指代buffer⼤⼩,单位帧


⼀个简单的转播(读->写)示例如下:

frames = 6000; # 假设⼀个周期 6000 帧buffer = malloc( frames * 4 ); # 双通道16Bit采样精度,因此⼀帧 4Bwhile (true) { ret = snd_pcm_readi(chandle, buffer, frames); snd_pcm_writei(phandle, buffer, ret);}


5.4 关闭声卡设备

int snd_pcm_close(snd_pcm_t *pcm)


关闭声卡设备的接⼝⾮常简单,类似于关闭⽂件句柄。

6. 设置音量


录播⽤ pcm APIs,⽽设置⾳量需要使⽤ ctrl APIsAlsa 有两类控制接⼝,⼀个是 ctrl,⼀个则是更⾼层抽象的 hctrl,以下是官⽹两个类型接⼝⽂档:

Alsa HCTL 接⼝说明:https://www.alsa-project.org/alsa-doc/alsa-lib/grouphcontrol.html

Alsa CTL 接⼝说明:https://www.alsa-project.org/alsa-doc/alsa-lib/group_control.html

以及下⾯链接是官⽹关于控制的⼀些概念介绍:

Control interface 概述:https://www.alsa-project.org/alsa-doc/alsa-lib/control.html

下⽂会先介绍关于 ctrl 的基本概念,再参考 Alsa Utils amixer 命令学习如何获取、设置⾳量。


6.1 控制基本概念


不管是实体声卡还是虚拟声卡,每⼀个声卡都会提供⼀个控制⽅法,我们需要设置声卡属性,就必须要先打开丢应的声卡控制。打开声卡设置需要使⽤ snd_ctl_open() ,并⽤以下⼏种⽅法可以指定声卡:


1. 使⽤声卡编号,例如: hw:1

2. 使⽤声卡名,例如: hw:sndtasXXXX 或者 hw:CARD=sndtasXXXX

3. 使⽤设备⽂件,例如:hw:/dev/snd/controlC0


每个声卡可以有很多控制项,在 Alsa ⾥叫做 要素(Elements)。要素可以有多个成员(Member),例如⽴体声有左右声道⾳量两个成员。⼀个要素的所有成员共享⼀样的属性,例如最⼤、最⼩⾳量。此外,要素数据也区分类型,例如⾳量是整型。以下是所有⽀持的要素类型:



既然⼀个声卡可以有很多要素(控制项),我们设置要素需要先定位哪个要素吧。要定位每个要素,可以有以下⽅法:


1. 使⽤numid:当声卡被检测到的时候就会赋予⼀个编号,但每次开机可能都不⼀样。使⽤此编号主要是减少根据属性遍历时间。

2. 使⽤固定属性:固定属性包括⽅法类型(interface type)、设备(device)、⼦设备(subname)、名字(name)或者编号index)。可以⼀次指定多个属性以便准确定位要素。


6.2 获取设置音量


Alsa Libs 关于设置⾳量的示例不多,这时候我们不妨看看 Alsa Utils amixer 命令的实现,毕竟其我们通过命令⾏设置⾳量往往是通过 amixer 命令,例如:


amixer -D default cset name='Master Volume' 60 # 设置默认声卡⾳量为60(要素名为:Master Volume)


6.2.1 关键数据类型


在了解相关代码实现前,需要先了解⼏个很重要的数据类型。


1. snd_ctl_elem_id_t :记录了定位要素的属性,例如设备、numid

2. snd_ctl_elem_value_t :存储了要素值,需要根据不同类型⽤不同接⼝获取具体值

3. snd_ctl_elem_info_t :要素的信息


hctl API,还有 snd_hctl_elem_t 描述具体的要素对象。


  • id 唯⼀标识了要素,在定位要素时可以赋值部分已知属性到 id,⽤于遍历要素。

  • 通过绑定 id 后获取要素的 infoinfo包含了要素的所有属性,例如类型、完整要素 id 信息。

  • 通过绑定 id 后读取要素的 value,最后根据类型调⽤对应接⼝从 value 中获取具体值。


6.2.2 代码实现


以下是精简后设置⾳量的实现(为了⽅便理解跟源代码 amixer 的调⽤API不完全相同):


int cset(...){ /* 从栈申请 info/id/value 对象空间 */ snd_ctl_elem_info_alloca(&info); snd_ctl_elem_id_alloca(&id); snd_ctl_elem_value_alloca(&control); /* 根据命令⾏指定的要素信息来初始化 id (id 记录了定位要素的信息) */ snd_ctl_ascii_elem_id_parse(id, "name='Master Volume'"); /* 打开默认声卡,获取控制句柄 */ snd_ctl_open(&handle, "default", 0); /* 绑定要素 id 到 info 对象,此处仅仅是把 id 赋值到 info 的成员 */ snd_ctl_elem_info_set_id(info, id); /* 从声卡中,依据绑定的 id,获取要素完整的 info 信息 */ snd_ctl_elem_info(handle, info); /* 读取当前⾳量 */ /* 绑定要素 id 到 value 对象,此处仅仅是把 id 复制到 value 的成员 */ snd_ctl_elem_value_set_id(control, id); /* 从声卡中,依据绑定的 id,获取要素完整的 value 信息 */ snd_ctl_elem_read(handle, control); /* 从 value 对象中,获取通道 idx 的整型⾳量值 */ vol = snd_ctl_elem_value_get_integer(control, idx); /* 设置新⾳量 */ /* * info ⾥记录了要素类型、成员数量等属性,此接⼝根据要素属性, * 解析命令⾏设置字符串的值,获取新的的 value 信息。 * 此⽅法⽤于命令⾏字符串解析,如果是⾃⼰编程实现,应该⽤ snd_ctl_elem_value_set_xxxx()。 */ snd_ctl_ascii_value_parse(handle, control, info, "60"); /* 把最终的 value 设置⼊声卡 */ snd_ctl_elem_write(handle, control); /* 关闭声卡控制 */ snd_ctl_close(handle);}


以获取⾳量为例,就以下⼏个关键的步骤:


1. 初始化 id ,赋值已知的要素属性,⽅便遍历定位要素。

  • snd_ctl_ascii_elem_id_parse()


2. 绑定 id,根据 id 获取要素 value

  • snd_ctl_elem_value_set_id()

  • snd_ctl_elem_read()


3. (默认⾳量是int类型)调⽤ int 类型获取接⼝,从 value 对象获取实际⾳量值

  • snd_ctl_elem_value_get_integer()


设置⾳量与获取⾳量相⽐,多了以下⼏个步骤:


1. (默认⾳量是int类型)调⽤ int 类型设置接⼝,设置 value 对象新⾳量值

  • snd_ctl_elem_value_set_integer()


2. value 对象写⼊声卡

  • snd_ctl_elem_write()


当然,如果想要做的兼容性更好,我们还需要获取要素 info,以根据 info 记录的要素类型调⽤不同接⼝:


1. 绑定 id,根据 id 获取要素 info

  • snd_ctl_elem_info_set_id()

  • snd_ctl_elem_info()


2. info 获取要素类型、要素成员数量、完整的id信息等

  • snd_ctl_elem_info_get_type()

  • snd_ctl_elem_info_get_count()

  • snd_ctl_elem_info_get_id()


补充⼀点,我们可以直接⽤ snd_ctl_elem_id_set_numid/name/index/... 直接初始化 id,也可以参考 amixer 通过字符串⾃⾏解析初始化 id,调⽤ snd_ctl_ascii_elem_id_parse() 。⾃⾏解析字符串⽀持以下格式:

[[iface=,][name='name',][index =,][device=,][subdevice=]]|[numid=]

7. 调试信息

调试信息用于打印声卡详细的属性,类似于 aplay 命令的 -v 选项。

alsa debug API文档:https://www.alsa-project.org/alsa-doc/alsa-lib/grouppcmdump.html

以下是我常用的一个例子:

/* 定义dump输出对象 */snd_output_t *output = NULL;/* 绑定输出对象到 stdout */snd_output_stdio_attach(&output, stdout, 0);/* dump 出声卡 handle (pcm)的信息 */snd_pcm_dump(handle, output);/* 关闭输出对象 */snd_output_close(output);

snd_pcm_dump() 可以dump出播放链路中每⼀个节点的配置信息,例如 dmix 插件的信息:


Slave: Direct Stream Mixing PCMIts setup is: stream : PLAYBACK access : MMAP_INTERLEAVED format : S16_LE subformat : STD channels : 2 rate : xxxx exact rate : xxxx (xxxx/1) msbits : xxx buffer_size : xxx period_size : xxx period_time : xxx tstamp_mode : NONE tstamp_type : GETTIMEOFDAY period_step : 1 avail_min : 6000 period_event : 0 start_threshold : xxx stop_threshold : xxxx silence_threshold: 0 silence_size : 0 boundary : 5066549580791808000


当然,如果想看声卡的 hw/sw_params,也可以直接读 proc 的⽂件,例如声卡0的播放设备0节点:

cat /proc/asound/card0/pcm0p/sub0/{hw_params,sw_params}

8. 命令工具集


Alsa Utils 提供了⼀系列⾮常有⽤的⼯具集,常⽤的包括 arecord 录⾳、aplay 播放、amixer 设置。

每个命令都有详细的 --help 信息,本⽂只提供⼏个简单的例⼦。


# 从 default 设备录⾳,采样精度为 16 bit,采样率为16K,1通道arecord -D default -f S16_LE -r 16000 -c 1 ./record.wav# 向 default 设备播放# wav 可以⾃⾏从头信息读取,PCM格式需要指定更多参数,不⽀持mp3等需要解码的⾳频格式aplay -D default ./record.wav# 修改系统⾳量为90amixer -D default cset name='xxxxx Volume' 90


精华文章:【精华】Linux阅码场原创精华文章汇总



阅码场付费会员专业交流群

会员招募:各专业群会员费为88元/季度,权益包含群内提问,线下活动8折,全年不定期群技术分享(普通用户直播免费,分享后每次点播价为19元/次),有意加入请私信客服小月(小月微信号:linuxer2016)


专业群介绍:

彭伟林-阅码场内核性能与稳定性
本群定位内核性能与稳定性技术交流,覆盖云/网/车/机/芯领域资深内核专家,由阅码场资深讲师彭伟林主持。


甄建勇-性能优化与体系结构

本群定位Perf、cache和CPU架构技术交流,覆盖云/网/车/机/芯领域资深用户,由阅码场资深讲师甄建勇主持。


李春良-Xenomai与实时优化

本群定位Xenomai与实时优化技术交流,覆盖云/网/车/机/芯领域资深用户,由阅码场资深讲师李春良和彭伟林共同主持。


周贺贺-Tee和ARM架构

本群定位Tee和ARM架构技术交流,覆盖云/网/车/机/芯领域资深用户,由阅码场资深讲师周贺贺主持。


谢欢-Linux tracers

本群定位Linux tracers技术交流,覆盖云/网/车/机/芯领域资深用户,由阅码场资深讲师谢欢主持。




Linux阅码场 专业的Linux技术社区和Linux操作系统学习平台,内容涉及Linux内核,Linux内存管理,Linux进程管理,Linux文件系统和IO,Linux性能调优,Linux设备驱动以及Linux虚拟化和云计算等各方各面.
评论
  • RK3506 是瑞芯微推出的MPU产品,芯片制程为22nm,定位于轻量级、低成本解决方案。该MPU具有低功耗、外设接口丰富、实时性高的特点,适合用多种工商业场景。本文将基于RK3506的设计特点,为大家分析其应用场景。RK3506核心板主要分为三个型号,各型号间的区别如下图:​图 1  RK3506核心板处理器型号场景1:显示HMIRK3506核心板显示接口支持RGB、MIPI、QSPI输出,且支持2D图形加速,轻松运行QT、LVGL等GUI,最快3S内开
    万象奥科 2024-12-11 15:42 118浏览
  • 应用环境与极具挑战性的测试需求在服务器制造领域里,系统整合测试(System Integration Test;SIT)是确保产品质量和性能的关键步骤。随着服务器系统的复杂性不断提升,包括:多种硬件组件、操作系统、虚拟化平台以及各种应用程序和服务的整合,服务器制造商面临着更有挑战性的测试需求。这些挑战主要体现在以下五个方面:1. 硬件和软件的高度整合:现代服务器通常包括多个处理器、内存模块、储存设备和网络接口。这些硬件组件必须与操作系统及应用软件无缝整合。SIT测试可以帮助制造商确保这些不同组件
    百佳泰测试实验室 2024-12-12 17:45 108浏览
  • 本文介绍瑞芯微RK3588主板/开发板Android12系统下,APK签名文件生成方法。触觉智能EVB3588开发板演示,搭载了瑞芯微RK3588芯片,该开发板是核心板加底板设计,音视频接口、通信接口等各类接口一应俱全,可帮助企业提高产品开发效率,缩短上市时间,降低成本和设计风险。工具准备下载Keytool-ImportKeyPair工具在源码:build/target/product/security/系统初始签名文件目录中,将以下三个文件拷贝出来:platform.pem;platform.
    Industio_触觉智能 2024-12-12 10:27 109浏览
  • 一、SAE J1939协议概述SAE J1939协议是由美国汽车工程师协会(SAE,Society of Automotive Engineers)定义的一种用于重型车辆和工业设备中的通信协议,主要应用于车辆和设备之间的实时数据交换。J1939基于CAN(Controller Area Network)总线技术,使用29bit的扩展标识符和扩展数据帧,CAN通信速率为250Kbps,用于车载电子控制单元(ECU)之间的通信和控制。小北同学在之前也对J1939协议做过扫盲科普【科普系列】SAE J
    北汇信息 2024-12-11 15:45 132浏览
  • 时源芯微——RE超标整机定位与解决详细流程一、 初步测量与问题确认使用专业的电磁辐射测量设备,对整机的辐射发射进行精确测量。确认是否存在RE超标问题,并记录超标频段和幅度。二、电缆检查与处理若存在信号电缆:步骤一:拔掉所有信号电缆,仅保留电源线,再次测量整机的辐射发射。若测量合格:判定问题出在信号电缆上,可能是电缆的共模电流导致。逐一连接信号电缆,每次连接后测量,定位具体哪根电缆或接口导致超标。对问题电缆进行处理,如加共模扼流圈、滤波器,或优化电缆布局和屏蔽。重新连接所有电缆,再次测量
    时源芯微 2024-12-11 17:11 133浏览
  • 习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习笔记&记录学习习笔记&记学习学习笔记&记录学习学习笔记&记录学习习笔记&记录学习学习笔记&记录学习学习笔记记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记
    youyeye 2024-12-12 10:13 75浏览
  • 铁氧体芯片是一种基于铁氧体磁性材料制成的芯片,在通信、传感器、储能等领域有着广泛的应用。铁氧体磁性材料能够通过外加磁场调控其导电性质和反射性质,因此在信号处理和传感器技术方面有着独特的优势。以下是对半导体划片机在铁氧体划切领域应用的详细阐述: 一、半导体划片机的工作原理与特点半导体划片机是一种使用刀片或通过激光等方式高精度切割被加工物的装置,是半导体后道封测中晶圆切割和WLP切割环节的关键设备。它结合了水气电、空气静压高速主轴、精密机械传动、传感器及自动化控制等先进技术,具有高精度、高
    博捷芯划片机 2024-12-12 09:16 104浏览
  • 全球智能电视时代来临这年头若是消费者想随意地从各个通路中选购电视时,不难发现目前市场上的产品都已是具有智能联网功能的智能电视了,可以宣告智能电视的普及时代已到临!Google从2021年开始大力推广Google TV(即原Android TV的升级版),其他各大品牌商也都跟进推出搭载Google TV操作系统的机种,除了Google TV外,LG、Samsung、Panasonic等大厂牌也开发出自家的智能电视平台,可以看出各家业者都一致地看好这块大饼。智能电视的Wi-Fi连线怎么消失了?智能电
    百佳泰测试实验室 2024-12-12 17:33 113浏览
  • 首先在gitee上打个广告:ad5d2f3b647444a88b6f7f9555fd681f.mp4 · 丙丁先生/香河英茂工作室中国 - Gitee.com丙丁先生 (mr-bingding) - Gitee.com2024年对我来说是充满挑战和机遇的一年。在这一年里,我不仅进行了多个开发板的测评,还尝试了多种不同的项目和技术。今天,我想分享一下这一年的故事,希望能给大家带来一些启发和乐趣。 年初的时候,我开始对各种开发板进行测评。从STM32WBA55CG到瑞萨、平头哥和平海的开发板,我都
    丙丁先生 2024-12-11 20:14 93浏览
  • 在智能化技术快速发展当下,图像数据的采集与处理逐渐成为自动驾驶、工业等领域的一项关键技术。高质量的图像数据采集与算法集成测试都是确保系统性能和可靠性的关键。随着技术的不断进步,对于图像数据的采集、处理和分析的需求日益增长,这不仅要求我们拥有高性能的相机硬件,还要求我们能够高效地集成和测试各种算法。我们探索了一种多源相机数据采集与算法集成测试方案,能够满足不同应用场景下对图像采集和算法测试的多样化需求,确保数据的准确性和算法的有效性。一、相机组成相机一般由镜头(Lens),图像传感器(Image
    康谋 2024-12-12 09:45 114浏览
  • 习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习笔记&记录学习习笔记&记学习学习笔记&记录学习学习笔记&记录学习习笔记&记录学习学习笔记&记录学习学习笔记记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记
    youyeye 2024-12-11 17:58 106浏览
  • 天问Block和Mixly是两个不同的编程工具,分别在单片机开发和教育编程领域有各自的应用。以下是对它们的详细比较: 基本定义 天问Block:天问Block是一个基于区块链技术的数字身份验证和数据交换平台。它的目标是为用户提供一个安全、去中心化、可信任的数字身份验证和数据交换解决方案。 Mixly:Mixly是一款由北京师范大学教育学部创客教育实验室开发的图形化编程软件,旨在为初学者提供一个易于学习和使用的Arduino编程环境。 主要功能 天问Block:支持STC全系列8位单片机,32位
    丙丁先生 2024-12-11 13:15 77浏览
我要评论
0
点击右上角,分享到朋友圈 我知道啦
请使用浏览器分享功能 我知道啦