Linux Alsa

Alsa官网:https://www.alsa-project.org/wiki/Main_Page
音频通路 : https://wenku.baidu.com/view/dacb0922af45b307e87197a2.html

ALSA设备文件结构

命令 : cd /dev/snd ; ls -l

crw-rw----+ 1 root audio 116, 8 2011-02-23 21:38 controlC0	 用于声卡的控制,例如通道选择,混音,麦克风的控制等 
crw-rw----+ 1 root audio 116, 4 2011-02-23 21:38 midiC0D0	 用于播放midi音频 
crw-rw----+ 1 root audio 116, 7 2011-02-23 21:39 pcmC0D0c	 用于录音的pcm设备 
crw-rw----+ 1 root audio 116, 6 2011-02-23 21:56 pcmC0D0p	 用于播放的pcm设备 
crw-rw----+ 1 root audio 116, 3 2011-02-23 21:38 seq		 音序器 
crw-rw----+ 1 root audio 116, 2 2011-02-23 21:38 timer	     定时器

其中,C0D0代表的是声卡0中的设备0 ; pcmC0D0c最后一个c代表capture ; pcmC0D0p最后一个p代表playback。

音频参数的理解

声道

  • 单声道:mono
  • 双声道:stereo。最常见的类型,包含左声道以及右声道
  • 2.1声道:在双声道基础上加入一个低音声道
  • 5.1声道:包含一个正面声道、左前方声道、右前方声道、左环绕声道、右环绕声道、一个低音声道,最早应用于早期的电影院

采样率

音频采样,是把声音从模拟信号转换为数字信号。采样率,就是每秒对声音进行采集的次数,同样也是所得的数字信号的每秒样本数

采样越高,声音的还原就越真实越自然,人对频率的识别范围是 20HZ - 22000HZ, 如果每秒钟能对声音做 22000 个采样, 回放时就足可以满足人耳的需求. 所以 22050 的采样频率是常用的, 根据奈奎斯特采样定理44100Hz是不失真的情况下的采样率, 超过48000的采样对人耳已经没有意义。

采样位数

采样位数是指采样时候的计量单位,8bit (也就是1字节) 只能记录 256 个数, 也就是只能将振幅划分成 256 个等级;16bit (也就是2字节) 可以细到 65536 个数;

样本格式

样本组合格式

  • 交错(interleaved)。以stereo为例,一个stereo音频的样本是由两个单声道的样本交错地进行存储得到的,即A1-B1-A2-B2-A3-B3样式存储。
  • 平面(planar)。各个声道的样本分开进行存储,即A1-A2-A3-B1-B2-B3样式存储。

样本格式

enum AVSampleFormat {
    AV_SAMPLE_FMT_NONE = -1,
    AV_SAMPLE_FMT_U8,          ///< unsigned 8 bits
    AV_SAMPLE_FMT_S16,         ///< signed 16 bits
    AV_SAMPLE_FMT_S32,         ///< signed 32 bits
    AV_SAMPLE_FMT_FLT,         ///< float
    AV_SAMPLE_FMT_DBL,         ///< double
 
    AV_SAMPLE_FMT_U8P,         ///< unsigned 8 bits, planar
    AV_SAMPLE_FMT_S16P,        ///< signed 16 bits, planar
    AV_SAMPLE_FMT_S32P,        ///< signed 32 bits, planar
    AV_SAMPLE_FMT_FLTP,        ///< float, planar
    AV_SAMPLE_FMT_DBLP,        ///< double, planar
    AV_SAMPLE_FMT_S64,         ///< signed 64 bits
    AV_SAMPLE_FMT_S64P,        ///< signed 64 bits, planar
 
    AV_SAMPLE_FMT_NB           ///< Number of sample formats. DO NOT USE if linking dynamically
};

U8(无符号整型8bit)、S16(整型16bit)、S32(整型32bit)、FLT(单精度浮点类型)、DBL(双精度浮点类型)、S64(整型64bit),不以P为结尾的都是interleaved结构,以P为结尾的是planar结构。
Planar模式是FFmpeg内部存储模式,我们实际使用的音频文件都是Packed模式的。

比特率

每秒的传输速率(位速, 也叫比特率)。如12.5kbps 或 12500bps, 其中的 b 是 bit, ps 是每秒(per second)的意思,表示每秒12500bit的容量。压缩的音频文件常常用倍速来表示,譬如达到CD音质的MP3是128kbps/44100HZ。注意这里的单位是bit而不是Byte,一个Byte=8bit(位),bit是最小的单位,一般用于网络速度的描述和各种通信速度,Byte则用于计算硬盘,内存的大小。

