- 標準のSBCコーデックの低音質は、コーデック自体の限界だけでなく、Bluetoothスタックとヘッドホン設定の保守的な制限にも起因しており、既存機器でもソフトウェア修正で改善の余地がある
- 一般的なBluetoothスタックは44.1kHzステレオを通常328kbpsでネゴシエートするが、Dual Channelを強制すると同じbitpool 53でも約617kbpsまで上がる
- Android 8.1・9向けパッチは、Bluetooth機器設定にSBC Dual ChannelをHD Audioオプションのように追加し、EDR 3Mb/s機器には551kbps、EDR 2Mb/s機器には452kbpsを使用する
- 551kbpsと452kbpsはBluetooth 5-slot伝送効率を考慮した値であり、bitpoolをさらに上げるとフレームの束ね数が減って、無線環境が悪い場合に途切れやすくなる
- LineageOS、Resurrection Remix、crDroidの利用者は設定のチェックボックスで高ビットレートSBCを有効化でき、Linux利用者はPulseAudioパッチでより高いSBCビットレートとaptX系サポートを得られる
SBCの音質が低く聞こえる理由
- 一部のワイヤレスヘッドホン利用者は、すべてのBluetoothオーディオ機器が対応するSBCコーデックで音質低下や高域不足を経験する
- aptXやLDAC対応の機器やヘッドホンを買う方法もあるが、それらのコーデックはライセンス費用が必要で、機器価格を押し上げることがある
- 低いSBC品質の核心的な原因は、現在のBluetoothスタックとヘッドホン設定にある人為的制限であり、既存機器でもソフトウェア修正で回避できる
SBCパラメータとビットレート
- SBCは接続設定段階で複数のパラメータをネゴシエートする
- オーディオチャンネルの種類と数: Joint Stereo、Stereo、Dual Channel、Mono
- 周波数バンド数: 4または8
- パケット内のオーディオブロック数: 4、8、12、16
- 量子化ビット割り当て方式: Loudness、SNR
- 量子化に使う最小・最大bitpool: 通常2..53
- デコーダはこれらすべてのパラメータ組み合わせをサポートしなければならないが、エンコーダは一部のみ実装していてもよい
- 既存のBluetoothスタックは通常、Joint Stereo、8 bands、16 blocks、Loudness、bitpool 2..53の組み合わせをネゴシエートし、このとき44.1kHzステレオ音声は328kbpsでエンコードされる
- bitpoolはエンコードのビットレートを変える値で、値が高いほどビットレートと音質が上がる
- 正確なbitpool値とビットレートの対応は、特定のプロファイル内でのみ成り立つ
- チャンネル種別、周波数バンド数、オーディオブロック数もビットレートに大きく影響する
- Dual ChannelはStereoやJoint Stereoと異なり、各チャンネルを別々にエンコードし、チャンネルごとに個別のbitpoolを使う
- Joint Stereoの代わりにDual Channelを強制すると、同じbitpool 53でもビットレートは約617kbpsとなり、ほぼ2倍になる
A2DP仕様と現在のスタックの制限
- 2007年から2015年まで有効だったA2DP specification v1.2では、デコーダは最大ビットレートを超えないすべてのbitpool値をサポートしなければならないと定めていた
- このプロファイルはmonoで320kb/s、2チャンネルモードで512kb/sを最大ビットレートに制限していた
- 新しい仕様ではビットレート制限が明記されていない
- 2015年以降に発売されたEDR対応の最新ヘッドホンは、最大730kbpsまでサポートできると想定される
- テストされたBluetoothスタックであるLinux PulseAudio、Android、Blackberry、macOSはいずれも、最大bitpoolパラメータに人為的制限を設けている
- ほぼすべてのヘッドホンも最大bitpool値を53に制限している
- 修正されたBluetoothスタックでは大半の機器が551kbpsで途切れやノイズなく動作したが、標準のBluetoothスタックは通常条件ではこのビットレートをネゴシエートしない
Android Bluetoothスタックのパッチ
- すべてのA2DP互換BluetoothスタックはDual Channelモードをサポートしなければならないが、一般利用者がこのモードを強制する方法はない
- Android 8.1とAndroid 9向けパッチは、Dual Channelをスタックと開発者メニューに追加し、aptX、AAC、LDACのようにBluetooth機器設定のHD Audioコーデックオプションとして扱う
- パッチリンク
- このチェックボックスはDual Channelモードを切り替え、機器ごとに次のビットレートを使う
- EDR 3Mb/s機器: 551kbps
- EDR 2Mb/s機器: 452kbps
- パッチセットは次の代替ファームウェアにマージされた
- LineageOS 15.1: 2019年3月31日から
- LineageOS 16.0: 2019年5月13日から
- Resurrection Remix: 2019年5月14日から
- crDroid: 2019年5月13日から
551kbpsと452kbpsを選んだ理由
- Bluetoothの時分割伝送は、大きな固定サイズのパケットを効率よく送るよう設計されている
- 1回の伝送で送れる最大スロット数は5個で、1-slotと3-slot伝送モードもあるが、2-slotと4-slotモードはない
- 5-slot伝送で送れるデータ量は次の通り
- 2Mbps接続: 最大679 bytes
- 3Mbps接続: 最大1021 bytes
- 3-slot伝送の最大データ量は次の通り
- 2Mbps接続: 367 bytes
- 3Mbps接続: 552 bytes
- 367または552 bytesより大きく、679または1021 bytesより小さいデータを送る場合でも、5-slotが必要になり伝送効率が下がる
- 44.1kHz音声をSBC Dual Channel、bitpool 38、16 blocks、8 frequency bandsでエンコードすると、164-byteのオーディオフレームと452kbpsのビットレートになる
- オーディオペイロードはL2CAPとAVDTP伝送プロトコルで包む必要があり、この過程でオーディオペイロードから16 bytesのオーバーヘッドが差し引かれる
- EDR 2Mb/s DH5では、5-slotの音声伝送1回にオーディオフレーム4個を格納できる
679 - 4(L2CAP) - 12(AVDTP/RTP) - 1(SBC header) - (164*4) = 6
- パケットには6 bytes残る
- 単一パケットは最大11.7ms分の音声データを含み、3.75msで送信される
- bitpoolを少し上げるだけでも、1回の伝送にオーディオフレーム4個を収められず、3個ずつ送る必要が出てくる
- 伝送効率が低下する
- 1パケットに含められる音声量が減る
- 無線環境が悪い場合に音切れの可能性が高まる
- EDR 3Mb/s向けの551kbpsも同じ原理で選ばれている
- bitpool 47、16 blocks per frame、8 frequency bandsではフレームサイズは200 bytes
- 1回の伝送で最大5フレーム、つまり14.6ms分の音楽を束ねられる
- SBCパラメータ計算は複雑で、手計算ではミスしやすいため、計算用Webツールが提供されている
aptXとSBCの音質差
- aptXが常にSBCより優れているという通説に反して、場合によってはaptXが標準のSBC 328kbpsより低い音質になることがある
- SBCは周波数バンドに量子化ビットを動的に割り当て、低い方から高い方へビットを配分する
- 低周波数帯と中周波数帯に全ビットレートを使うと、高周波数帯はカットされるか無音処理される
- aptXは周波数バンドを常に同じビット数で量子化する固定ビットレートコーデックである
- 44.1kHzでは352kbps
- 48kHzでは384kbps
- aptXは必要な周波数帯へビットを移せず、周波数を切り落としはしないが、量子化ノイズを加えて音声のダイナミックレンジを狭め、ときにノイズを生むことがある
- SBCは逆に静かな領域を捨てるため、328kbpsのSBCと比べると、aptXは広い周波数帯域の音楽で平均的には歪みが少ない
- 狭い周波数帯域と広いダイナミックレンジを持つ音楽では、SBC 328kbpsがaptXより良い場合もある
- ピアノ録音の例では、エネルギーの大半が0〜4kHzにあり、10kHzまで続いていた
- SBC 328kbpsは16kHz以上の帯域を周期的に完全にカットしていた
- aptXは人が聞き取れる周波数スペクトラムにより多くの歪みを入れていた
- SBC 328kbpsは0〜10kHz帯域でより少ない歪みを出し、残りの周波数をカットしていた
- SBC 485kbpsは全周波数帯域をカットせず保持するのに十分だった
- 元音声とSBC/aptXエンコード済みファイルの資料が提供されている
- 高ビットレートSBCを使えば、多くの場合aptXより良い音を得られ、EDR 3Mb/s対応ヘッドホンでは551kbps SBCがaptX HDに非常に近い音を出す
さらに高いビットレートの選択肢
- Androidパッチセットには、EDR 2Mb/s機器のビットレートをさらに高める追加オプションがある
persist.bluetooth.sbc_hd_higher_bitrateの値を1に設定すると、ビットレートを452kbpsから595kbpsへ引き上げられる
- このオプションは混雑した無線環境で伝送安定性を下げる可能性がある
# setprop persist.bluetooth.sbc_hd_higher_bitrate 1
- 極端なビットレート用パッチは現在LineageOS 15.1にのみマージされており、LineageOS 16.0にはマージされていない
対応機器と比較ツール
- SBC Dual Channelは、ほぼすべてのヘッドホン、スピーカー、車載ヘッドユニットでサポートされている
- 標準がすべてのデコード機器でこのモードのサポートを要求しているため、大半の機器で動作する
- このモードで問題が出る機器も少数存在するが、非常にまれな事例である
- 対応機器情報は次のコミュニティで確認できる
- ブラウザ上で音声をリアルタイムにSBC、aptX、aptX HDへエンコードするWebサービスも提供されている
AOSP反映の試みと利用方法
- GoogleのBluetoothスタック開発者に、AndroidメインブランチであるAOSPへパッチを取り込んでほしいと連絡したが、返答は得られなかった
- Gerrit code review system for Androidに上がっているパッチも、Android開発関係者からコメントを得られていない
- Gerritパッチセットは古い初期リビジョンの1つであり、開発者が関心を示せば更新できる
- LineageOS、Resurrection Remix、crDroid利用者は、Bluetooth機器設定のチェックボックスを有効にしてBluetoothオーディオ品質を高められる
- Linux利用者はPali RohárのPulseAudioパッチを導入して、より高いSBCビットレートを利用できる
- このパッチはaptX、aptX HD、FastStreamコーデック対応も追加する
1件のコメント
Hacker Newsのコメント
これは素晴らしい: SBC は広くサポートされていて、既存標準の自然な拡張のように見える
個人的には問題は SBC か LDAC/AAC かではなく、HFP がひどいことにある。マイクがオンになった瞬間に90年代へ戻ったような感じになり、双方向 Bluetooth オーディオをきちんと実現できるなら本当に歓迎したい
あるいは AVRCP かもしれないが、どちらにせよ音はひどい
この記事は Bluetooth 全般についてではなく、Android Bluetooth スタック に埋もれていたバグを深く掘り下げたものだ
筆者がまったく認めていない点は、基盤ハードウェアが非常に多様だということだ。Android は無数の Bluetooth チップセット上で動作するため、自分のハードウェアでパッチが動いたからといって、他の Android スマートフォンでも動く保証はない
また、その瞬間に端末が何をしているかも影響する。BT+Wi-Fi 共有チップセットで Wi-Fi で映像をストリーミングしながら音声をヘッドホンへ送る場合、端末は Wi-Fi 利用と Bluetooth の間でリソースを配分しなければならない。だからローカル保存音声とストリーミング音声が必ずしも同じ コーデックパラメータ を受け取るとは限らない
この話題には筆者が考慮していない微妙な要素が多すぎるので、読んだ内容は慎重に受け取るべきだ
これにより、Android と Bluetooth レシーバーが強制する最大 bitpool を超えることなく、より高いビットレートを使える
それでもソースとシンクの間でネゴシエーションは行われ、どちらか一方がデュアルチャネル SBC をサポートしていなければ、対応可能な方式へフォールバックする。私が保守していた端末はすべて対応していたが、当時テストした一部の安価なスピーカーは対応しておらず、joint stereo セッションとしてネゴシエートされた
Windows では Alternative A2DP Driver がこの機能を提供している。SBC パラメータを調整でき、AAC や aptX も使えるようになる
私の経験ではうまく動作し、Sony XM4 で LDAC を使うのにも役立つ。試用版方式だが価格は安い
高音質モードで Bluetooth の通信距離が短くなるのを見たことがあり、実際にコーデックか少なくとも何かが変わっていて、プラシーボではないことのサインのように思える
https://www.bluetoothgoodies.com/a2dp/ とは何の関係もない
人間の可聴範囲は通常 20KHz までとされているが、一部の若い人はそれより少し高い周波数も聞こえることがある
参考までに、Linux でも SBC XQ と呼ばれる方式でより高ビットレートの SBC オーディオを有効にできる。同様に mSBC でより良いヘッドセット音声も使える
もちろん、それでもなお SBC や aptX のレベルにはまったく及ばない
Google 側でこうしたものをすでにマージしてくれていればよかったのにと思う。より良い音声コーデックは多くのヘッドホンなどが対応しているが一般的ではなく、双方向音声の改善は特にまだ不足している
現在ヘッドセットが何を使っているか確認する方法も知りたい
以前、適切な設定を露出するパッチ済み PulseAudio を使っていた記憶があるが、後で「メインストリームにマージされた」と聞いたものの、実際の設定や使用情報が見つからなかった
Bluetooth オーディオプロファイル で、あらかじめ長くバッファできるものを誰か作ってほしい
たとえば1分の曲を再生するなら、曲全体がバッファに載るべきだ。もちろん一時停止したり音量を変えたりしたら、バッファは破棄されるべきだが
長いバッファがあれば、スマートフォンがより頻繁にスリープできて電力を節約でき、無線接続が悪くても耐えられる
RAM が 1〜2MB 程度で済むとしても、ヘッドホンはその RAM をアクティブに保つために貴重なバッテリーを使わなければならない
以前少しオーディオアプリを扱った経験からすると、アプリケーション側の対応も難しそうだ
だからこれはプロトコルの問題というより、個々の製品が設計として取り入れ、アプリでユーザーがオン・オフできるようにする機能に近い
LineageOS でこの機能を使ったことがあるが、正直本当に良かった。サードパーティ製コーデックをサポートしない 車載ステレオ のような機器に、より高品質の音声を送れたし、ヘッドホンにもかなり効果があった
ユーザー体験は磨く必要があるが、機能自体は素晴らしい
タイトルに 2019 を付けるべきだと思う。「現在のすべての Bluetooth スタック」のような表現が出てくるが、こうしたものはすでにしばらく前から PulseAudio や PipeWire に実装されていた
551kbps Dual Channel が 328kbps Joint Stereo より目に見えて高品質だという点には少し懐疑的だ。単に重複情報のエンコードにより多くのビットを使っているだけかもしれない
少なくとも大半の音楽ではそうで、左右に異なる録音トラックを意図的に配置した曲のような例外はあるかもしれない
関連する疑問として、macOS で Bluetooth HFP を改善する方法があるのか気になる
同じヘッドセットを Linux では mSBC でかなり良い品質で使えているのに、macOS では完全にひどく、電話線/モノラル品質になってしまう。Darwin でちゃんと動かすハックがすでにあるのだろうか
この記事を見るまで、自分が SBC を使っていることすら知らなかった。Lineage 18.1 は SBC 対応機器を接続しても、その UI チェックボックスを表示しない。まるで魔法だ -