模擬與數(shù)字的區(qū)別及Linux ALSA驅(qū)動(dòng)調(diào)試實(shí)戰(zhàn))
最近幫客戶(hù)調(diào)試一塊嵌入式開(kāi)發(fā)板的音頻通路連著幾天都在和 Type-C 耳機(jī)打交道。插上耳機(jī)不出聲、插上耳機(jī)識(shí)別不到、兩個(gè)耳朵音量不一樣、麥克風(fēng)完全沒(méi)反應(yīng)……這些問(wèn)題來(lái)回折騰了幾天之后我強(qiáng)烈感覺(jué)到一個(gè)問(wèn)題很多人根本分不清自己手里的 Type-C 耳機(jī)到底是模擬的還是數(shù)字的。在以前 3.5mm 耳機(jī)時(shí)代這個(gè)問(wèn)題不存在因?yàn)樗卸鷻C(jī)都是模擬接口。但 Type-C 時(shí)代不一樣它既能像以前一樣傳輸模擬音頻信號(hào)也能通過(guò) USB 協(xié)議傳輸數(shù)字音頻信號(hào)。這兩種完全不同的通信方式?jīng)Q定了同一個(gè)耳機(jī)插在不同設(shè)備上有時(shí)能用有時(shí)不能用的神秘現(xiàn)象。今天我就用實(shí)際調(diào)試過(guò)程中積累的經(jīng)驗(yàn)把模擬耳機(jī)和數(shù)字耳機(jī)的區(qū)別、判斷方法、以及 Linux 下 ALSA 驅(qū)動(dòng)的實(shí)戰(zhàn)調(diào)試一次說(shuō)清楚。這篇內(nèi)容適合嵌入式開(kāi)發(fā)、Linux 音頻調(diào)試的朋友也適合普通用戶(hù)——至少看完之后你買(mǎi)東西的時(shí)候不會(huì)買(mǎi)錯(cuò)。1. 兩種Type-C耳機(jī)到底差在哪里想要真正區(qū)分模擬和數(shù)字耳機(jī)首先要搞清楚它們各自的工作原理。我盡量用大白話講只要你關(guān)注過(guò)手機(jī)音頻就一定聽(tīng)得懂。1.1 模擬耳機(jī)只是換了個(gè)插頭的傳統(tǒng)耳機(jī)模擬耳機(jī)的本質(zhì)和 3.5mm 耳機(jī)沒(méi)有區(qū)別。耳機(jī)內(nèi)部只有揚(yáng)聲器單元和麥克風(fēng)沒(méi)有任何數(shù)字處理芯片。聲音信號(hào)從主機(jī)出來(lái)時(shí)就已經(jīng)是模擬信號(hào)通過(guò)線纜里的金屬導(dǎo)線直接驅(qū)動(dòng)耳機(jī)單元發(fā)聲。在 Type-C 接口時(shí)代這種耳機(jī)并不是通過(guò) Type-C 定義里的數(shù)據(jù)線傳輸聲音的而是利用了 Type-C 標(biāo)準(zhǔn)里的“音頻適配器模式”。簡(jiǎn)單說(shuō)Type-C 接口幾十根引腳里有一組引腳可以復(fù)用為模擬音頻通道——左右聲道走 D/D- 引腳麥克風(fēng)和模擬地走 SBU 引腳。這樣耳機(jī)就可以像老式 3.5mm 耳機(jī)一樣工作只是換了個(gè)物理插頭而已。關(guān)鍵點(diǎn)在于模擬耳機(jī)本身不處理任何信號(hào)所以它必須依賴(lài)播放設(shè)備內(nèi)部有一整套完整的模擬音頻電路包括 DAC數(shù)字轉(zhuǎn)模擬芯片和功放。換句話說(shuō)手機(jī)、電腦或開(kāi)發(fā)板的 SoC 里必須有對(duì)應(yīng)的硬件通路能把芯片內(nèi)部 Codec編解碼器輸出的模擬信號(hào)接到 Type-C 的那個(gè)復(fù)用引腳上去。這也就解釋了為什么同一個(gè)模擬 Type-C 耳機(jī)在這臺(tái)設(shè)備上能出聲插到另一臺(tái)設(shè)備上就沒(méi)聲。不是耳機(jī)壞了是那臺(tái)設(shè)備硬件上壓根就沒(méi)有做模擬直通電路。它只支持?jǐn)?shù)字 USB 音頻。1.2 數(shù)字耳機(jī)耳機(jī)里藏了一張聲卡數(shù)字耳機(jī)就完全不同了。它內(nèi)部集成了一顆 DAC 芯片早期常見(jiàn)的有 Realtek 的 ALC4042、Conexant 的 CX31993現(xiàn)在國(guó)產(chǎn)方案也很多耳機(jī)線里走的是真正的 USB 數(shù)字信號(hào)。當(dāng)你把數(shù)字耳機(jī)插到主機(jī)上主機(jī)會(huì)把耳機(jī)識(shí)別為一個(gè) USB 音頻設(shè)備——就像你插了一個(gè) USB 聲卡。播放的音頻文件經(jīng)過(guò)主機(jī)端編碼成數(shù)字信號(hào)通過(guò) D/D- 兩條數(shù)據(jù)線傳到耳機(jī)里的 DAC由這顆 DAC 完成數(shù)字到模擬的轉(zhuǎn)換再驅(qū)動(dòng)耳機(jī)單元發(fā)聲。數(shù)字耳機(jī)內(nèi)部其實(shí)包含兩個(gè)功能模塊USB Audio ClassUAC設(shè)備模塊和 HID 控制模塊。UAC 負(fù)責(zé)數(shù)字音頻流的傳輸HID 模塊負(fù)責(zé)耳機(jī)的音量和播放暫停按鍵控制。這也是為什么你在電腦上插一個(gè)帶線控的數(shù)字耳機(jī)系統(tǒng)會(huì)同時(shí)識(shí)別出兩個(gè)設(shè)備接口一個(gè) Audio 接口一個(gè) HID 接口。因?yàn)閿?shù)字耳機(jī)自帶 DAC所以它對(duì)播放設(shè)備幾乎沒(méi)有要求。只要設(shè)備能標(biāo)準(zhǔn)地枚舉 USB 設(shè)備、能跑 USB Audio Class 協(xié)議就能用它。兼容性問(wèn)題通常出在 UAC 版本1.0 和 2.0以及供電能力上而不是出在耳機(jī)模擬電路那部分。1.3 為什么會(huì)有兩種方案并存這個(gè)問(wèn)題背后其實(shí)是產(chǎn)品設(shè)計(jì)思路的差異。最早 3.5mm 耳機(jī)孔被砍掉的時(shí)候手機(jī)廠商必須給用戶(hù)一個(gè)過(guò)渡方案——用戶(hù)手里還有一堆老耳機(jī)怎么才能插到新手機(jī)上一種思路是隨機(jī)附贈(zèng)一個(gè) Type-C 轉(zhuǎn) 3.5mm 的轉(zhuǎn)接頭這個(gè)轉(zhuǎn)接頭里面其實(shí)就是模擬直通電路把 Type-C 的模擬音頻引腳轉(zhuǎn)接出來(lái)。這個(gè)方案成本低、電路簡(jiǎn)單只需要手機(jī)內(nèi)部做模擬直通支持但音質(zhì)上限完全取決于手機(jī)內(nèi)置 Codec。另一種思路是直接走 USB 數(shù)字音頻協(xié)議耳機(jī)廠商自己在耳機(jī)里做 DAC。這個(gè)方案的好處是耳機(jī)可以獨(dú)立控制音質(zhì)降噪也可以做到耳機(jī)里和播放設(shè)備的音頻電路完全解耦。缺點(diǎn)是耳機(jī)成本更高功耗更高而且對(duì) USB 供電質(zhì)量比較敏感。所以今天市面上的 Type-C 耳機(jī)魚(yú)龍混雜兩種方案都有而且外觀幾乎一模一樣。下面說(shuō)說(shuō)怎么快速判斷。2. 三個(gè)方法快速判斷你的耳機(jī)是模擬還是數(shù)字區(qū)分方法其實(shí)沒(méi)有想象中那么難尤其是當(dāng)你手邊有電腦或者手機(jī)的時(shí)候幾條命令或者幾個(gè)界面就能看出來(lái)。2.1 Windows 下最直觀的判斷這個(gè)方法我最推薦因?yàn)殚T(mén)檻最低而且準(zhǔn)確率極高。把耳機(jī)插到電腦的 Type-C 口上然后右鍵點(diǎn)擊任務(wù)欄右下角的喇叭圖標(biāo)打開(kāi)“聲音設(shè)置”看“輸出設(shè)備”這一欄。如果插上后出現(xiàn)一個(gè)新的設(shè)備選項(xiàng)名字通常叫“USB Audio Device”“Realtek USB Audio”或者廠商名字聲音輸出可以切換到它——那就是數(shù)字耳機(jī)。如果插上后并沒(méi)有出現(xiàn)任何新設(shè)備聲音依然走原來(lái)的“揚(yáng)聲器/耳機(jī)”輸出通路——那基本可以確定是模擬耳機(jī)它只是在復(fù)用主板聲卡的模擬通道。這個(gè)方法在 Windows 10/11 上很好用。需要注意一點(diǎn)有些筆記本的 Type-C 口不是全功能的可能不支持音頻附件模式導(dǎo)致模擬耳機(jī)插上去完全沒(méi)反應(yīng)但數(shù)字耳機(jī)只要 Type-C 口支持 USB 數(shù)據(jù)傳輸就能正常工作。2.2 Android 手機(jī)上的判斷手機(jī)上的判斷稍微隱蔽一點(diǎn)但同樣有規(guī)律可循。把耳機(jī)插到手機(jī) Type-C 口下拉狀態(tài)欄看音頻輸出圖標(biāo)。如果狀態(tài)欄顯示的是一個(gè)耳機(jī)圖標(biāo)和插 3.5mm 耳機(jī)一樣設(shè)備走的是模擬直通是模擬耳機(jī)。如果狀態(tài)欄顯示的是“USB 音頻”“USB 耳機(jī)”之類(lèi)的字樣或者系統(tǒng)彈窗提示“已連接 USB 音頻設(shè)備”那就是數(shù)字耳機(jī)。用開(kāi)發(fā)者的角度還可以打開(kāi)“開(kāi)發(fā)者選項(xiàng)”找到“USB 音頻”相關(guān)設(shè)置。不同手機(jī)選項(xiàng)位置和名稱(chēng)有差異但很多 Android 機(jī)型在開(kāi)發(fā)者選項(xiàng)里都有一個(gè)“默認(rèn) USB 配置”如果里面有選擇“音頻源”或“DAC”之類(lèi)的東西就說(shuō)明系統(tǒng)在把數(shù)字音頻信號(hào)從 USB 口送出去了。另外Android 里音頻輸出道路徑可以通過(guò)dumpsys audio命令查看會(huì)輸出類(lèi)似usb_device或headset的關(guān)鍵字。這個(gè)對(duì)開(kāi)發(fā)者來(lái)說(shuō)非常直觀。2.3 Linux 下用 ALSA 的思路判斷如果你是開(kāi)發(fā)和調(diào)試人員在 Linux 下判斷就非常爽快了因?yàn)檫@是系統(tǒng)層面的信息。核心思路是數(shù)字耳機(jī)是一個(gè) USB 聲卡設(shè)備插上后 ALSA 會(huì)多出一張 sound card模擬耳機(jī)不產(chǎn)生新聲卡聲音走原來(lái)的板載聲卡。插上耳機(jī)后執(zhí)行cat /proc/asound/cards如果原本只有一個(gè)聲卡插上后出現(xiàn)了USB-Audio字樣的新聲卡那它就是數(shù)字耳機(jī)。我前面調(diào)試時(shí)插入某款國(guó)產(chǎn)數(shù)字耳機(jī)后輸出是這樣的0 [HDAIntel ]: HDA-Intel - HDA Intel PCH HDA Intel PCH at 0xf7230000 irq 34 1 [USB ]: USB-Audio - USB Audio USB Audio at usb-0000:00:14.0-3, high speedcard 1 就是 USB Audio說(shuō)明這個(gè)耳機(jī)是數(shù)字的。如果插入后 cards 文件沒(méi)有任何變化耳機(jī)沒(méi)有形成獨(dú)立聲卡那么它走的就是設(shè)備內(nèi)部 Codec是模擬耳機(jī)。此時(shí)需要在原來(lái)的聲卡 mixer 里找Headphone、Headset之類(lèi)的控制項(xiàng)來(lái)識(shí)別。2.4 一張速查表搞定如果你手頭有設(shè)備可以實(shí)測(cè)直接用下面的表判斷是最快的判斷入口模擬耳機(jī)表現(xiàn)數(shù)字耳機(jī)表現(xiàn)Windows 聲音設(shè)置無(wú)新輸出設(shè)備新增 USB Audio 類(lèi)設(shè)備Android 狀態(tài)欄普通耳機(jī)圖標(biāo)USB 音頻設(shè)備提示Linux /proc/asound/cards聲卡列表無(wú)變化多出 USB-Audio 聲卡Linux 執(zhí)行 lsusb無(wú)新設(shè)備出現(xiàn) USB Audio 設(shè)備耳機(jī)內(nèi)部拆解只有揚(yáng)聲器/麥克風(fēng)有 DAC 芯片、晶振等耳機(jī)功耗較低插上基本無(wú)發(fā)熱可能略微溫升順便說(shuō)一句如果你想從硬件層面直接坐實(shí)拆開(kāi)耳機(jī)線控或者插頭附近的封裝看里面有沒(méi)有一顆 IC。數(shù)字耳機(jī)幾乎一定有主控或 DAC 芯片模擬耳機(jī)通??湛杖缫?。這個(gè)方法雖然粗暴但絕對(duì)準(zhǔn)確。3. ALSA驅(qū)動(dòng)實(shí)戰(zhàn)讓Linux正確認(rèn)識(shí)Type-C耳機(jī)說(shuō)完了怎么判斷接下來(lái)是重頭戲——在 Linux 環(huán)境下通過(guò) ALSA 音頻架構(gòu)完成 Type-C 耳機(jī)的識(shí)別、配置和調(diào)試。這套操作在嵌入式 Linux 開(kāi)發(fā)板上非常實(shí)用桌面 Linux 也有參考價(jià)值。3.1 先搞懂ALSA幾個(gè)關(guān)鍵概念A(yù)LSA 全稱(chēng)是 Advanced Linux Sound Architecture是 Linux 內(nèi)核的音頻子系統(tǒng)。做音頻調(diào)試之前你需要知道幾個(gè)概念Card聲卡每一個(gè)音頻設(shè)備在 ALSA 中都是一個(gè) card數(shù)字耳機(jī)插入后通常會(huì)成為新的 USB-Audio card。Device設(shè)備一個(gè) card 下可以有一個(gè)或多個(gè) PCM 設(shè)備比如播放 device 0、錄音 device 1 等。數(shù)字耳機(jī)一般同時(shí)暴露 playback 和 capture 設(shè)備節(jié)點(diǎn)。PCMPulse Code Modulation數(shù)字音頻數(shù)據(jù)的格式播放和錄音都是圍繞 PCM 流做的。Mixer混音器控制音量的旋鈕和開(kāi)關(guān)在 ALSA 里用 amixer 命令操作。查看當(dāng)前聲卡列表最常用的命令就是cat /proc/asound/cards前面已經(jīng)演示過(guò)。然后通過(guò)aplay -l列出所有播放設(shè)備節(jié)點(diǎn)$ aplay -l **** List of PLAYBACK Hardware Devices **** card 0: HDAIntel [HDA Intel PCH], device 0: ALC892 Analog [ALC892 Analog] Subdevices: 1/1 Subdevice #0: subdevice #0 card 1: USB [USB Audio], device 0: USB Audio [USB Audio] Subdevices: 1/1 Subdevice #0: subdevice #0如果你插入的是模擬耳機(jī)aplay -l里不會(huì)多出 card 1聲音是直接通過(guò) card 0 的某組模擬輸出走的。這正是判斷兩種耳機(jī)在 ALSA 層面最關(guān)鍵的區(qū)別。3.2 實(shí)戰(zhàn)一確認(rèn)系統(tǒng)識(shí)別到數(shù)字耳機(jī)先別急著配置第一步是確認(rèn)系統(tǒng)到底有沒(méi)有把耳機(jī)識(shí)別成 USB 設(shè)備。插入數(shù)字耳機(jī)后執(zhí)行dmesg看內(nèi)核日志$ dmesg | tail -n 20 [ 1234.567890] usb 3-1: new high-speed USB device number 4 using xhci_hcd [ 1234.612345] usb 3-1: New USB device found, idVendor1116, idProductf152, bcdDevice 1.00 [ 1234.612350] usb 3-1: New USB device strings: Mfr3, Product4, SerialNumber0 [ 1234.612355] usb 3-1: Product: USB TYPE-C AUDIO [ 1234.612358] usb 3-1: Manufacturer: C-Media Electronics Inc. [ 1234.612362] usb 3-1: SerialNumber: 00000000看到new USB device說(shuō)明 USB 枚舉成功了。接著看驅(qū)動(dòng)是否綁定$ lsusb | grep -i audio Bus 003 Device 004: ID 1116:f152 C-Media Electronics Inc.再檢查 ALSA 系統(tǒng)是否生成了新聲卡$ cat /proc/asound/cards 1 [USB ]: USB-Audio - USB Audio USB TYPE-C AUDIO at usb-0000:00:14.0-3, high speed如果 cards 文件里出現(xiàn) USB-Audio說(shuō)明內(nèi)核snd-usb-audio驅(qū)動(dòng)已經(jīng)正常綁定了這個(gè)數(shù)字耳機(jī)。此時(shí)無(wú)論你先烤什么配置聲音已經(jīng)可以從 ALSA 層輸出。反過(guò)來(lái)如果 dmesg 里沒(méi)有 USB 枚舉、lsusb 里看不到設(shè)備、聲卡列表也沒(méi)有新卡大概率是 Type-C 口物理鏈路的問(wèn)題——線太差、接口接觸不良、USB 供電不足或者內(nèi)核編譯時(shí)把 USB Audio 模塊給砍了。排查順序是先確認(rèn)硬件再查內(nèi)核配置。3.3 實(shí)戰(zhàn)二用speaker-test測(cè)試、aplay播放具體文件識(shí)別到聲卡之后先做一個(gè)最基礎(chǔ)的播放測(cè)試。用 ALSA 自帶的speaker-test最方便speaker-test -D plughw:1,0 -c 2 -t sine -f 440 -l 1這里的plughw:1,0含義是card 1device 0。plughw類(lèi)型會(huì)自動(dòng)做格式轉(zhuǎn)換比較省事。參數(shù)-c 2是雙聲道-t sine用正弦波-f 440是 440Hz 的 A 音-l 1只播一次。如果你聽(tīng)到左右聲道各響一聲說(shuō)明 ALSA 通路基本是通的。如果你想播放一個(gè)實(shí)際的音頻文件用aplayaplay -D plughw:1,0 /usr/share/sounds/alsa/Front_Center.wav如果系統(tǒng)里沒(méi)有這個(gè)測(cè)試文件可以用speaker-test代替。注意用plughw只是臨時(shí)指定設(shè)備。如果你希望默認(rèn)設(shè)備就是這張 USB 卡可以用aplay -D default:1測(cè)試但default:1語(yǔ)法需要先有定義后面講asound.conf時(shí)再說(shuō)。提示如果speaker-test播放時(shí)提示找不到設(shè)備或者被占用確認(rèn)有沒(méi)有 PulseAudio/PipeWire 在搶占聲卡。很多桌面系統(tǒng)默認(rèn)是這些上層服務(wù)占用 hw 設(shè)備直接指定plughw會(huì)失敗或沒(méi)有聲音。先用sudo fuser -v /dev/snd/*查看占用情況必要時(shí)停掉服務(wù)再測(cè)。3.4 實(shí)戰(zhàn)三切換默認(rèn)輸出、解決插入不切換問(wèn)題調(diào)通了 ALSA 層下面就是要讓整個(gè)系統(tǒng)默認(rèn)使用這張卡。這里有一個(gè)很容易踩的坑桌面的應(yīng)用程序Chrome、音樂(lè)播放器一般不會(huì)直接訪問(wèn) ALSA hw 節(jié)點(diǎn)而是走 PulseAudio 或 PipeWire再由它們通過(guò) ALSA 訪問(wèn)硬件。所以很多時(shí)候你用 aplay 能出聲應(yīng)用程序卻還是沒(méi)動(dòng)靜。最簡(jiǎn)單的處理辦法是直接修改 ALSA 的默認(rèn)設(shè)備配置。在/etc/asound.conf全局生效或~/.asoundrc當(dāng)前用戶(hù)生效里寫(xiě)入pcm.!default { type plug slave.pcm hw:1,0 } ctl.!default { type hw card 1 }這段配置把默認(rèn) PCM 輸出和混音器控制都指到了 card 1。配置好后用aplay -D default front.wav測(cè)試。如果你是開(kāi)發(fā)板的調(diào)試場(chǎng)景沒(méi)有桌面音頻服務(wù)這個(gè)配置就夠了。但如果系統(tǒng)里有 PulseAudio還要保證 PulseAudio 本身選對(duì)了聲卡。用命令pactl list short sinks查看當(dāng)前默認(rèn) sink如果指向的是 card 0 而不是 card 1就用pactl set-default-sink sink-name切換到目標(biāo)聲卡。PipeWire 下的操作類(lèi)似用pw-cli或wpctl status查看和設(shè)置默認(rèn)設(shè)備wpctl status wpctl set-default audio-sink-id關(guān)于“插上耳機(jī)不能自動(dòng)切換”的問(wèn)題核心邏輯其實(shí)是ALSA 不存在自動(dòng)切換自動(dòng)切換是上層音頻管理系統(tǒng)做的策略。嵌入式上如果自己做開(kāi)關(guān)機(jī)檢測(cè)通常通過(guò)監(jiān)聽(tīng)耳機(jī)插入事件比如 GPIO 中斷或 Type-C 狀態(tài)去切換路由這已經(jīng)超出基礎(chǔ) ALSA 范疇了。桌面 Linux 上則要看 PulseAudio/PipeWire 的設(shè)備切換策略和耳機(jī)模擬/數(shù)字類(lèi)型沒(méi)有直接關(guān)系。3.5 實(shí)戰(zhàn)四音量、Mixer控制與排查無(wú)聲問(wèn)題聲音通了、默認(rèn)設(shè)備也對(duì)了但有時(shí)候音量是 0或者 mixer 里面某個(gè)通路被靜音了照樣聽(tīng)不到聲音。這時(shí)要用amixer查和調(diào)。查看 card 1 的所有控制項(xiàng)amixer -c 1 scontrols數(shù)字耳機(jī)通??刂祈?xiàng)比較少常見(jiàn)的是Simple mixer control PCM,0注意這就是 USB Audio 設(shè)備的主音量或叫 DAC 增益。如果它是 0音量再大也沒(méi)意義。調(diào)整它amixer -c 1 set PCM 80%再查看具體控制項(xiàng)的狀態(tài)amixer -c 1 contents你可以直接看到當(dāng)前值、限制范圍比如Mute開(kāi)關(guān)、Volume的 percent。掌握了這些基礎(chǔ)之后排查數(shù)字耳機(jī)無(wú)聲就快多了。排查模擬耳機(jī)的無(wú)聲問(wèn)題則是另一套思路。模擬耳機(jī)走主聲卡比如 card 0你要檢查的是Headphone或Headset控制項(xiàng)amixer -c 0 scontrols | grep -i head amixer -c 0 set Headphone 80% amixer -c 0 set Headphone unmute很多時(shí)候模擬耳機(jī)插上沒(méi)聲音不是硬件壞了而是這個(gè)控制項(xiàng)被 mute 或音量為 0。這在嵌入式開(kāi)發(fā)板的出廠系統(tǒng)里極其常見(jiàn)因?yàn)楹芏喟蹇J(rèn) codec 狀態(tài)是全部靜音的。注意開(kāi)發(fā)板上的模擬直通并不是所有平臺(tái)都默認(rèn)開(kāi)啟。你需要在 SoC 的數(shù)據(jù)手冊(cè)或者設(shè)備樹(shù)里確認(rèn)Type-C 的 D/D- 引腳是否被配置為 Audio Adapter Accessory Mode有沒(méi)有把 Codec 的輸出路由到這個(gè)引腳上。設(shè)備樹(shù)里相關(guān)的屬性、pinctrl 配置錯(cuò)了模擬耳機(jī)插上去不可能出聲音。4. 常見(jiàn)問(wèn)題與排查技巧實(shí)錄下面整理幾個(gè)我實(shí)際調(diào)試中反復(fù)遇到的問(wèn)題每一個(gè)都是血淚教訓(xùn)。4.1 插上數(shù)字耳機(jī)完全沒(méi)聲音系統(tǒng)毫無(wú)反應(yīng)這是比較詭異的一種情況耳機(jī)插到 Type-C 口上dmesg 沒(méi)有輸出lsusb 也找不到設(shè)備好像根本沒(méi)插一樣。排查步驟換一根全功能 Type-C 數(shù)據(jù)線。有些線只支持充電或 USB 2.0 數(shù)據(jù)接觸不良時(shí)音頻設(shè)備最容易出問(wèn)題。確認(rèn) Type-C 口支持 Host 模式。部分設(shè)備比如某些手機(jī)默認(rèn)是 Device 模式需要外部識(shí)別到 USB Host 才能反向供電耳機(jī)插上去無(wú)法枚舉。開(kāi)發(fā)板/電腦是否給到了足夠的 VBUS 電流。數(shù)字耳機(jī)內(nèi)部 DAC 需要從 VBUS 取電如果 USB 口供電弱良率差的耳機(jī)就是無(wú)法枚舉。檢查內(nèi)核有沒(méi)有編入snd-usb-audio。執(zhí)行l(wèi)smod | grep snd_usb_audio如果沒(méi)有手動(dòng)modprobe snd-usb-audio或者重編內(nèi)核。排到最后如果硬件鏈路沒(méi)問(wèn)題但設(shè)備還是不出來(lái)可以拿一個(gè)標(biāo)準(zhǔn) USB 聲卡插到同一個(gè) USB Host 口測(cè)試排除是耳機(jī)本身兼容性問(wèn)題。4.2 模擬耳機(jī)在其他設(shè)備有聲音插這臺(tái)開(kāi)發(fā)板沒(méi)聲音這種情況下九成不是耳機(jī)的問(wèn)題而是你的開(kāi)發(fā)板或電腦壓根就沒(méi)有實(shí)現(xiàn)模擬直通電路。模擬耳機(jī)依賴(lài)設(shè)備端的音頻適配器模式。我需要強(qiáng)調(diào)一個(gè)很多人忽略的事實(shí)Type-C 規(guī)范定義了音頻適配器模式但并不是所有設(shè)備都實(shí)現(xiàn)了這個(gè)模式。尤其是某些開(kāi)發(fā)板、迷你主機(jī)和臺(tái)式機(jī)Type-C 口只做了 DisplayPort 和 USB 數(shù)據(jù)功能完全沒(méi)有把 Codec 的聲音信號(hào)接到 Type-C 的模擬引腳上。判斷起來(lái)也很簡(jiǎn)單你把模擬耳機(jī)插上去看cat /proc/asound/cards聲卡列表沒(méi)有變化再看板載聲卡的 mixer 是否多出Headphone控制選項(xiàng)。如果連 Headphone 控制項(xiàng)都沒(méi)有說(shuō)明軟件層沒(méi)有暴露這個(gè)通路這時(shí)候從驅(qū)動(dòng)怎么折騰都沒(méi)用只能換數(shù)字耳機(jī)或者另配一個(gè) TYPE-C 轉(zhuǎn) 3.5 的 DAC 轉(zhuǎn)接線。4.3 數(shù)字耳機(jī)插上后底噪很大、播放中有爆音數(shù)字耳機(jī)底噪的來(lái)源通常是供電不干凈或數(shù)字和模擬地線處理不好。首先試試換個(gè) USB 口特別是不要和無(wú)線網(wǎng)卡、硬盤(pán)這種高功耗設(shè)備挨在一起供電。臺(tái)式機(jī)建議插到主板后置的 USB 口而不是前置面板。其次和 UAC 版本有關(guān)系。某些數(shù)字耳機(jī)支持 UAC 2.0 但也兼容 UAC 1.0Linux 下可以嘗試用 quirk 強(qiáng)制讓設(shè)備工作在不同的 mode。比較地道的做法是直接看內(nèi)核在枚舉時(shí)輸出dmesg | grep -i uac如果顯示為UAC2而你當(dāng)前內(nèi)核版本對(duì) UAC2 支持有 bug會(huì)出現(xiàn)規(guī)律性的爆音。這時(shí)候可以看看設(shè)備有沒(méi)有切換協(xié)議的按鈕或配套 App把它切到 UAC1.0 模式再試。爆音還有一個(gè)常見(jiàn)原因就是 ALSA buffer 參數(shù)設(shè)置太小。對(duì)于某些 USB Audio 設(shè)備默認(rèn)周期值在負(fù)載高時(shí)欠載underrun表現(xiàn)為咔咔聲。你可以用speaker-test配合環(huán)境變量實(shí)驗(yàn)一下或者在應(yīng)用中調(diào)大 buffer size。比如speaker-test -D plughw:1,0 -c 2 -t wav -r 48000 -b 16384-b指定 buffer 大小臨時(shí)感受一下是否改善。如果是 PulseAudio/PipeWire 環(huán)境下還需要調(diào)整它們的配置比如 PipeWire 的api.alsa.headroom、session.suspend-timeout-seconds這些屬性不能只盯 ALSA 層。4.4 耳機(jī)上的音量鍵、播放鍵在 Linux 下不生效數(shù)字耳機(jī)的線控按鍵走的是 HID report和使用 ALSA 音量通道是兩條路。Linux 下應(yīng)用層處理按鍵事件需要 USB HID 驅(qū)動(dòng)正確上報(bào)KEY_VOLUMEUP等事件。先檢查按鍵有沒(méi)有被識(shí)別sudo evtest在 evtest 里選擇對(duì)應(yīng)的 HID 設(shè)備按下音量鍵看有沒(méi)有 key 事件上報(bào)。如果事件正常上報(bào)系統(tǒng)還不管說(shuō)明桌面環(huán)境的 keymap 沒(méi)有綁定到音頻操作如果事件完全不上報(bào)說(shuō)明耳機(jī) HID 報(bào)告描述符和主機(jī)的適配有問(wèn)題。這個(gè)問(wèn)題在 Windows/macOS 上一般不會(huì)出現(xiàn)在 Linux 上屬于兼容性老大難。實(shí)用建議是優(yōu)先檢查xmodmap、桌面環(huán)境的全局快捷鍵設(shè)置別一上來(lái)就懷疑驅(qū)動(dòng)。4.5 錄音沒(méi)聲音插上數(shù)字耳機(jī)麥克風(fēng)不能用錄音和播放是兩條通路。在 ALSA 里用arecord -l查看錄音設(shè)備節(jié)點(diǎn)$ arecord -l **** List of CAPTURE Hardware Devices **** card 1: USB [USB Audio], device 1: USB Audio [USB Audio] Subdevices: 1/1 Subdevice #0: subdevice #0很多數(shù)字耳機(jī)在播放端和錄音端是同一個(gè) USB Audio Control 接口里的不同 Alternate Setting所以你會(huì)看到 card 1 下同時(shí)有 device 0 和 device 1。不要奇怪這是正常的。測(cè)試錄音arecord -D plughw:1,1 -f cd -d 5 /tmp/test.wav aplay -D plughw:1,0 /tmp/test.wav如果錄音文件回放完全沒(méi)聲音先看 mixer 的Capture通路amixer -c 1 contents | grep -A5 -i capture有的數(shù)字耳機(jī)內(nèi)部有硬件 AGC自動(dòng)增益控制或者一個(gè)固定增益的麥克風(fēng)音量如果這個(gè)值在某些設(shè)備上被初始化成 0錄音就會(huì)靜默。順便說(shuō)一句如果是模擬耳機(jī)錄音沒(méi)聲重點(diǎn)檢查主聲卡的Mux和Mic控制項(xiàng)看輸入源有沒(méi)有從 Type-C 的 SBU 引腳切換到板載 Codec 的 MIC 通道。5. 實(shí)用小結(jié)不同場(chǎng)景下的選擇建議從音頻調(diào)試的角度來(lái)說(shuō)我個(gè)人強(qiáng)烈建議做嵌入式產(chǎn)品原型時(shí)優(yōu)先選用數(shù)字耳機(jī)做聯(lián)調(diào)。原因很簡(jiǎn)單數(shù)字耳機(jī)的鏈路更標(biāo)準(zhǔn)它通過(guò) USB Audio Class 進(jìn)行通信只要內(nèi)核 USB 子系統(tǒng)正常ALSA 識(shí)別和采集信息都很規(guī)范而模擬耳機(jī)對(duì)你的板子硬件設(shè)計(jì)有天然要求如果板子沒(méi)有預(yù)留模擬直通通路你在軟件層再怎么調(diào)也是浪費(fèi)時(shí)間。如果你的使用場(chǎng)景是普通消費(fèi)者經(jīng)常在一個(gè)手機(jī)一個(gè)電腦之間切著用耳機(jī)那我建議直接買(mǎi)數(shù)字耳機(jī)。因?yàn)?PC 的 Type-C 口幾乎都支持 USB 音頻但模擬直通的支持情況參差不齊而手機(jī)這邊支持模擬直通的機(jī)型在縮水?dāng)?shù)字耳機(jī)兼容性反而更穩(wěn)。如果是發(fā)燒友想做音質(zhì)折騰模擬耳機(jī)的好處是音質(zhì)下限由播放設(shè)備決定你可以通過(guò)換設(shè)備調(diào)整風(fēng)格數(shù)字耳機(jī)的音質(zhì)上限取決于耳機(jī)內(nèi)部那顆 DAC一旦買(mǎi)到手基本就鎖死了。這個(gè)就看你更信誰(shuí)了。我在實(shí)際調(diào)試中還有一個(gè)體會(huì)很多問(wèn)題不是“驅(qū)動(dòng)寫(xiě)不好”而是“一開(kāi)始設(shè)備類(lèi)型就搞錯(cuò)了”。你在用 ALSA 給一個(gè)模擬耳機(jī)加 USB 驅(qū)動(dòng)配置或者在給一個(gè)數(shù)字耳機(jī)調(diào) Codec 的 Headphone 通路方向錯(cuò)了越調(diào)越亂。先花兩分鐘用lsusb、cat /proc/asound/cards這幾個(gè)命令定位設(shè)備身份比什么技巧都重要。最后再分享一個(gè)小經(jīng)驗(yàn)調(diào)試的時(shí)候一定要養(yǎng)成先看dmesg的習(xí)慣。不管是數(shù)字耳機(jī)的 USB 枚舉失敗還是模擬耳機(jī)的編解碼器探測(cè)失敗內(nèi)核日志都會(huì)留下線索。很多新人一上來(lái)就改 ALSA 配置、改設(shè)備樹(shù)結(jié)果核心問(wèn)題在 USB 供電或者設(shè)備樹(shù) pinctrl 配置方向不對(duì)白折騰好幾個(gè)小時(shí)。掌握基礎(chǔ)的 ALSA 排查流程配合 Type-C 模擬/數(shù)字知識(shí)以后遇到耳機(jī)問(wèn)題就不會(huì)再一頭霧水了。