本人在研究瑞星微RK3568时由于要使用音频,初步进行了探索,记录使用方法和驱动相关的内容以供自己和其他人后期使用。
- 音频驱动框架介绍
ALSA(Advanced Linux Sound Architecture)是linux上主流的音频结构,在没有出现ALSA架构之前,一直使用的是OSS(Open Sound System)音频架构。关于OSS和ALSA音频架构之间的区别图如下:
主要的区别就是在OSS架构下,App访问底层是直接通过Sound设备节点访问的。而在ALSA音频架构下,App是通过ALSA提供的alsa-lib库访问底层硬件的操作,不再访问Sound设备节点了。这样做的好处可以简化App实现的难度。同样ALSA为了兼容OSS,ALSA提供了内核模块来模拟OSS声音驱动,所以在OSS架构下编写的App无需修改就可以在ALSA下运行。另外libaoos库也可以模拟OSS,无需OSS相关的内核模块。
- ALSA接口信息
proc接口,关于音频的proc接口,位于/proc/asound目录下
参数说明如下:
card0: 其中0代表的是声卡号,每个声卡系统都存在这样的目录。
cards: 列出系统中可用的,注册的声卡。可以看到RK809已经注册成功。
devices: 列出系统card下所有注册的device,包括control,pcm,timer,seq等等,查看声卡下的功能设备。devices字段详细解释,会在后面更了解各个字段的含义。
modoles: 列出所有ALSA声卡驱动模块列表。
oss: 此目录下包含了ALSA用来模拟OSS的模拟仿真模块。
pcm: 列去出系统的cpm设备,包括capture和playback。
seq: 此目录保护一些音序相关的信息。
timers: 描述一些ALSA相关的定时器信息。
version: 描述ALSA版本信息。
devices字段信息:
对于devices的print格式如下:
- Control设备: “minor: [card_id] : control”;
- PCM设备 : “minor: [card_id- device_id]: digital audio playback/capture”;
- timer设备 : “minor: : timer”;
注意:可以看到上图中,设备 [0,0]既是数字音频播放设备,又是数字音频捕获设备,
hwdep: 列出所有硬件依赖(hardward dependent)的设备。此设备不是所有系统上都存在的。
查看声卡采集、播放PCM信息 cat /proc/asound/pcm
查看ALSA驱动版本 cat /proc/asound/version
查看声卡0的信息 cat /proc/asound/card0/pcm0p/sub0/status
查看时钟clk summary: cat /sys/kernel/debug/clk/clk_summary | egrep "i2s0|pll"
示例:查询 i2s0 mclk 频率,以及其所在的 pll,结果:mclk 为 12288000 Hz,pll 源为 cpll
2.dev接口信息
关于sound的dev节点信息,位于/dev/snd下
介绍写各个设备文件的功能:
control: 用于声卡的控制。
pcmC0D0c: 用于录音的pcm设备。
pcmC0D0p: 用于播音的pcm设备。
seq: 音序器接口。
timer: 定时器接口。
其中,C0D0 代表的是声卡 0 中的设备 0,pcmC0D0c 最后一个 c 代表 Capture,pcmC0D0p 最后一个 p 代表 Playback,这些都是 alsa-driver 中的命名规则。
- 音频调试和使用
ALSA软件由alsa-lib和alsa-utils组成,前者是用户空间库,供用户app调用使用,后者是测试工具包,供测试使用。
1.用户linux C使用
从用户空间打开 PCM 设备过程如下:
snd_pcm_open("default", SND_PCM_STREAM_PLAYBACK) // alsa-lib 接口
open("/dev/snd/controlC0") // 打开控制设备; 主设备 116, 次设备 0
open("/dev/snd/pcmC0D0p") // 打开PCM设备; 主设备 116, 次设备 16
snd_open() // 根据主设备号找到该入口
snd_minors[minor] // 根据次设备号找到对应操作集
snd_ctl_f_ops::open() // 控制设备打开方法
snd_ctl_open()snd_pcm_f_ops::open() // PCM设备打开方法
snd_pcm_playback_open()
snd_lookup_minor_data() // 根据次设备号查找对应 PCM 设备(snd_pcm)
snd_pcm_open() // 打开 PCM 播放子流
2.设备调试
alsa-utils 包含的工具有:alsactl, aconnect, alsamixer, amidi, amixer, aplay, aplaymidi, arecord, arecordmidi, aseqnet, iecset, speaker-test
其中比较重要的也是后面要使用到的有,alsamixer,amixer,aplay,arecord。
alsamixer是图像化的音频配置工具,是基于文本下的图形界面的,可以通过键盘的上下键,左右键等,很方便地设置需要的音量,开关某个 switch(开关)等等操作。
amixer是音频配置工具,控制 codec 内部的通路开关,结合 codec 手册的音频拓扑图实现音频流的路由,音量控制等。amixer是 alsamixer 的文本模式,即命令行模式,需要用 amixer 命令的形式去配置你的声卡的各个选项。对于amixer 的使用,你首先需要搞懂你要设置的参数是哪些,然后才可能去了解,如何去配置对应的值,相对 alsamixer来说,amixer是有点繁琐。
amixer 使用
Usage: amixer <options> [command]
Available options:
-h,--help this help
-c,--card N select the card
-D,--device N select the device, default 'default'
-d,--debug debug mode
-n,--nocheck do not perform range checking
-v,--version print version of this program
-q,--quiet be quiet
-i,--inactive show also inactive controls
-a,--abstract L select abstraction level (none or basic)
-s,--stdin Read and execute commands from stdin sequentially
-R,--raw-volume Use the raw value (default)
-M,--mapped-volume Use the mapped volume
Available commands:
scontrols show all mixer simple controls
scontents show contents of all mixer simple controls (default command)
sset sID P set contents for one mixer simple control
sget sID get contents for one mixer simple control
controls show all controls for given card
contents show contents of all controls for given card
cset cID P set control contents for one control
cget cID get control contents for one control
amixer 软件命令分为两组, scontrols、 scontents、 sset 和 sget 为一一组。 controls、 contents、 cset 和 cget 为另一组。这两组的基本功能都是一样的,只不过“ s”开头的是 simple(简 单)组,这一组命令是简化版,如下是使用controls/scontrols和contents/scontents的结果。
参数含义如下表:
Playback Path | 音频输出通道 | |
Capture MIC Path | 音频输入通道 | |
Voice Call Pah | 通话音频通道 | 设备没有通话模块,暂无法測试 |
Voip Pah | IP电话音频通道 | 场景Gtalk;值有:SPK/HP_NO_MIC/BT |
Speaker Playback Volume | 扬声器音量 | 和上层音量值无关 |
Headphone Playback Volume | 耳机音量 | 同上 |
Modem Input Enable | 暂不知何用 | 经測试不能控制音频输入输出 |
Playback Path有:
英文 | 中文 | 英文 | 中文 |
OFF | 关闭 | SPK_HP | - |
RCV | - | RING_SPK | - |
SPK | 扬声器 | RING_HP | - |
HP | 耳机带麦 | RING_HP_NO_MIC | - |
HP_NO_MIC | 耳机无麦 | RING_SPK_HP | - |
BT | 蓝牙 |
在使用音频设备前一定要对音频设备进行设置,如 amixer contents结果所示:
上图中绿框为可以控制的设备,红框为该设备的具体信息,分号为注释信息,冒号为具体参数值,例如上图中音频输出通道(Playback Path)设备,取值为3代表,当前正在使用HP模式即耳机带麦模式,则可以播放录制音频,若为OFF模式,即Playback Path中的values=0代表为启用该设备,则不可以放录制音频,可以通过以下命令切换为HP模式:
amixer cset numid=1,iface=MIXER,name='Playback Path' 3
也可以使用amixer 修改左右声道的音量
修改右声道音量为12
amixer cset numid=4,iface=MIXER,name='DACR Playback Volume' 12
修改右声道音量为120
amixer cset numid=3,iface=MIXER,name='DACL Playback Volume' 120
注:如左右声道有问题,可尝试使用电脑先控制改变左右声道声音大小,再测试,接触不良时也会出现一个声道无输出。
当然,也可以使用图像化配置工具alsamixer来配置,如下图
如果终端界面显示不全,可以在终端中使用stty或者resize来同步终端尺寸大小。
音频播放命令aplay
Usage: aplay [OPTION]... [FILE]...
-h, --help help
--version print current version
-l, --list-devices list all soundcards and digital audio devices
-L, --list-pcms list device names
-D, --device=NAME select PCM by name
-q, --quiet quiet mode
-t, --file-type TYPE file type (voc, wav, raw or au)
-c, --channels=# channels
-f, --format=FORMAT sample format (case insensitive)
-r, --rate=# sample rate
-d, --duration=# interrupt after # seconds
-M, --mmap mmap stream
-N, --nonblock nonblocking mode
-F, --period-time=# distance between interrupts is # microseconds
-B, --buffer-time=# buffer duration is # microseconds
--period-size=# distance between interrupts is # frames
--buffer-size=# buffer duration is # frames
-A, --avail-min=# min available space for wakeup is # microseconds
-R, --start-delay=# delay for automatic PCM start is # microseconds
(relative to buffer size if <= 0)
-T, --stop-delay=# delay for automatic PCM stop is # microseconds from xrun
-v, --verbose show PCM structure and setup (accumulative)
-V, --vumeter=TYPE enable VU meter (TYPE: mono or stereo)
-I, --separate-channels one file for each channel
-i, --interactive allow interactive operation from stdin
-m, --chmap=ch1,ch2,.. Give the channel map to override or follow
--disable-resample disable automatic rate resample
--disable-channels disable automatic channel conversions
--disable-format disable automatic format conversions
--disable-softvol disable software volume control (softvol)
--test-position test ring buffer position
--test-coef=# test coefficient for ring buffer position (default 8)
expression for validation is: coef * (buffer_size / 2)
--test-nowait do not wait for ring buffer - eats whole CPU
--max-file-time=# start another output file when the old file has recorded
for this many seconds
--process-id-file write the process ID here
--use-strftime apply the strftime facility to the output file name
--dump-hw-params dump hw_params of the device
--fatal-errors treat all errors as fatal
Recognized sample formats are: S8 U8 S16_LE S16_BE U16_LE U16_BE S24_LE S24_BE U24_LE U24_BE S32_LE S32_BE U32_LE U32_BE FLOAT_LE FLOAT_BE FLOAT64_LE FLOAT64_BE IEC958_SUBFRAME_LE IEC958_SUBFRAME_BE MU_LAW A_LAW IMA_ADPCM MPEG GSM SPECIAL S24_3LE S24_3BE U24_3LE U24_3BE S20_3LE S20_3BE U20_3LE U20_3BE S18_3LE S18_3BE U18_3LE U18_3BE G723_24 G723_24_1B G723_40 G723_40_1B DSD_U8 DSD_U16_LE DSD_U32_LE DSD_U16_BE DSD_U32_BE
Some of these may not be available on selected hardware
The available format shortcuts are:
-f cd (16 bit little endian, 44100, stereo)
-f cdr (16 bit big endian, 44100, stereo)
-f dat (16 bit little endian, 48000, stereo)
用 aplay -l 可以列出声卡和数字音频设备
通过声卡0播放48k采样率2声道16位的静音数据
aplay -D hw:0,0 --period-size=1024 --buffer-size=4096 -r 48000 -c 2 -f s16_le /dev/zero
使用设备0,0播放Lambada.wav
aplay -Dhw:0,0 Lambada.wav
注意,如果wav音频格式不对,可以使用windows软件Audacity将MP3转为wav,转换时注意采样率和位数,否者会有以下错误。
正常播放如下:
音频录制命令arecord
Usage: arecord [OPTION]... [FILE]...
-h, --help help
--version print current version
-l, --list-devices list all soundcards and digital audio devices
-L, --list-pcms list device names
-D, --device=NAME select PCM by name
-q, --quiet quiet mode
-t, --file-type TYPE file type (voc, wav, raw or au)
-c, --channels=# channels
-f, --format=FORMAT sample format (case insensitive)
-r, --rate=# sample rate
-d, --duration=# interrupt after # seconds
-M, --mmap mmap stream
-N, --nonblock nonblocking mode
-F, --period-time=# distance between interrupts is # microseconds
-B, --buffer-time=# buffer duration is # microseconds
--period-size=# distance between interrupts is # frames
--buffer-size=# buffer duration is # frames
-A, --avail-min=# min available space for wakeup is # microseconds
-R, --start-delay=# delay for automatic PCM start is # microseconds
(relative to buffer size if <= 0)
-T, --stop-delay=# delay for automatic PCM stop is # microseconds from xrun
-v, --verbose show PCM structure and setup (accumulative)
-V, --vumeter=TYPE enable VU meter (TYPE: mono or stereo)
-I, --separate-channels one file for each channel
-i, --interactive allow interactive operation from stdin
-m, --chmap=ch1,ch2,.. Give the channel map to override or follow
--disable-resample disable automatic rate resample
--disable-channels disable automatic channel conversions
--disable-format disable automatic format conversions
--disable-softvol disable software volume control (softvol)
--test-position test ring buffer position
--test-coef=# test coefficient for ring buffer position (default 8)
expression for validation is: coef * (buffer_size / 2)
--test-nowait do not wait for ring buffer - eats whole CPU
--max-file-time=# start another output file when the old file has recorded
for this many seconds
--process-id-file write the process ID here
--use-strftime apply the strftime facility to the output file name
--dump-hw-params dump hw_params of the device
--fatal-errors treat all errors as fatal
Recognized sample formats are: S8 U8 S16_LE S16_BE U16_LE U16_BE S24_LE S24_BE U24_LE U24_BE S32_LE S32_BE U32_LE U32_BE FLOAT_LE FLOAT_BE FLOAT64_LE FLOAT64_BE IEC958_SUBFRAME_LE IEC958_SUBFRAME_BE MU_LAW A_LAW IMA_ADPCM MPEG GSM SPECIAL S24_3LE S24_3BE U24_3LE U24_3BE S20_3LE S20_3BE U20_3LE U20_3BE S18_3LE S18_3BE U18_3LE U18_3BE G723_24 G723_24_1B G723_40 G723_40_1B DSD_U8 DSD_U16_LE DSD_U32_LE DSD_U16_BE DSD_U32_BE
Some of these may not be available on selected hardware
The available format shortcuts are:
-f cd (16 bit little endian, 44100, stereo)
-f cdr (16 bit big endian, 44100, stereo)
-f dat (16 bit little endian, 48000, stereo)
示例:通过声卡0 录制 16k 采样率 8声道 32 位 的音频数据
arecord -D hw:0,0 --period-size=1024 --buffer-size=4096 -r 16000 -c 8 -f s32_le r.wav
aplay | arecord
两者通过管道可以方便的实现 loopback 功能,方便驱动调试和指标测试。
示例:声卡0 录制 -> 声卡1 播放
arecord -D hw:0,0 --period-size=1024 --buffer-size=4096 -r 48000 -c 2 -f s16_le
-t raw | aplay -D hw:1,0 --period-size=1024 --buffer-size=4096 -r 48000 -c 2 -f
s16_le -t raw
alsaloop
支持任意声卡间的路由;支持自适应时钟同步;自持自适应重采样;支持mixer controls 重定向;
Usage: alsaloop [OPTION]...
-h,--help help
-g,--config configuration file (one line = one job specified)
-d,--daemonize daemonize the main process and use syslog for errors
-P,--pdevice playback device
-C,--cdevice capture device
-X,--pctl playback ctl device
-Y,--cctl capture ctl device
-l,--latency requested latency in frames
-t,--tlatency requested latency in usec (1/1000000sec)
-f,--format sample format
-c,--channels channels
-r,--rate rate
-n,--resample resample in alsa-lib
-A,--samplerate use converter (0=sincbest,1=sincmedium,2=sincfastest,
3=zerohold,4=linear)
-B,--buffer buffer size in frames
-E,--period period size in frames
-s,--seconds duration of loop in seconds
-b,--nblock non-block mode (very early process wakeup)
-S,--sync sync mode(0=none,1=simple,2=captshift,3=playshift,4=samplerate,
5=auto)
-a,--slave stream parameters slave mode (0=auto, 1=on, 2=off)
-T,--thread thread number (-1 = create unique)
-m,--mixer redirect mixer, argument is:
SRC_SLAVE_ID(PLAYBACK)[@DST_SLAVE_ID(CAPTURE)]
-O,--ossmixer rescan and redirect oss mixer, argument is:
ALSA_ID@OSS_ID (for example: "Master@VOLUME")
-e,--effect apply an effect (bandpass filter sweep)
-v,--verbose verbose mode (more -v means more verbose)
-w,--workaround use workaround (serialopen)
-U,--xrun xrun profiling
-W,--wake process wake timeout in ms
-z,--syslog use syslog for errors
Recognized sample formats are: S8 U8 S16_LE S16_BE U16_LE U16_BE S24_LE S24_BE U24_LE U24_BE S32_LE S32_BE U32_LE U32_BE FLOAT_LE FLOAT_BE FLOAT64_LE FLOAT64_BE IEC958_SUBFRAME_LE IEC958_SUBFRAME_BE MU_LAW A_LAW IMA_ADPCM MPEG GSM SPECIAL S24_3LE S24_3BE U24_3LE U24_3BE S20_3LE S20_3BE U20_3LE U20_3BE S18_3LE S18_3BE U18_3LE U18_3BE G723_24 G723_24_1B G723_40 G723_40_1B DSD_U8 DSD_U16_LE DSD_U32_LE DSD_U16_BE
Tip #1 (usable 500ms latency, good CPU usage, superb xrun prevention):
alsaloop -t 500000
Tip #2 (superb 1ms latency, but heavy CPU usage):
alsaloop -t 1000
示例:声卡0录制的音频通过声卡1播放,同步模式采用 策略1(增加或减少采样点)
alsaloop -C hw:0,0 -P hw:1,0 -t 10000 -A 3 -S 1 -b -v