Technical Comparison Report

AiLens Ultra HFP / Audio 與 Master 原版差異分析

📅 📄 12 個章節 離線單檔 HTML

結論摘要#

Vendor 原版已具備 Classic Bluetooth HFP,包含 HFP profile、SCO 連線、mSBC 編碼、麥克風上行、喇叭下行、通話狀態同步與通話音量控制。我們這次並不是從零實作 HFP。

實際難點是連線與執行架構已經改變:

  • Vendor 原流程:由原生 App 建立 Classic Bluetooth,依產品原本預期的事件順序連接 HFP。
  • 目前 POC:macOS 先以 BLE 控制眼鏡,透過 CTKD 建立 Classic Bluetooth,再啟動 HFP,同時還要執行 STN 的 WiFi Camera / Live pipeline。

這個新組合暴露了原流程不會遇到或不容易觸發的問題,包括:HFP profile 啟動依賴非必要的 SPP 事件、BLE 與 Classic Bluetooth 生命週期互相影響、HFP 與 Live 爭用同一套麥克風資源,以及 G07S5 的 HFP 麥克風路徑進入不相容的 vendor ENC / noise-suppression 初始化流程。

因此,「HFP firmware code 被註解掉」這個說法不精確。HFP 主體一直存在且有編入;被 #if 0 關閉的是其中一條 BLE encryption 到 CTKD / Classic Bluetooth 的交接路徑,不是 HFP codec、SCO、麥克風或喇叭本身。

比較範圍#

元件 比較基準 目前分支 目前 revision 差異規模
WuQi master (3ee9f93) pure_ble 2af4b91 33 files,+1753 / -147
STN master (d17d58c) web-socket 2070f0b 63 files,+6690 / -314

本文件將兩個 repository 的 master 視為匯入的 vendor source baseline。這不等同於已證明每一個 vendor release binary 都與該 revision byte-for-byte 相同;正式產品 release 仍應以 vendor 的確切 tag、source package 與 map file 再做一次核對。

WuQi 與 STN 的責任分工#

連線架構
macOS
  |-- BLE GATT command / control ---------------------+
  |                                                   |
  |      CTKD -> Classic ACL -> HFP -> SCO            |
  |                            |                      |
  |                            +-> speaker / mic      |
  |                                                   |
  +-- WiFi camera consumer ---------------------------+
                                                      |
WuQi:Bluetooth profiles、SCO、mSBC、audio DSP、mic / speaker
STN :UI、WiFi / Live service、camera / media lifecycle、command routing

HFP 的實際音訊資料主要由 WuQi 處理。STN 有通話、麥克風、音樂與音量的命令及狀態同步,但不負責 HFP SCO codec 或麥克風 DSP pipeline。

Vendor 原版已具備的功能#

WuQi 原版已編入 HFP#

wq-adk/components/bt_service/SConscript:55-76 的標準 Bluetooth service module 清單中已包含:

  • hfp
  • bt_audio
  • a2dp
  • avrcp
  • spp

G07S5 DVT 設定也已啟用 CTKD 與 voice processing 相關功能:

  • wq-adk/examples/g07s5/config/7036A/defconfig_g07s5_dvt.pro:34CONFIG_CTKD_DERIVATION_BREDR_ENABLED=y
  • 同檔案 :38:record / AEC support
  • 同檔案 :47:ENC 3.0

同檔案 :35CONFIG_BLE_AUDIO_ENABLED 未啟用,並不代表 HFP 未啟用。BLE Audio 與 Classic Bluetooth HFP 是不同 profile;本產品的 call audio 走 Classic HFP。

原版已有 HFP profile 與 SCO handler#

WuQi master 原本就有:

  • HFP state processing:wq-adk/components/apps/acore/bt/src/app_bt.c:1307-1396
  • HFP profile connected event:同檔案 :1367-1378
  • SCO connect / disconnect:同檔案 :1418-1456
  • HFP 與 Live microphone 的既有協調邏輯:同檔案 :1457-1474

原版的 profile reconnect 函式也會呼叫:

  • wq_bt_hfp_connect()
  • wq_bt_a2dp_connect()
  • wq_bt_avrcp_connect()

也就是說,HFP profile negotiation、SCO 與 mSBC 的基礎能力不是這次新增的。

STN 原版已有通話與麥克風狀態同步#

STN master 已定義並處理:

  • microphone start / stop / status;
  • incoming / dial / answer / reject / hang-up / call status;
  • music control;
  • call / music volume。

對應檔案為:

  • Apps/Meta_Bounds/Ux/bt_audio/audio_volume_mpack.h:11-39
  • Apps/Meta_Bounds/Ux/bt_audio/ux_audio_handler.c:18-57

