Ubuntu 声音问题

Ubuntu 声音问题

我给自己买了一台华为 Matebook 14s 笔记本电脑并在上面安装了 Ubuntu 22.04。这台笔记本电脑有两对扬声器。问题在于系统将第一个定义为扬声器,第二个定义为耳机。我如何让他们一起工作?也许我需要安装额外的驱动程序或类似的东西,例如英特尔的声卡。

我尝试重新启动 PulseAudio,但没有帮助。

答案1

我遇到了类似的问题,根据我找到的资料,我写了一个守护进程来解决它。您可以在我的 GitHub 存储库中获取它:https://github.com/Smoren/huawei-ubuntu-sound-fix

问题

Linux 发行版的声卡驱动程序中耳机和扬声器通道是混合的。

连接耳机时,系统认为声音应从扬声器输出。当耳机关闭时,系统会尝试通过耳机输出声音。

问题详情(发现这里

看起来有一些奇怪的硬件设计,因为从我的角度来看,有趣的小部件是:

  • 0x01 - 音频功能组
  • 0x10 - 耳机 DAC(实际上两个设备都连接在这里)
  • 0x11 - 扬声器 DAC
  • 0x16 - 耳机插孔
  • 0x17 - 内置扬声器

和:

  • 小部件 0x16 和 0x17 应该连接到不同的 DAC 0x10 和 0x11,但内部扬声器 0x17 会忽略连接选择命令并使用耳机插孔 0x16 中的值。
  • 耳机插孔 0x16 由一些奇怪的东西控制,因此应该使用音频组 0x01 的 GPIO 命令启用它。
  • 内部扬声器 0x17 与耳机插孔 0x16 耦合,因此应使用 EAPD/BTL Enable 命令明确禁用它。

解决方案

已实现一个守护进程,用于监视耳机的连接/断开并访问声卡设备,以便将播放切换到正确的位置。

华为-声卡-耳机-monitor.sh

#!/bin/bash

# ensures script can run only once at a time
pidof -o %PPID -x $0 >/dev/null && echo "Script $0 already running" && exit 1

function move_output() {
   hda-verb /dev/snd/hwC0D0 0x16 0x701 "$@" > /dev/null 2> /dev/null
}

function move_output_to_speaker() {
    move_output 0x0001
}

function move_output_to_headphones() {
    move_output 0x0000
}

function switch_to_speaker() {
    move_output_to_speaker

    # enable speaker
    hda-verb /dev/snd/hwC0D0 0x17 0x70C 0x0002 > /dev/null 2> /dev/null

    # disable headphones
    hda-verb /dev/snd/hwC0D0 0x1 0x715 0x2 > /dev/null 2> /dev/null
}

function switch_to_headphones() {
    move_output_to_headphones

    # disable speaker
    hda-verb /dev/snd/hwC0D0 0x17 0x70C 0x0000 > /dev/null 2> /dev/null

    # pin output mode
    hda-verb /dev/snd/hwC0D0 0x1 0x717 0x2 > /dev/null 2> /dev/null

    # pin enable
    hda-verb /dev/snd/hwC0D0 0x1 0x716 0x2 > /dev/null 2> /dev/null

    # clear pin value
    hda-verb /dev/snd/hwC0D0 0x1 0x715 0x0 > /dev/null 2> /dev/null

    # sets amixer sink port to headphones instead of the speaker
    pacmd set-sink-port alsa_output.pci-0000_00_1f.3-platform-skl_hda_dsp_generic.HiFi__hw_sofhdadsp__sink "[Out] Headphones"
}

function get_sound_card_index() {
    card_index=$(cat /proc/asound/cards | grep sof-hda-dsp | head -n1 | grep -Eo "^\s*[0-9]+")
    # remove leading white spaces
    card_index="${card_index#"${card_index%%[![:space:]]*}"}"
    echo $card_index
}

sleep 2 # allows audio system to initialise first

card_index=$(get_sound_card_index)
if [ $card_index == "" ]; then
    echo "sof-dha-dsp card is not found in /proc/asound/cards"
    return 1
fi

old_status=0

while true; do
    # if headphone jack isn't plugged:
    if amixer "-c${card_index}" get Headphone | grep -q "off"; then 
        status=1
        move_output_to_speaker
    # if headphone jack is plugged:
    else
        status=2
        move_output_to_headphones
    fi

    if [ ${status} -ne ${old_status} ]; then
        case "${status}" in
            1)
                message="Headphones disconnected"
                switch_to_speaker
                ;;
            2)
                message="Headphones connected"
                switch_to_headphones
                ;;
        esac

        echo "${message}"
        old_status=$status
    fi

    sleep .3
done

华为-声卡-耳机-monitor.service

[Unit]
Description=Huawei soundcard headphones monitor

[Service]
ExecStart=/usr/local/bin/huawei-soundcard-headphones-monitor.sh
Restart=always
User=root

[Install]
WantedBy=multi-user.target

相关内容