驱动适配
1. 配置USB控制器为otg或者host
bash
&usb_otg0 {
dr_mode = "otg";
vbus-supply = <&vbus_regulator0>;
status = "okay";
};
编译系统,插入设备查看设备状态:
bash
[ 35.196082] usb 1-1: new full-speed USB device number 2 using dwc2
[ 35.441393] input: C-Media Electronics Inc. AD2000 as /devices/platform/soc/11c0000.usb/usb1/1-1/1-1:1.0/0003:0D8C:033D.0001/input/input0
[ 35.516342] hid-generic 0003:0D8C:033D.0001: input,hidraw0: USB HID v1.10 Device [C-Media Electronics Inc. AD2000] on usb-11c0000.usb-1/input0
[ 37.556148] usb 1-1: USB disconnect, device number 2
[ 38.046082] usb 1-1: new full-speed USB device number 3 using dwc2
[ 38.291123] input: C-Media Electronics Inc. AD2000 as /devices/platform/soc/11c0000.usb/usb1/1-1/1-1:1.0/0003:0D8C:033D.0002/input/input1
[ 38.367191] hid-generic 0003:0D8C:033D.0002: input,hidraw0: USB HID v1.10 Device [C-Media Electronics Inc. AD2000] on usb-11c0000.usb-1/input0
~ # lsusb
Bus 003 Device 001: ID 1d6b:0002
Bus 002 Device 002: ID 0483:5740
Bus 001 Device 001: ID 1d6b:0002
Bus 001 Device 003: ID 0d8c:033d
Bus 002 Device 001: ID 1d6b:0002
~ # cat /proc/asound/
cards devices pcm timers version
~ # cat /proc/asound/cards
--- no soundcards ---
~ # cat /proc/asound/pcm
由此可见 usb设备已经识别到了,但是还不是uac设备
2. 配置添加uac设备驱动
bash
make ARCH=arm64 CROSS_COMPILE=/opt/toolchain/7.5.0/gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu- menuconfig
bash
Device Drivers --->
<*> Sound card support --->
<*> Advanced Linux Sound Architecture --->
[*] USB sound devices --->
<*> USB Audio/MIDI driver
或者直接添加在defconfig文件中
bash
CONFIG_SND_USB_AUDIO=y
CONFIG_SND_RAWMIDI=y
CONFIG_SND_HWDEP=y
软件库交叉编译
1. 下载源代码(切换至 v1.2.3 标签)
bash
alsa-lib$ git branch
* (头指针分离于 v1.2.3)
master
alsa-utils$ git branch
* (头指针分离于 v1.2.3)
master
2. 编译alsa-lib
生成configure文件
bash
touch ltconfig
libtoolize --force --copy --automake
aclocal $ACLOCAL_FLAGS
autoheader
automake --foreign --copy --add-missing
touch depcomp # seems to be missing for old automake
autoconf
配置生成makefile文件
bash
./configure --host=aarch64-linux-gnu --disable-python
编译并安装
bash
make -j4
make DESTDIR=/home/xxx/git/asound/test/alsa-lib/install install
编译alsa-utils
拷贝alsa.m4文件
bash
cp ../alsa-lib/utils/alsa.m4 m4/
生成configure Makefile 文件,并编译
bash
#!/bin/bash
if test -d ../alsa-lib/utils && ! test -r `aclocal --print-ac-dir`/alsa.m4; then
alsa_m4_flags="-I ../alsa-lib/utils"
fi
aclocal $alsa_m4_flags $ACLOCAL_FLAGS
# save original files to avoid stupid modifications by gettextize
cp Makefile.am Makefile.am.ok
cp configure.ac configure.ac.ok
gettextize -c -f --no-changelog
echo "EXTRA_DIST = gettext.m4" > m4/Makefile.am
cp Makefile.am.ok Makefile.am
cp configure.ac.ok configure.ac
autoheader
automake --foreign --copy --add-missing
touch depcomp # for older automake
autoconf
export LDFLAGS="-L/home/tuning/git/asound/alsa-lib/install/lib" export CFLAGS="-I/home/tuning/git/asound/alsa-lib/install/include"
export PKG_CONFIG_PATH=/home/tuning/git/asound/alsa-lib/install/lib/pkgconfig:$PKG_CONFIG_PATH
export ACLOCAL_FLAGS="-I /home/tuning/git/asound/alsa-lib/utils"
./configure --host=aarch64-linux-gnu --prefix=/home/tuning/git/asound/alsa-lib/install/ --disable-alsamixer --disable-xmlto
make
安装
bash
sudo make install
至此所有的工具和库都在alsa-lib/install 文件中了。
运行时添加下路径:
bash
export LD_LIBRARY_PATH=/home/xxx/git/asound/alsa-lib/install/lib:$LD_LIBRARY_PATH
音频设备调试
其中涉及到一些专业知识和名词,针对调试中遇到的一些参数进行说明。
- aplay -l
bash
# aplay -l
**** List of PLAYBACK Hardware Devices ****
card 0: AD2000 [AD2000], device 0: USB Audio [USB Audio]
Subdevices: 1/1
Subdevice #0: subdevice #0
-
card 0: AD2000 [AD2000]
card 0: 第一个声卡,编号为0
AD2000: 声卡名称,一个 USB 音频设备
-
device 0: 该声卡上的第一个设备,编号为0
USB Audio: 设备名称,表明是通过 USB 连接的音频设备
-
Subdevices: 1/1
该设备有 1个子设备,总共也是1个可用
-
Subdevice #0: subdevice #0
子设备编号 #0,这是唯一可用的子设备
- arecord -D hw:0,0 --dump-hw-params
bash
# arecord -D hw:0,0 --dump-hw-params
Recording WAVE 'stdin' : Unsigned 8 bit, Rate 8000 Hz, Mono
HW Params of device "hw:0,0":
--------------------
ACCESS: MMAP_INTERLEAVED RW_INTERLEAVED
FORMAT: S24_3LE
SUBFORMAT: STD
SAMPLE_BITS: 24
FRAME_BITS: 24
CHANNELS: 1
RATE: 48000
PERIOD_TIME: [1000 3640875]
PERIOD_SIZE: [48 174762]
PERIOD_BYTES: [144 524286]
PERIODS: [2 1024]
BUFFER_TIME: [2000 7281771)
BUFFER_SIZE: [96 349525]
BUFFER_BYTES: [288 1048575]
TICK_TIME: ALL
--------------------
arecord: set_params:1343: Sample format non available
Available formats:
- S24_3LE
- 格式: 只支持 S24_3LE
采样率: 固定 48000 Hz
声道: 只支持 1 个声道(单声道)
精度: 24位,3字节存储
- ./arecord -D plughw:0,0 -f S24_3LE -r 48000 -c 1 -d 5 corrected_test.wav
bash
# ./arecord -D plughw:0,0 -f S24_3LE -r 48000 -c 1 -d 5 corrected_test.wav
Recording WAVE 'corrected_test.wav' : Signed 24 bit Little Endian in 3bytes, Rate 48000 Hz, Mono
[10227.244626] dwc2 11c0000.usb: dwc2_hc_halt() Channel can't be halted
- -D plughw:0,0
使用 ALSA 插件系统,自动进行格式转换。0,0:第一个声卡(card 0)的第一个设备(device 0)
plughw 会在应用程序和硬件之间插入转换层,如果应用程序请求的格式与硬件不匹配,会自动转换。比如:16bit → 24bit,44100Hz → 48000Hz 等 - -f S24_3LE
S24:有符号 24 位,3LE:3字节小端序(Little Endian) - -r 48000
每秒采集 48000 个样本,人耳能听到的频率范围:20Hz - 20,000Hz。根据奈奎斯特定理,48000Hz 能完美录制 0-24,000Hz 的音频,这是专业音频和视频的常用采样率。 - -c 1
单声道录音,您的设备硬件只支持单声道输入。如果设为 -c 2(立体声),plughw 会自动复制单声道数据到两个声道 - -d 5
录制 5 秒后自动停止
计算公式:
c
# 计算 5 秒录音的数据量
位深度:24 bit = 3 字节/样本
采样率:48000 样本/秒
声道数:1 声道
时长:5 秒
数据量 = 3 字节 × 48000 × 1 × 5 = 720,000 字节 ≈ 703 KB
加上 WAV 文件头:约 704 KB
- ./aplay -D plughw:0,0 Front_Center.wav
bash
# ./aplay -D plughw:0,0 Front_Cente
r.wav
Playing WAVE 'Front_Center.wav' : Signed 16 bit Little Endian, Rate 48000 Hz, Mono
[10950.431463] dwc2 11c0000.usb: dwc2_hc_halt() Channel can't be halted
- Mono代表是单声道,Signed 16 bit Little Endian表示这个wav的格式
常见的预设格式:
CD 质量(最常用)
-f cd # S16_LE, 44100Hz, 立体声
DAT 质量
-f dat # S16_LE, 48000Hz, 立体声
DVD 质量
-f dv # S16_LE, 96000Hz, 立体声
电话质量
-f phone # U8, 8000Hz, 单声道
合成立体声
1. 在ubuntu系统找两个文件Side_Left.wav Side_Right.wav
查看音频信息:
bash
$ soxi Side_Right.wav
Input File : 'Side_Right.wav'
Channels : 1
Sample Rate : 48000
Precision : 16-bit
Duration : 00:00:01.35 = 64961 samples ~ 101.502 CDDA sectors
File Size : 130k
Bit Rate : 768k
Sample Encoding: 16-bit Signed Integer PCM
2. 获取两个音频时长
bash
# 获取两个文件的时长
DUR1=$(soxi -D Side_Left.wav)
DUR2=$(soxi -D Side_Right.wav)
# 创建静音文件
sox -n -r 48000 -c 1 silence1.wav trim 0.0 $DUR2
sox -n -r 48000 -c 1 silence2.wav trim 0.0 $DUR1
3. 产生等时长的静音音频文件
bash
sox Side_Left.wav silence1.wav left_final.wav
sox silence2.wav Side_Right.wav right_final.wav
4. 合并两个音频文件
bash
sox -M left_final.wav right_final.wav stereo_output.wav
5. 如果需要拆开进行验证
bash
sox stereo_output.wav left_check.wav remix 1
sox stereo_output.wav right_check.wav remix 2
soxi -D left_check.wav right_check.wav stereo_output.wav
验证了一个事情: 单声道音频文件是不区分左右喇叭的,也就是播放单声道音频文件时,两个喇叭都会响。 立体声音频才区分,如果只想要其中一个喇叭响,那么必须合成立体声音频文件,一个通道为静音,另一个为正常声音。
音频驱动验证:
第一步查看USB驱动,能不能正确识别USB设备:
bash
# lsusb
Bus 003 Device 001: ID 1d6b:0002
Bus 002 Device 002: ID 0483:5740
Bus 001 Device 001: ID 1d6b:0002
Bus 001 Device 009: ID 0d8c:033d
Bus 002 Device 001: ID 1d6b:0002
第二步判断UAC驱动有没有正确识别呢?
拔插设备内核打印如下:
bash
# dmesg | grep -i audio
[ 1.178052] usbcore: registered new interface driver snd-usb-audio
bash
[11495.556303] usb 1-1: USB disconnect, device number 9
[11499.216233] usb 1-1: new full-speed USB device number 10 using dwc2
[11499.461364] input: C-Media Electronics Inc. AD2000 as /devices/platform/soc/11c0000.usb/usb1/1-1/1-1:1.0/0003:0D8C:033D.0009/input/input8
[11499.536472] hid-generic 0003:0D8C:033D.0009: input,hidraw0: USB HID v1.10 Device [C-Media Electronics Inc. AD2000] on usb-11c0000.usb-1/input0
[11501.556298] usb 1-1: USB disconnect, device number 10
[11502.046234] usb 1-1: new full-speed USB device number 11 using dwc2
[11502.291410] input: C-Media Electronics Inc. AD2000 as /devices/platform/soc/11c0000.usb/usb1/1-1/1-1:1.0/0003:0D8C:033D.000A/input/input9
[11502.366485] hid-generic 0003:0D8C:033D.000A: input,hidraw0: USB HID v1.10 Device [C-Media Electronics Inc. AD2000] on usb-11c0000.usb-1/input0
第三步 查看识别到的设备信息
bash
# cat /proc/asound/AD2000/pcm0c/inf
o
card: 0
device: 0
subdevice: 0
stream: CAPTURE
id: USB Audio
name: USB Audio
subname: subdevice #0
class: 0
subclass: 0
subdevices_count: 1
subdevices_avail: 1
# cat /proc/asound/AD2000/pcm0p/inf
o
card: 0
device: 0
subdevice: 0
stream: PLAYBACK
id: USB Audio
name: USB Audio
subname: subdevice #0
class: 0
subclass: 0
subdevices_count: 1
subdevices_avail: 1
bash
# cat /proc/asound/cards
0 [AD2000 ]: USB-Audio - AD2000
C-Media Electronics Inc. AD2000 at usb-11c0000.usb-1, full speed
bash
# cat /proc/asound/pcm
00-00: USB Audio : USB Audio : playback 1 : capture 1
USB相关知识:
bash
ab@zsf:~$ lsusb
Bus 006 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 005 Device 005: ID 0bda:4852 Realtek Semiconductor Corp.
Bus 005 Device 003: ID 27c6:6594
Bus 005 Device 008: ID 0d8c:033d C-Media Electronics, Inc.
Bus 005 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 004 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 003 Device 002: ID 046d:c534 Logitech, Inc. Unifying Receiver
Bus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 002: ID 13d3:5439 IMC Networks
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
ab@zsf:~$ lsusb -t
/: Bus 06.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/2p, 10000M
/: Bus 05.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/4p, 480M
|__ Port 2: Dev 8, If 2, Class=Audio, Driver=snd-usb-audio, 12M
|__ Port 2: Dev 8, If 0, Class=Human Interface Device, Driver=usbhid, 12M
|__ Port 2: Dev 8, If 3, Class=Audio, Driver=snd-usb-audio, 12M
|__ Port 2: Dev 8, If 1, Class=Audio, Driver=snd-usb-audio, 12M
|__ Port 3: Dev 3, If 0, Class=Vendor Specific Class, Driver=, 12M
|__ Port 4: Dev 5, If 1, Class=Wireless, Driver=btusb, 12M
|__ Port 4: Dev 5, If 0, Class=Wireless, Driver=btusb, 12M
/: Bus 04.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/2p, 10000M
/: Bus 03.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/4p, 480M
|__ Port 2: Dev 2, If 0, Class=Human Interface Device, Driver=usbhid, 12M
|__ Port 2: Dev 2, If 1, Class=Human Interface Device, Driver=usbhid, 12M
/: Bus 02.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/2p, 5000M
/: Bus 01.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/2p, 480M
|__ Port 2: Dev 2, If 0, Class=Video, Driver=uvcvideo, 480M
|__ Port 2: Dev 2, If 1, Class=Video, Driver=uvcvideo, 480M
Bus 05.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/4p, 480M
- Bus 05: 第5个USB总线
- Port 1: 根集线器的第1个端口
- Dev 1: 设备号1(通常是主机控制器)
- Driver=xhci_hcd: 使用xhci驱动(USB 3.0控制器)
- 480M: 该总线最高支持USB 2.0速度(480 Mbps)
Port 2: Dev 8, If 2, Class=Audio, Driver=snd-usb-audio, 12M
- Port 2 - 物理端口, 这是主机或USB集线器上的物理插槽编号,表示这个设备插在您电脑的第2个USB物理端口上,是硬件层面的连接点
- Dev 8 - 设备地址,这是USB系统分配给该设备的逻辑地址(8号设备),当设备插入时,主机给它分配一个唯一的编号用于通信,这个编号在每次重新插拔后可能会变化,是软件层面的标识
- If 2 - 接口编号,这是最关键的概念:If = Interface(接口),一个USB设备可以有多个独立的功能,每个功能就是一个Interface,If 2 表示这是该设备的第3个功能接口(从0开始计数)
这个 Dev 8 设备有4个Interface:
If 0: HID(人机交互设备)- 可能是音量控制按钮
If 1: 音频接口 - 可能是音频流传输
If 2: 音频接口 - 可能是另一个音频通道
If 3: 音频接口 - 可能是麦克风输入