這是 STN 與 WuQi 間的命令和狀態同步,不是 STN 上另做一套 HFP。

實際被註解掉的是什麼#

WuQi masterwq-adk/components/apps/acore/bt/src/app_bt.c:1219-1284 中,bt_evt_le_encryp_result_handler() 內有一段 #if 0

這段停用程式原本會:

  1. 接收 BLE encryption success;
  2. 取得 CTKD identity address;
  3. 排程 Classic Bluetooth connection;
  4. Classic link 建立後主動中斷 BLE。

它是產品特定的 BLE / CTKD handoff 流程,不是 HFP codec、SCO transport、mic pipeline 或 speaker pipeline。因此不能從這段 #if 0 推論「vendor 把 HFP 註解掉」。

目前 POC 也不能直接把這整段打開,因為它會在 Classic link 建立後中斷 BLE;而現在的 macOS POC 需要保留 BLE 作為 Camera、設定及控制通道。

為什麼原版有 HFP,我們仍需大量修改#

連線發起者與事件順序不同#

Vendor 原流程假設原生 App 與 Classic Bluetooth lifecycle,部分 profile 恢復會由 SPP 或 vendor App 的事件觸發。

目前 POC 的順序是:

  1. macOS 連接 BLE GATT;
  2. BLE secure exchange 透過 CTKD 取得 Classic identity;
  3. Classic ACL 可能早於 SPP 建立;
  4. HFP / A2DP / AVRCP 必須從 ACL state 啟動,不能等待 SPP;
  5. BLE 仍需保持連線,供 WiFi Camera 與裝置控制使用。

所以「原本可當藍牙耳麥」不代表「macOS BLE-first 的連線方式可以自然啟動並恢復所有 profile」。

三種 transport、兩顆處理器同時運作#

目前 POC 同時使用:

  • BLE GATT:裝置控制;
  • Classic Bluetooth HFP / SCO:call audio;
  • WiFi:camera / live transport;
  • WuQi:Bluetooth 與 audio;
  • STN:camera、UI、WiFi / Live state。

因此,同一個「連線失敗」可能來自 BLE、CTKD、Classic ACL、HFP profile、SCO、audio DSP、WiFi、CameraX 或跨晶片狀態。若只用單一 Connected state 表示所有層級,很容易出現 UI 顯示成功但實際功能未就緒的情況。

HFP 與 Live 共用麥克風資源#

Live streaming 會錄製麥克風並進行 Opus encoding;HFP 則需要 voice / SCO microphone pipeline 與 mSBC encoder。若 Live 尚未釋放 record pipeline 就啟動 SCO,兩條路徑可能同時持有麥克風或留下部分 DSP state。

目前 WuQi 會在啟動 SCO audio pipeline 之前,先停止 Live Opus microphone 並中止 Agent audio downlink。對應位置為 app_bt.c:1450-1472

WuQi 相較 Master 的主要修改#

Pure BLE control 與 CTKD / profile startup#

目前版本新增或調整:

  • Pure BLE command service 與 secure command tunnel;
  • Classic encryption 完成後不再立即中斷 BLE;
  • CTKD 對應的 Classic ACL 建立後直接啟動 HFP / A2DP / AVRCP,不再依賴可選的 SPP transport;
  • Classic ACL 已存在但 application PDL 遺失時,自動修復 PDL 並重新連接 profiles;
  • 將 CTKD 各階段狀態回報給 host,能區分 BLE、Classic path 與 profile failure。

關鍵位置:

  • wq-adk/components/apps/acore/bt/src/app_bt.c:937-951
  • wq-adk/components/meta_bounds/acore/mhal/msg_dispatcher/src/mhal_msg_dispatcher.c:97-128
  • 同檔案 :188-220

這些修改處理的是 HFP 的啟動與恢復,不是重寫 HFP protocol。

BLE disconnect / reconnect recovery#

原 detach path 可能在 response 尚未送完時同步拆除共用 Bluetooth state。實際現象是眼鏡仍 advertising,但下一次 GATT connect 一直 timeout,最後只能重開眼鏡。

目前 wq-adk/components/meta_bounds/acore/ux/src/ux_connection_handler_bt.c:202-218 改為:

  • 先回覆 host disconnect;
  • 不在這個 command handler 中強制同步拆除 shared BT baseband;
  • BLE transport lifetime 由 host 與實際 BLE link event 管理。

SCO resource arbitration#

