「この Bluetooth イヤホン、ゲームで遅くない?」 その感覚を、実測したミリ秒で確かめるためのテストアプリです。 スマホからテスト信号を鳴らし、マイクで取り込んだ音とのズレを計測することで、 Bluetooth / 有線 / スピーカーの実際のオーディオ遅延を可視化します。
blootoothchecker は、オーディオの「体感ラグ」を定量化するための実験用アプリです。 スマホで短いクリック音やチャープ信号を再生し、 イヤホンから出た音をスマホのマイクで拾って、 元の波形と録音波形のズレ(サンプル差) を計算します。
計測結果は「平均遅延」「最小・最大」「ばらつき」として保存され、 有線 / Bluetooth(SBC / AAC / LDAC …)や機種ごとの違いを比較できます。 ゲーム・配信・音ゲーなど、レイテンシがクリティカルな用途のための ベンチマークとして使うことを想定しています。
アプリ内部では、AudioTrack でテスト信号を出力し、 AudioRecord でマイク入力を同時に取得します。 取得した 2 つの波形を Kotlin 側でバッファリングし、 相互相関(cross-correlation)でピークを求めることで遅延を推定します。
遅延測定では、あとから位置を特定しやすい信号が重要です。 blootoothchecker では、立ち上がりの鋭いクリック音や、 周波数をスイープするチャープ信号を使うことで、 相互相関のピークがシャープになりやすいように設計しています。
val fs = 48000
val length = 2048
// 例: 簡易インパルス
val impulse = FloatArray(length).apply { this[0] = 1f }
// 例: チャープ信号(省略)
Android のオーディオスタックは OS 側でもバッファを持つため、 「完全なサンプル同期」は難しいです。 blootoothchecker では、再生開始と録音開始のタイミングをできるだけ揃えつつ、 録音側にテスト信号が現れるまで十分なバッファを確保して解析しています。
録音波形 y[n] と元信号 x[n] に対して、
相互相関 R_xy[k] = Σ x[n]·y[n+k] を計算し、
最大値を取るシフト量 k* を求めます。
これを k* / fs 秒として、実測遅延としています。
fun estimateDelayMs(x: FloatArray, y: FloatArray, fs: Int): Float {
// 簡易な相互相関(実装は最適化可)
var bestK = 0
var bestVal = Float.NEGATIVE_INFINITY
for (k in 0 until maxLag) {
var sum = 0f
for (n in x.indices) {
if (n + k < y.size) sum += x[n] * y[n + k]
}
if (sum > bestVal) { bestVal = sum; bestK = k }
}
return bestK * 1000f / fs
}
遅延は毎回完全に同じではないので、 同じデバイス・同じ接続方法で複数回測り、 平均・標準偏差・最小/最大などを保存します。 これにより、「たまたま遅かった」のか 「そもそもレイテンシが大きい」のかを切り分けやすくしています。
手元のスマホとイヤホンで、 有線イヤホン / Bluetooth イヤホン(SBC / AAC)を何度か測定したところ、 おおよそ以下のような傾向が見られました(あくまで一例です)。
「Bluetooth はなんとなく遅い」ではなく、 実際に ○○ms 遅い / ばらつきがこれくらい と数字で見えると、 用途に応じたデバイス選びがしやすくなります。
・スマホの内部バッファや OS レベルの遅延も含んだ値になるため、 「絶対値」としては限界があること ・周囲の騒音やマイクの位置により測定が不安定になること ・リアルタイムグラフ表示を滑らかにしつつ、バッテリー消費を抑える必要があること など、実験ツールならではの難しさもあります。
実際にイヤホンを接続して測定を行い、 結果がリアルタイムで更新されていく様子を撮影したデモ動画です。
blootoothchecker は現状、オーディオ遅延を測るだけのツールです。 しかし今後は、測定結果をもとに 「このゲームは有線推奨」「この遅延なら音ゲーは厳しい」など、 用途別の目安も提示できるようにしていきたいと考えています。
計測精度・使いやすさ・解釈のしやすさをバランスよく伸ばしていく予定です。
オーディオの世界では、「なんとなく遅い」「気のせいかも」という 感覚ベースの議論が多くなりがちです。 blootoothchecker を作る過程で、 「体感」を「データ」に変換することの大切さを改めて実感しました。
一方で、計測の前提や限界(スマホ内部遅延 / ノイズ / 計測環境)もはっきり見えてきて、 「数字が出たから正しい」というわけではないことも学びました。 それでも、自分の耳と数値の両方を並べて考えられるようになったのは、 この小さなテストアプリのおかげだと思います。