Ubuntu Weekly Recipe

第681回 BluetoothヘッドセットでHD Voiceを使う

この記事を読むのに必要な時間:およそ 3 分

Bluetoothデバイスを音声通話やビデオ会議で使用する際は,音楽再生用のA2DPではなく,音声入力(マイク)と出力を同時に使用できるHFP(Hands-Free Profile)が一般に使われます。このHFP規格の中で,HFP 1.6以降でサンプリングレートを従来の8kHzから16kHzに改善したWide Band Speechに関する仕様が規定されています注1⁠。

注1
Wide Band SpeechはHFP 1.8でも規格上必須とはなっておらず,HFP 1.6以上のバージョンが製品説明に記載されているからといって必ずしもサポートされているとは限りません。

このWide Band Speech(HD Voiceとも呼ばれます)は,HFP 1.6が2011年に策定されたこともあり,他のOSでは少なくとも数年前までには対応が完了している状況です。Ubuntuを含むいわゆるLinuxデスクトップでは,Wide Band Speechに長らく対応していなかったため,Bluetoothヘッドセットをビデオ会議に使うのはお互いの声が聞き取りづらいなど音質面で厳しい状況でした。

そうしたなか今年に入って動きがあり,Ubuntuがデフォルトで使用しているPulseAudioでは,バージョン15.0でWide Band SpeechのためのmSBCコーデックがサポートされるようになりました注2⁠。今回は,2021年10月にリリース予定のUbuntu 21.10(PulseAudio 15.0が利用可能)で実際にWide Band Speechが使えるか確認してみます。

注2
PulseAudioを置き換える可能性があるとして注目されているPipeWireプロジェクトでは,バージョン0.3.20でmSBCサポートが入ったようです。

テストに使用したBluetooth機器

今回は以下の機器を使用しました。

  • 親機(AG:Audio Gateway)
    • Lenovo ThinkPad T480内蔵のIntel Dual Band Wireless-AC 8265
      • Bluetooth 4.2
  • 子機(HF:Hands-Free unit)
    • SOUNDPEATS Air3
      • Bluetooth 5.2
      • HFPバージョン: 明記なし
    • Anker Soundcore Liberty Neo 2
      • Bluetooth 5.2
      • HFPバージョン: 明記なし
    • JBL E25BT
      • Bluetooth 4.1
      • HFPバージョン: 1.6

結論から述べてしまうと,SOUNDPEATS Air3とAnker Soundcore Liberty Neo 2ではWide Band Speechが有効となり,JBL E25BTでは有効になりませんでした。JBL E25BTは4年以上前に発売された機種ですし,仕方がないのかもしれません。いずれにしろ,Wide Band Speech対応が明記されていない限り,BluetoothやHFPのバージョンなどのスペックからは対応可否がわからないのが正直なところです。

Wide Band Speechを使用した接続

Note:今回はリリース前のバージョンであるUbuntu 21.10を使っています。正式リリース時には動作が異なる可能性があります。

Wide Band Speechにお互いが対応していれば自動で使われるため,実は通常のペアリングや使用となんら変わりません図1⁠。それだけでは実際にWide Band Speechが使われているかわからないので,実際に確認する方法も紹介します。

図1 ペアリング,接続は通常通り

図1

Bluetoothヘッドセットに接続したら,サウンドメニューで入力と出力の両方をヘッドセットに設定します。そして,接続プロファイルがHFPに切り替わっていることを確認します図2⁠。

図2 出入力をヘッドセットに設定し,HFPに切り替え

図2

現状では画面上からHFP接続の詳細を確認できる簡単な方法がないので,端末を使います。pactl list sourcesを実行し,PulseAudioが認識している入力一覧の中からState: RUNNINGとなっている入力を探します。Wide Band Speechに対応していれば,次のようにbluetooth.codec = "mSBC"Sample Specification: s16le 1ch 16000Hz(16kHz)と表示されるはずです。