HFP SCO 啟動前,目前 WuQi 會:

  1. 檢查 Live Opus microphone 是否仍在錄音;
  2. 停止並確認 microphone ownership 已釋放;
  3. 若 preemption 失敗,拒絕 SCO,而不是在不一致狀態下繼續;
  4. 中止 Web / Agent audio downlink;
  5. 最後才啟動 SCO audio pipeline。

對應位置:app_bt.c:1450-1472

選取 HFP 麥克風時眼鏡重開#

重複出現的 WuQi DCORE crash 為:

Crash Signature
Hardfault epc=0x26035a78

使用現有 G07S5 DCORE ELF 解碼當時記錄的 call stack,得到:

DCORE Call Stack
vect_div_aligned
  -> AUDIO_NS_Init
  -> dsp_voice_dn_process
  -> dsp_dma_process_20ms
  -> dsp_dma_process
  -> echo_probe
  -> wq_pipeline_stream_control

這條呼叫鏈將故障定位到 HFP voice pipeline 啟動時的 vendor ENC / noise-suppression 初始化。對應到使用者現象就是:macOS 一選眼鏡作為 input,SCO 開始、DSP voice pipeline 啟動,接著 WuQi hardfault 並重開。

目前 wq-adk/components/audio_algorithm/processor/src/enc.c:261-348 的 G07S5 修正為:

  • 初始化完整 microphone pointer array;
  • 在 G07S5 上辨識 SM_VOICE
  • HFP voice path 不再進入不相容的 vendor ENC / NS;
  • 直接輸出 main voice microphone PCM;
  • 記錄 microphone topology 與 PCM diagnostics。

這是目前 HFP audio 與 vendor 原版最重要的功能差異。HFP 本來存在,但其 ENC 設定在新的並行情境下不穩定。

Speaker 有聲音,但 microphone 幾乎無聲#

移除重開問題後,diagnostics 已證明:

  • microphone PCM frame 不是全零;
  • mSBC encoder 持續執行;
  • SCO packet 持續送出且沒有 TX failure。

剩餘問題是訊號電平。Vendor voice-volume block 僅支援 attenuation(<= 0 dB),正增益設定沒有得到需要的上行音量。

目前 wq-adk/components/audio_algorithm/processor/src/volume_controller.c:279-340

  • 以 Q12 fixed-point 實作正的 HFP uplink gain;
  • 上限設為 +18 dB;
  • 對 16-bit PCM 做 saturation,避免整數 overflow。

另外,wq-adk/components/apps/acore/audio/src/app_audio.c:2343-2352 會在 SCO connect 時清除可能殘留的 upstream mute。

這說明為什麼 vendor 原本已有 HFP 與 mSBC,我們仍需要修改,最後 checkpoint 的 microphone 才真正可用。

連線提示音與 diagnostics#

目前 WuQi 將 user-facing connected tone 延後到 profile ready,避免 BLE、Classic ACL、HFP 各完成一次就重複播放提示音。

另外新增:

  • mic pre-gain / post-gain level;
  • microphone topology 與實際 source;
  • mSBC run / frame / byte count;
  • SCO RX / TX frame、byte 與 allocation failure;
  • saved crash summary 與 DCORE call stack;
  • CTKD / profile stage result。

沒有這些資料時,host 端只能看到「audio device 不見」或「眼鏡重開」,無法判斷是 PCM、gain、mSBC、SCO 還是 DSP init 出錯。

STN 相較 Master 的主要修改#

STN 沒有重新實作 HFP#

目前 STN 延續 vendor 原本的 call、mic、music 與 volume command routing。HFP profile、SCO codec、mSBC 與 microphone DSP 仍在 WuQi。

因此,STN 這部分的主要價值是讓 Camera / Live 狀態能與 HFP 穩定共存,而不是新增 HFP protocol。

Web / Agent audio downlink 是另一條功能#

目前 STN 額外新增 command 27-31:

  • CMD_AUDIO_DOWNLINK_BEGIN
  • CMD_AUDIO_DOWNLINK_DATA
  • CMD_AUDIO_DOWNLINK_PLAY
  • CMD_AUDIO_DOWNLINK_STOP
  • CMD_AUDIO_DOWNLINK_END

對應位置:

  • Apps/Meta_Bounds/Ux/bt_audio/audio_volume_mpack.h:39-43
  • Apps/Meta_Bounds/Ux/bt_audio/ux_audio_handler.c:56-66

這些 command 用於 Web / Agent TTS 音訊傳到眼鏡播放,不是 HFP SCO speaker path。HFP call 開始時,WuQi 必須中止這條自訂 downlink,避免兩條 playback path 同時持有音訊資源。

Camera / Live lifecycle recovery#

