12 KiB
ALSA UCM Configurations
此文档介绍了 alsa-ucm-aw-configs 中 UCM 配置文件的语法及约定
目录结构
UCM 配置文件放置在 ucm_configs 目录下, 按芯片级方案名字分类 (astar, azalea, ...); 在芯片级方案目录下, 按板级方案分类 (astar-dm, astar-parrot, ...), 并有一个 Default 目录用于放置该芯片级方案默认的配置文件
alsa-ucm-aw-configs 在编译时, 会根据当前芯片级方案的名字将对应目录下的配置文件拷 贝到小机端的 /usr/share/alsa/ucm 目录; 若当前芯片级方案的配置文件不存在, 则会拷贝 Default 目录下的默认配置文件
ucm_configs
├── astar
│ ├── astar-dm
│ │ ├── AC108
│ │ │ ├── AC108.conf
│ │ │ └── Record.conf
│ │ └── audiocodec
│ │ ├── audiocodec.conf
│ │ └── Play.conf
│ ├── astar-parrot
│ │ └── audiocodec
│ │ ├── audiocodec.conf
│ │ ├── Play.conf
│ │ └── Record.conf
│ └── Default
│ └── audiocodec
│ ├── audiocodec.conf
│ ├── Play.conf
│ └── Record.conf
└── azalea
├── azalea-m2ultra
│ └── audiocodec
│ ├── audiocodec.conf
│ ├── Play.conf
│ └── Record.conf
└── Default
└── audiocodec
├── audiocodec.conf
├── Play.conf
└── Record.conf
UCM 配置文件
一份完整的 UCM 配置文件包括以下内容: card, verb, device, modifier (可选). 想要使 用某个 ALSA 设备并配置它的控件, 需要指定 1 个 card + 1 个 verb + 1 个或以上的 device + 0 个或以上的 modifier.
card
表示声卡, 每个 card 单独一个目录, 每个方案需要包含一个或以上的 card, 如 astar-dm 下的 "AC108" 和 "audiocodec" 分别为两个不同的 card
verb
表示使用案例 (use case), 表明某个特定的使用场景, 每个 card 需要包含一个或以上的 verb, 如 astar-parrot 的 audiocodec 下有 "Play" 和 "Record" 两个 verb
ALSA 官方默认定义有一些 verb 的名字, 如 "HiFi", "Voice", 但为了 Tina 平台下不同 方案的统一, 不推荐 使用这些名字, 而应遵循后面的 verb 的命名约定
device
表示设备, 如 "Headphone", "Speaker" 等, 每个 verb 需要包含一个或以上的 device, 其可用的命名请参考后面的 device 的命名约定
modifier
表示修饰, 是对某个设备使用时附加的一些设置, 使同一个 verb 下的同一个 device 可以 有不同的使用效果, 如 "PlayTone", "PlayMusic" 等. modifier 并不是必须的, 每一个 verb 可以包含零至多个 modifier. 其可用的命名并无限制, 只要遵循通用命名约定 即可
语法
以 ucm_configs/DEMO/Default 目录下的配置文件为例
定义 card
新建一个目录, 并在该目录中新建一个与该目录同名的 .conf 文件, 如目录 democard
及其中的 democard.conf 就定义了一个名为 democard
的 card
democard.conf :
Comment "Comment on democard"
SectionUseCase."Play" {
File "Play.conf"
}
ValueDefaults {
Card "hw:demo"
Foobar "value of Foobar in democard"
}
- 开头的
Comment
关键字是对这个 card 的注释 SectionUseCase
关键字用于定义 verb, 上述例子中定义了名为Play
的 verb, 其 详细内容位于文件 Play.conf 中ValueDefaults
关键字用于定义 card 级别的变量值, 上述例子中定义的Foobar
和Card
变量的有效作用域为该 card 及其以下的 verb, device 和 modifier. 可在 verb, device 或 modifier 中定义同名变量来覆盖这些变量的值
定义 verb
如上所述, 在 democard 这个 card 的定义中, 通过 democard.conf 定义了名为 Play
的 verb, 此时需要创建 Play.conf 文件以描述 Play
的详细内容
Play.conf 中 verb 相关的部分:
SectionVerb {
Commnent "Comment on verb Play"
EnableSequence [
cdev "hw:demo"
cset "name='Play Switch' 1"
]
DisableSequence [
cdev "hw:foobar"
cset "name='Play Switch' 0"
]
Value {
Foobar "Value of Foobar in verb Play"
}
}
SectionVerb
关键字中的就是Play
这个 verb 的内容Comment
关键字是对这个 verb 的注释EnableSequence
指使能这个 verb 时的操作,cdev
指定控件对应的 ALSA 虚拟设备 名字,cset
指定需要操作的控件名字和它的值;DisableSequence
与EnableSequence
类似, 指失能这个 verb 时的操作 (注意 : 由于 ALSA UCM 自身的缺陷,DisableSequence
中的内容实际无法执行, 因此 不推荐 在SectionVerb
中使用EnableSequence
和DisableSequence
关键字, 而应该把相关的使能和失能操作放到具体的 device 或 modifier 内容中; 另外,EnableSequence
和DisableSequence
使用的是 方括号 而不是大括号 { })Value
关键字定义了 verb 级别的变量值, 其有效作用域为该 verb 以及其下的 device 和 modifier. 此处中的Foobar
变量的值覆盖了 democard.conf 中ValueDefaults
处定义的同名变量的值
定义 device
device 的定义也在 Play.conf 文件中, 通过 SectionDevice
关键字指定
Play.conf 中 device 相关的内容:
SectionDevice."Headphone" {
Comment "Comment on device Headphone"
EnableSequence [
cdev "hw:demo"
cset "name='Headphone Switch' 1"
]
DisableSequence [
cdev "hw:foobar"
cset "name='Headphone Switch' 0"
]
Value {
Foobar "Value of Foobar in device Headphone"
}
}
SectionDevice
关键字用于定义 device, 此处定义了一个名为Headphone
的 deviceComment
,EnableSequence
和DisableSequence
关键字与SectionVerb
中含义 相同 (不同之处在于SectionDevice
中的EnableSequence
和DisableSequence
都 是可被实际执行的)Value
关键字定义 device 级别的变量值, 其有效作用域为该 device. 此处定义的Foobar
变量的值覆盖了SectionVerb
中同名变量的值
定义 modifier
除了使用的是 SectionModifier
关键字, modifier 的定义与 device 的类似. Value
关键字定义的变量值作用域为该 modifier, 会覆盖 SectionVerb
中同名变量的值
Play.conf 中 modifier 相关的内容:
SectionModifier."PlayTone" {
Comment "Comment on modifier PlayTone"
EnableSequence [
cdev "hw:demo"
cset "name='PlayTone Switch' 1"
]
DisableSequence [
cdev "hw:foobar"
cset "name='PlayTone Switch' 0"
]
Value {
Foobar "Value of Foobar in modifier PlayTone"
}
}
注释
UCM 配置文件中 #
符号后的内容会被认为是注释
# This is a comment
SectionUseCase."Play" {
File "Play.conf"
}
约定
为了保持 Tina 中不同方案下配置文件的统一, 有如下的约定:
通用命名约定
除了 card 和某些特定的 Value 的名字外, 其余自定义的名字均采用 驼峰命名法, 如
LineIn
, PlayTone
, MicToHeadphone
, ... 名字中不包含空格, 下划线, 短横线等字
符
对于某些原本是全字母大写或部分字母大写的单词, 更倾向于将它们视作一个单词而仅
大写其首字母, 如: 使用 Dmic
而非 DMIC
, I2s
而非 I2S
, AdcChannels
而非
ADCChannels
card
- 全志 SoC 内置 codec 的名字统一使用
audiocodec
- 内置 codec 以外的其他 card 的名字按照实际情况而定, 除了不能包含空格外并无额外 限制
- 在
ValueDefaults
中需要定义变量Card
指定对应的 ALSA 虚拟设备声卡名字 (不能使用数字编号, 而应该把声卡的名字写出来, 如hw:audiocodec
,hw:sndcodec
)
verb
- verb 的命名遵循通用命名约定
- 如无特殊情况, 推荐 verb 统一使用
Play
,Record
和Call
三个名字.Play
包含用于播放的设备, 如Headphone
,Speaker
等;Record
包含用于录 制的设备, 如Mic
,LineIn
等;Call
则包含兼有播放和录制功能的设备, 如Bluetooth
,Headset
等 - 不推荐 在
SectionVerb
中定义EnableSequence
和DisableSequence
, 除非 只存在使能操作而不存在失能操作
device
- device 的命名遵循通用命名约定
- 在一般情况下, 推荐使用以下的名字, 若无合适的再自行定义
- Headphone
- Headset
- Speaker
- Mic
- LineIn
- LineOut
- PhoneIn
- PhoneOut
- Bluetooth
- Spdif
- Hdmi
- 若某一个 verb 中存在多个同类型的设备, 可在 device 名字后面加编号区分 (编号不
一定需要从 1 开始, 可以根据实际情况而定), 然后在
SectionVerb
的Value
中定义xxxNumber
和xxxNames
分别说明这种同类型设备的数量和名字, 名字之间用空格隔开 (如实际存在两个麦克风 MIC2 和 MIC3, 可以定义Mic2
和Mic3
两个 device, 并在SectionVerb
的Value
中定义MicNumber "2"
和MicNames "Mic2 Mic3"
) - 有时候会有多个设备联合使用的情况, 对此没有硬性的命名约定, 对于某些情况推荐以下 命名:
- 普通情况下多个设备联合使用, 使用 序数词+设备 的命名, 如
TwoMics
,FourMics
- 特定的设备需要对应特定的操作, 如 "MIC1 录制左声道, MIC2 录制右声道" 可命名为
Mic1LeftMic2Right
- 特定的设备数量与特定的通道数, 如两个麦克风可能分别用于录制两声道或四声道的不 同场景下, 可命名为
TwoMicsTwoChs
和TwoMicsFourChs
以区分 (Chs
为Channels
的缩写)
- 若定义了多个设备联合使用的 device, 需要有它们各自本身的 device 定义. 例如定义
了
TwoMics
对应 MIC1 和 MIC2 的联合使用, 则需要分别定义Mic1
和Mic2
来提供 调节音量等操作的接口 (因为麦克风统一使用CaptureVolume
变量作为音量控制的接口, 在当中不能同时定义多个设备的音量)
modifier
除了需要遵循通用命名约定外, modifier 的命名由配置文件的编写者自行决定
Value
推荐优先使用以下变量的命名, 若无合适的再自行定义 (自定义的名字应遵循通用命名约定)
Card
: 需要在 card 的ValueDefaults
中定义, 用于指定该 card 对应的 ALSA 虚 拟声卡设备的名字 (不能使用数字编号, 而应该把具体的名字写出来), 如:
ValueDefaults {
Card "hw:audiocodec"
}
PlaybackPCM
,CapturePCM
: 在 verb, device 或 modifier 中用于指定具体的 PCM 设备, 如PlaybackPCM "hw:audiocodec,0"
(这两个变量的名字沿用了 ALSA 官方的名字, 因此没遵循本文档的通用命名约定)PlaybackVolume
,CaptureVolume
: 指定音量控件的名字及其默认值, 格式为: "控 件ID 默认值", 如PlaybackVolume "name='Headphone Volume' 40"
PlaybackVolumeMin
,PlaybackVolumeMax
,CaptureVolumeMin
,CaptureVolumeMax
: 指定音量数值的有效范围, 需要在定义了PlaybackVolume
或CaptureVolume
的同时 定义, 如:
Value {
PlaybackVolume "name='Headphone Volume' 40"
PlaybackVolumeMin "0"
PlaybackVolumeMax "63"
}
PlaybackRate
,CaptureRate
: 表明支持的特定采样率, 如PlaybackRate "16000 32000"
表明仅支持 16000Hz 和 32000Hz 的采样率播放PlaybackChannels
,CaptureChannels
: 表明支持的特定通道数, 如PlaybackChannels "2 4"
表明仅支持两通道或四通道播放PlaybackFormat
,CaptureFormat
: 表明支持的特定格式, 语法与 aplay 和 arecord 中 "-f" 选项的参数相同, 如PlaybackFormat "S16_LE S32_LE"
表明仅支持 S16_LE 和 S32_LE 的格式播放
其他
顺序
(与 interfaces.md 中的 "默认使用案例 API" 相关联)
verb, device 和 modifier 的顺序是根据配置文件中的先后位置决定的, 因此在编写配置文 件时, 尽量将想要默认使用的项放在前面, 保证 alsa-ucm-aw 中的程序能优先选中它们
card 则是按照文件名的先后顺序排列, 除了修改名字外, 无法直接规定其顺序