Linux音频(2):pulseaudio
pulseaudio作为声音服务器,启动时根据配置文件对ALSA子系统进行配置,并作为后台进程进行声音重定向配置。
官方文档位于《Documentation – PulseAudio》,但是没有更多概括性介绍和设计功能介绍。《PulseAudio under the hood (gavv.net)》做了很好的补充,首先可以从这篇文档开始pulseaudio的理解。
1 pulseaudio框架
PulseAudio是一个声音服务器,启动时读取配置文件对ALSA系统Control进行配置。作为一个后台进程从一个或多个音源(进程或输入设备)接受声音输入 然后重定向声音到一个或多个槽(声卡,远程网络PulseAudio服务,或其他进程)。PulseAudio的一个目的通过它是重定向所有声音流,包括那些试图访问硬件的进程。
参考《PulseAudio》、《PulseAudio - ArchWiki (archlinux.org)》、《Modules – PulseAudio (www.freedesktop.org)》、《Linux音频系统研究(ALSA Udev PulseAudio)》。
2 pulseaudio启动
/etc/init.d/S50pulseaudio在系统启动时被调用,启动pulseaudio进程:
#!/bin/sh # # Starts pulseaudio. # start() { printf "Starting pulseaudio: " umask 077 /usr/bin/pulseaudio & # --system \ # --daemonize \ # --disallow-module-loading \ # --disallow-exit \ # --exit-idle-time=-1 \ # --use-pid-file \ # --disable-shm echo "OK" } stop() { printf "Stopping pulseaudio: " PULSE_RUNTIME_PATH=/var/run/pulse /usr/bin/pulseaudio --kill echo "OK" } restart() { stop start } case "$1" in start) start ;; stop) stop ;; restart|reload) restart ;; *) echo "Usage: $0 {start|stop|restart}" exit 1 esac exit $?
3 RK3588相关pulseaudio配置
/etc/pulse/daemon.conf
/usr/share/alsa/alsa.conf
UCM定义了用户配置,pulseaudio在启动时对ALSA子系统进行配置(Use Case Configuration)。
/usr/share/alsa/ucm2/ucm.conf
Syntax 4 Define.V1 "" # non-empty string to enable ucm v1 paths Define.V2ConfD yes # empty string to disable Define.V2Module "" # non-empty string to enable module name lookups (obsolete) Define.V2Name "" # non-empty string to enable driver & card name lookups (obsolete) Include.libgen.File "/lib/generic.conf" # private alsa-lib configuration If.driver { Condition { Type String Empty "${CardNumber}" } ... False { # # The probed path when hw-card is found: # # ucm2/conf.d/[${CardDriver}|${KernelDriver}]/${CardLongName}.conf # ucm2/conf.d/[${CardDriver}|${KernelDriver}]/[${CardDriver}|${KernelDriver}].conf # ucm2/${KernelModule}/${KernelModule}.conf (obsolete) # ucm2/${CardDriver}/${CardLongName}.conf (obsolete) # ucm2/${CardDriver}/${CardDriver}.conf (obsolete) # ... If.V2Name { Condition { Type String Empty "${var:V2Name}" } False.UseCasePath {--指定用户自动以配置文件。 longname { Directory "${CardDriver}" File "${CardLongName}.conf" } driver { Directory "${CardDriver}" File "${CardDriver}.conf" } } } } }
根据ucm.conf配置,对应的配置文件为:/usr/share/alsa/ucm2/conf.d/rockchip-es8388/rockchip-es8388.conf:
Syntax 2 Comment "Rockchip ES8388 card" SectionUseCase."HiFi" { File "HiFi.conf"--读取HiFi.conf文件。 Comment "Default" } SectionVerb { Value { MinBufferLevel "512" } EnableSequence [--默认启动Control配置流程。 cset "name='Speaker Switch' off" cset "name='Headphone Switch' off" cset "name='Headset Mic Switch' off" cset "name='Main Mic Switch' off" cset "name='Speaker Switch' off" cset "name='Headphone Switch' off" cset "name='Headset Mic Switch' off" cset "name='Main Mic Switch' off" cset "name='PCM Volume' 192"--PCM默认音量。 cset "name='Output 1 Playback Volume' 27" cset "name='Output 2 Playback Volume' 27" cset "name='Capture Digital Volume' 192" cset "name='Left Channel Capture Volume' 3" cset "name='Right Channel Capture Volume' 3" cset "name='Left Mixer Left Playback Switch' on" cset "name='Right Mixer Right Playback Switch' on" cset "name='Capture Mute' off" cset "name='Right PGA Mux' DifferentialR" cset "name='Left PGA Mux' DifferentialL" ] } SectionDevice."Speaker" {--外放喇叭。 Comment "Speaker" ConflictingDevice [ "Headphones" ] Value { PlaybackPriority 100 PlaybackPCM "hw:${CardId}" } EnableSequence [ cset "name='Speaker Switch' on" ] DisableSequence [ cset "name='Speaker Switch' off" ] } SectionDevice."Mic" {--单Mic。 Comment "Internal Microphone" ConflictingDevice [ "Headset" ] Value { CapturePriority 100 CapturePCM "hw:${CardId}" } EnableSequence [ cset "name='Differential Mux' Line 2" cset "name='Main Mic Switch' on" ] DisableSequence [ cset "name='Main Mic Switch' off" ] } SectionDevice."Headphones" {--头戴式耳机。 Comment "Headphones" ConflictingDevice [ "Speaker" ] Value { PlaybackPriority 200 PlaybackPCM "hw:${CardId}" JackControl "Headphone Jack" JackHWMute "Speaker" } EnableSequence [ cset "name='Headphone Switch' on" ] DisableSequence [ cset "name='Headphone Switch' off" ] } SectionDevice."Headset" {--头戴式单麦克。 Comment "Headset Microphone" ConflictingDevice [ "Mic" ] Value { CapturePriority 200 CapturePCM "hw:${CardId}" JackControl "Headset Mic Jack" JackHWMute "Mic" } EnableSequence [ cset "name='Differential Mux' Line 1" cset "name='Headset Mic Switch' on" ] DisableSequence [ cset "name='Headset Mic Switch' off" ] }
联系方式:arnoldlu@qq.com