alsa相关函数及文件

函数及结构体

  1. AVFrame iFrame 存储非压缩的数据,输入

  2. AVFrame swapFrame 存储非压缩的数据,重采样

  3. AVPack oPacket 压缩即编码后的输入,输出

  4. snd_pcm_hw_params_get_rate( )

  5. snd_config_update_ref
    这个函数作用是检查alsa配置文件是否发生了变化,包括文件名字和各个配置文件的内容是否修改,如果有修改,就重新加载配置文件树,刷新全局变量snd_config并增加一个snd_config的引用计数,调用snd_config_update_ref传入的top就是指向snd_config的指针,这个top当作参数传入snd_pcm_open_noupdate函数中。snd_config_unref接下来会减去snd_config的引用计数。
    首先创建顶层配置节点,然后打开/usr/share/alsa/alsa.conf,加载文件内容到顶层配置节点上,然后遍历所有的hooks,调用snd_config_hooks加载所有hooks,并调用相关的hooks函数打开对应的plugin动态库。

  6. avcodec_open2( )
    检测指定的codec和context里面的codec是否匹配。
    分配空间。
    检测codec各个参数合法性,并给某些字段赋初值。
    调用codec的init初始化codec。
    释放资源,返回。

配置文件

参考网址 : https://www.cnblogs.com/lihaiping/p/alsaconfig.html
配置文件的调用过程

alsa-lib库 : alsa-lib-1.2.1.2/src/pcm/pcm.c

snd_pcm_open( ) 函数作为打开一个pcm的接口. 具体的调用过程是 : static snd_pcm_open_noupdate ----> static snd_pcm_open_conf( )

解析asound.conf过程 : https://www.xuebuyuan.com/1043778.html

snd_pcm_open内部直接解析的是usr/share/alsa/alsa.conf, 在这个文件中决定了etc/asound.conf和/.asoundrc这两个文件要不要调用

音频设备的定义

文件定义位置 : /system/core/include/system/audio.h
 enum {
     AUDIO_DEVICE_NONE                          = 0x0,
     /* reserved bits */
     AUDIO_DEVICE_BIT_IN                        = 0x80000000,
     AUDIO_DEVICE_BIT_DEFAULT                   = 0x40000000,
     /* output devices */
     AUDIO_DEVICE_OUT_EARPIECE                  = 0x1,    // 听筒
     AUDIO_DEVICE_OUT_SPEAKER                   = 0x2,    // 扬声器
     AUDIO_DEVICE_OUT_WIRED_HEADSET             = 0x4,    // 线控耳机,可以通过耳机控制远端播放、暂停、音量调节等功能的耳机
     AUDIO_DEVICE_OUT_WIRED_HEADPHONE           = 0x8,    // 普通耳机,只能听,不能操控播放
     AUDIO_DEVICE_OUT_BLUETOOTH_SCO             = 0x10,   // 单声道蓝牙耳机,十进制32
     AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET     = 0x20,   // 车载免提蓝牙设备,十进制64
     AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT      = 0x40,   // 立体声蓝牙耳机
     AUDIO_DEVICE_OUT_BLUETOOTH_A2DP            = 0x80,   // 十进制128
     AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES = 0x100,  // 十进制256
     AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER    = 0x200,  // 十进制512
     AUDIO_DEVICE_OUT_AUX_DIGITAL               = 0x400,  // 十进制1024
     AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET         = 0x800,  // 十进制2048
     AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET         = 0x1000, // 十进制4096
 };

alsa插件

asound.conf配置 https://www.alsa-project.org/main/index.php/Asoundrc
插件配置 https://www.alsa-project.org/alsa-doc/alsa-lib/pcm_plugins.html

生成alsa配置文件 : alsactl store -f a.conf
对于耳机的controls需要指定-c 1,默认走的是card 0
播放音频的命令 arecord -D usbheadsetC -d 5 -f cd -r 48000 -c 2 -t wav test.wav

//查看控件
# amixer -c 1 controls 
numid=3,iface=MIXER,name='PCM Playback Switch'
numid=4,iface=MIXER,name='PCM Playback Volume'
numid=6,iface=MIXER,name='usbCapture_vol'
numid=5,iface=MIXER,name='usbPlay_vol'
numid=1,iface=PCM,name='Capture Channel Map'
numid=2,iface=PCM,name='Playback Channel Map'