$ pactl list sources
  ...
  Source #4
          State: RUNNING
          Name: bluez_source.28_52_E0_XX_YY_ZZ.handsfree_head_unit
          Description: SOUNDPEATS Air3
          Driver: module-bluez5-device.c
          Sample Specification: s16le 1ch 16000Hz
          Channel Map: mono
          Owner Module: 33
          Mute: no
          Volume: mono: 65536 / 100%
                  balance 0.00
          Base Volume: 65536 / 100%
          Monitor of Sink: n/a
          Latency: 42932 usec, configured 32500 usec
          Flags: HARDWARE HW_VOLUME_CTRL LATENCY
          Properties:
                  bluetooth.protocol = "handsfree_head_unit"
                  bluetooth.codec = "mSBC"
                  device.intended_roles = "phone"
                  device.description = "SOUNDPEATS Air3"
                  device.string = "28:52:E0:XX:YY:ZZ"
                  device.api = "bluez"
                  device.class = "sound"
                  device.bus = "bluetooth"
                  device.form_factor = "headset"
                  bluez.path = "/org/bluez/hci0/dev_28_52_E0_XX_YY_ZZ"
                  bluez.class = "0x240404"
                  bluez.alias = "SOUNDPEATS Air3"
                  device.icon_name = "audio-headset-bluetooth"
          Ports:
                  headset-input: Headset (type: Headset, priority: 0, available)
          Active Port: headset-input
          Formats:
                  pcm

一方,対応していない場合は,次のようにbluetooth.codec = "CVSD"Sample Specification: s16le 1ch 8000Hz(8kHz)となります。

$ pactl list sources
...
Source #14
        State: RUNNING
        Name: bluez_source.00_11_67_XX_YY_ZZ.handsfree_head_unit
        Description: JBL E25BT
        Driver: module-bluez5-device.c
        Sample Specification: s16le 1ch 8000Hz
        Channel Map: mono
...
        Properties:
                bluetooth.protocol = "handsfree_head_unit"
                bluetooth.codec = "CVSD"
                device.intended_roles = "phone"
                device.description = "JBL E25BT"
                device.string = "00:11:67:XX_YY_ZZ"
                device.api = "bluez"
...

実際の音を聞いてみる

自分の声が相手にどのように届いているのかを体験する一番簡単な方法は,ヘッドセットのマイクで拾った音を,イヤホンにそのまま戻してあげる方法です。PulseAudioにはその動作を実現するloopbackモジュールがあり,これを有効にしてみます。出力先がイヤホンになっていることを事前に確認してください。スピーカーが出力になっている場合にloopbackを有効にするとハウリングが発生します。

次のコマンドを実行し,何かしゃべってみます。その声が少し遅れてイヤホンから聞こえるはずです。

$ pactl load-module module-loopback

この時に聞こえる声が,相手に届くものに近いでしょう。実際には再度変換されたり,ノイズが除去されたりした後に届くので多少の違いはあります。音の出力を止めるには,次のコマンドを実行します。

$ pactl unload-module module-loopback

他にも,プロファイルをA2DPではなくHFPに設定したままYouTubeで人がしゃべっている動画を見るなどすると,Wide Band Speechの感覚をつかめると思います。A2DPを使っているときと比べると微妙と感じるかもしれません。それもそのはず,サンプリングレート16kHzのWide Band SpeechはHFPで現状サポートされているものの中では良いものですが,まだまだSuper Wide BandやFull Bandといったより広い帯域をカバーできておらず注3⁠,A2DP標準のSBC(サンプリングレート44.1kHz)と比べてもだいぶ差があります。それでも,以前の明らかに音質の良くない状況から改善すると思うと,うれしいニュースです。

注3
QualcommのaptX Voiceがサンプリングレート32kHzを採用していますが,まだまだ一般には普及していないようです。

著者プロフィール

村田信人(むらたのぶと)

Ubuntu Japanese Teamメンバー。Ubuntuオフラインミーティングに参加するうちにUbuntu Japanese Teamの活動に興味を持ち,2009年8月に加入。