目前 STN 在 Apps/Meta_Bounds/Services/livestream/livestream_service.c:239-269 將 STOP 改成 authoritative reset boundary:

  • 即使 service state 已經是 STOP,仍實際停止 CameraX / media;
  • 釋放 performance 與 screen / power hold;
  • reset status UI;
  • 送出 recording indicator end event;
  • 保留 WiFi,供下一次 Live 使用。

Remote start 也會先清除 stale media / sensor ownership,再重新啟動(同檔案 :492-519)。

這些不是 HFP 實作,但能避免 stale camera state 影響後續 Camera + HFP session,也讓 Disconnect / Connect 具有實際恢復效果。

STN 大部分 diff 屬於 streaming#

STN branch 另包含 direct WebSocket / WSS、TLS diagnostics、SDIO congestion handling、frame integrity、runtime bitrate 與 camera recovery。這解釋了 63 files 的大幅差異,但不應將這些都列為 HFP 開發。

現象、原因與修正對照#

使用者現象 根因 修正
已配對,但 macOS 沒有眼鏡 audio device CTKD 先建立 Classic ACL,原本依賴 SPP 的 profile trigger 未發生 從 CTKD-matched ACL 啟動 HFP / A2DP / AVRCP,並修復 PDL
BLE reconnect timeout,需重開眼鏡 shared BT teardown 與 stale GATT / controller state host-owned detach,不在 command handler 同步拆 baseband
選眼鏡作 microphone 後重開 HFP voice startup 進入 vendor ENC / NS,DCORE hardfault G07S5 HFP ENC bypass,直接使用 main-mic PCM
Speaker 正常但 microphone 無聲 PCM / mSBC / SCO 正常,但正增益未生效,且可能殘留 mute +18 dB Q12 gain,加上 SCO upstream unmute
Live 與 HFP 互相造成異常 兩條路徑同時取得 mic / playback resource SCO 前先 preempt Live Opus 與 Agent downlink
離開 Live 後 camera 無法恢復 STN 顯示 STOP,但 media / sensor 仍被持有 authoritative media stop 與 stale-state reset
連線時播放多次提示音 BLE、Classic 與 profile 各自完成時都可能回報 profile ready 後只播放一次 user-facing tone

這次實作真正困難的地方#

困難不在 HFP protocol 本身,而是既有模組的原始假設已不再成立:

  1. 連線時序: BLE、CTKD、Classic ACL、HFP、WiFi 與 Camera readiness 都是非同步完成。
  2. Transport lifetime: CTKD 建立 Classic Bluetooth 後,BLE 仍必須保持可用。
  3. Profile recovery: macOS 可能保留 pairing,但眼鏡的 PDL、ACL 或 profile state 已不一致。
  4. Audio ownership: Live Opus、HFP SCO 與 Agent downlink 共用有限的 mic、DSP 與 playback resource。
  5. 跨晶片狀態: WuQi 管 Bluetooth / audio,STN 管 camera / UI / WiFi,恢復流程必須讓兩邊同步 reset。
  6. 底層除錯: 表面現象是 silent mic 或 reboot,實際 fault 位於 DCORE DSP pipeline。

Vendor HFP 提供了 profile 與 codec 的基礎;目前的工作是讓它能在 BLE-first 的 macOS virtual-camera 架構中使用,並修正這個新架構暴露出的 G07S5 runtime 問題。

目前取捨與後續驗證#

  • G07S5 HFP microphone 目前 bypass vendor ENC / noise-suppression,已排除 hardfault,但這條路徑不再套用 vendor AEC / NS 效果。
  • +18 dB uplink gain 可提高可聽度,也可能放大環境噪音或讓大聲輸入 clipping。產品化應以實際錄音統計重新調整,不宜永久沿用 demo 固定值。
  • Camera + HFP 仍應進行長時間與狀態切換測試,包括充電 / 拔電、折疊 / 展開、sleep / wake、App relaunch、重複 Disconnect / Connect,以及反覆切換 Meet device。
  • 正式 release 前,應使用確切 vendor source tag、binary map 與 build configuration 再驗證一次,而不是只依 repository master 判斷。

最終回答#

Vendor release 原本確實支援 HFP 與 audio;HFP 主體並沒有被註解掉。被停用的是其中一條 BLE / CTKD handoff 流程。我們投入的工作主要是適配 BLE-first 的連線方式、讓 BLE / WiFi Camera / Classic HFP 能同時存在、補足 profile 與 reconnect recovery,並修正新情境下暴露出的 G07S5 DSP microphone hardfault 與上行 gain 問題。

↑ 返回頂端