//对控件进行配置
# amixer -c 1 sget usbCapture_vol 
Simple mixer control 'usbCapture_vol',0
  Capabilities: volume
  Playback channels: Front Left - Front Right
  Capture channels: Front Left - Front Right
  Limits: 0 - 255
  Front Left: 100 [39%]
  Front Right: 100 [39%]
# amixer -c 1 cget numid=5,iface=MIXER,name='usbCapture_vol'
numid=5,iface=MIXER,name='usbCapture_vol'
  ; type=INTEGER,access=rw---RW-,values=2,min=0,max=255,step=0
  : values=100,100
  | dBscale-min=-20.00dB,step=0.20dB,mute=0
  
//查看录音设备
# arecord -l
**** List of CAPTURE Hardware Devices ****
card 0: smartpenknot [smartpen_knot], device 0: i2s-ecodec nau8822-hifi-0 []
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 0: smartpenknot [smartpen_knot], device 1: dmic dmic-codec-hifi-1 []
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 0: smartpenknot [smartpen_knot], device 2: i2s-tloop pcm-dump-2 []
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 1: EP3C [Meizu EP3C], device 0: USB Audio [USB Audio]
  Subdevices: 1/1
  Subdevice #0: subdevice #0


//查看播放设备
# aplay -l
**** List of PLAYBACK Hardware Devices ****
card 0: smartpenknot [smartpen_knot], device 0: i2s-ecodec nau8822-hifi-0 []
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 1: EP3C [Meizu EP3C], device 0: USB Audio [USB Audio]
  Subdevices: 0/1
  Subdevice #0: subdevice #0

alsa音频工具

arecode录音

  • 查看录音设备 : arecode -l
  • 命令实例 : arecord -D hw:0,1 -d 10 -f cd -r 44100 -c 2 -t wav test.wav
  • 参数解析 :
    -D 指定了录音设备,0,1 是card 0 device 1
    -d 指定录音的时长,单位 : 秒
    -f 指定采样格式,通过上面的信息知道只支持 cd cdr dat
    -r 指定了采样率,单位 : Hz
    -c 指定channel 个数
    -t 指定生成的文件格式

aplay放音

  • 查看放音设备 : aplay -l
  • 命令实例 : aplay test.wav
    如果是直接播放pcm数据,则需要指定pcm格式 、采样率、channel个数等。例如:aplay -t raw -r 16000 -e signed-integer -b 16 -c 1 test.wav

amixer配参

使用方法 :

  1. 用 # amixer controls 列出所有控制项。( 显示接口函数 )
  2. 如果对控制项不熟悉或者想查看当前的所有配置可以使用 # amixer contents 命令。(显示当前配置)
  3. 查看获取某个设置项的值用 # amixer cget + 控制参数 命令。 这里控制参数直接复制 # amixer controls 打印出来的数据就可以
  4. 根据控制参数类型设置控制参数使用 # amixer cset + 控制参数 + 设置参数 命令。
    values 表示数值对于 volume 之类的是具体的数字,在上下文菜单中有显示数值的范围,对于 switch 之类的表示开关一般是 on 或 off。

另外一sget/sset系列的命令, 与cget/cset的使用相同

//例:
//给的参数看value需要几个,需要什么类型进行相应的配置即可
/ # amixer cget numid=43,iface=MIXER,name='Speaker Playback Volum'
numid=43,iface=MIXER,name='Speaker Playback Volume'
  ; type=INTEGER,access=rw---R--,values=2,min=0,max=63,step=0
  : values=63,63
  | dBscale-min=-57.00dB,step=1.00dB,mute=0
/ # 
/ #
/ # amixer cset numid=43,iface=MIXER,name='Speaker Playback Volum' 30 30 
numid=43,iface=MIXER,name='Speaker Playback Volume'
  ; type=INTEGER,access=rw---R--,values=2,min=0,max=63,step=0
  : values=30,30
  | dBscale-min=-57.00dB,step=1.00dB,mute=0
/ # 

保存及恢复方法

  • 对声卡信息状态进行保存 : alsactl store -f /var/lib/alsa/asound.state
  • 声卡状态恢复命令 : alsactl restore -f /var/lib/alsa/asound.state

Linux音频分析工具

  • 名字 : audacity
  • 下载方法 : sudo apt install audacity -o Acquire::http::proxy=“http://…/”( -o 参数可以指定代理)
  • 使用方法 : 直接命令行 audacity , 添加音频观察即可

Q&A

Q1:数据存储出来只有78字节,但是写函数已经执行完毕?

A1:这只是写了一个文件头,而最终文件没有写入。原因是:avio_open之后没有关闭,调用closep函数之后数据正常写入;
调试流程:首先定位问题位置。在alsa录音完成之后将数据写入buffer中存储来看是否是alsa部分的录音问题。之后根据流程进行检查。一定要注意open close / new delete / 等配套的使用

av_write_trailer的作用

  1. 循环调用interleave_packet()以及write_packet(),将还未输出的AVPacket输出出来。
  2. 调用AVOutputFormat的write_trailer(),输出文件尾。 avio_closep的作用 关闭输出文件的上下文,与avio_open相对应使用
    这两个的使用需要保证av_write_trailer函数调用早于avio_closep 如果不调用这两个函数会导致最终文件不能写出

Q2:重采样时 channel 可以正常转换, sample_rate采样率变化不能转换?
A2:在做采样率的重采样时, 对输出的context配置需要将采样点也做一下转换,否则已经转换成功但是生成的文件大小还是按照以前的输出进行.
采样点转换函数 : av_rescale_rnd(iFrame->nb_samples, oSampleRate, iSampleRate, AV_ROUND_UP);

Q3 : 录音之后声音太小, 甚至有时候听不到, 需要如何调整?
A3: 通过amixer参数进行相应的配置.

/recode # amixer cset numid=53,iface=MIXER,name=‘DMIC GAIN’ 15
numid=53,iface=MIXER,name=‘DMIC GAIN’ ;
type=INTEGER,access=rw—R–,values=1,min=0,max=31,step=0 :
values=15 | dBscale-min=0.00dB,step=3.00dB,mute=0
//此步骤完成了dmic增益调整为15的过程

Q4: 耳机音量小但是amixer没有相关可以配置的参数?
A4: 通过asound.conf配置新的插件。

### Linux ALSA配置和故障排除 #### 了解ALSA架构及其组件 ALSA的主要目标是为Linux提供一个先进的、灵活的音频架构,以取代旧的OSS(Open Sound System)。其设计使得Linux可以支持更多种类的音频设备,包括内置声卡、USB音频设备、PCI音频设备等,并提供更好的音频性能和更多的功能[^1]。 #### 基本配置方法 对于大多数现代发行版,默认情况下已经安装并配置好了ALSA。然而,在某些特定场景下可能需要手动调整设置来优化音效或解决问题。通常可以通过编辑`/etc/asound.conf`全局配置文件或是用户的`.asoundrc`个人配置文件来进行自定义设定。这些文件允许用户指定默认设备、混音器控制以及其他高级选项。 #### 故障排查技巧 当遇到声音输出异常的情况时,可以从以下几个方面入手: - **确认模块加载状态** 使用命令 `lsmod | grep snd` 来查看当前已加载的声音驱动模块列表。如果发现缺少必要的alsa模块,则可通过`sudo modprobe <module_name>` 加载相应模块。 - **检查设备权限** 确认普通用户是否有权访问音频硬件节点 `/dev/snd/*` 。这通常是通过将用户加入audio组实现:`sudo usermod -aG audio $USER` - **利用工具辅助诊断** 工具如inxi是一个用于Linux和BSD系统的命令行系统信息工具。它具有良好的易用性和高度定制化输出的特点,能够快速提供关于您的硬件、操作系统、内核、驱动程序等方面的信息,有助于定位潜在的问题所在[^2]。 - **监听日志消息** 实时观察系统日志可以帮助捕捉到有关音频子系统错误提示的关键线索。例如执行`tail -f /var/log/syslog` 或者针对dmesg中的警告与错误记录做进一步分析。 - **测试播放能力** 尝试使用简单的aplay命令直接向选定的目标设备发送PCM流数据包作为初步验证手段之一。比如: ```bash echo "Testing sound playback..." aplay -D hw:CARD=Device,DEV=0 /usr/share/sounds/alsa/Front_Center.wav ``` 上述例子假设存在名为"Device"的声卡并且选择了第一个逻辑设备编号(即0),实际操作前需依据实际情况替换参数值。 #### 特定案例分享 在一个实例中,为了使DragonFly在基于Ubuntu 15.10环境下获得稳定高效的音频表现,采用了音乐播放软件QuodLibet 并将其配置成直通模式(ALSA backend)的方式绕过了额外处理层从而减少了不必要的延迟及失真现象的发生。最终结果显示整个过程流畅无误,既没有出现杂音也没有其他干扰因素影响正常使用体验[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值