LoginSignup
1
0

More than 1 year has passed since last update.

AndroidにBluetoothイヤフォンを接続するとAudioTrackの音が鳴らない問題

Last updated at Posted at 2022-06-30

はじめに

Android で AudioTrack を使って音楽を再生するアプリを開発しているのですが、ユーザーからレビューで「ワイヤレスイヤフォンだと音楽が鳴らない」というご指摘をいただき調査した結果、割と謎な手段で問題を回避したので紹介します。

AudioTrack 使用の流れ

    private fun createAudioTrack(
        seek: Int,
        onSeek: ((length: Int, time: Int) -> Unit)?,
        onPlayEnded: (() -> Unit)?
    ) {
        audioTrack?.release()
        val attributes = AudioAttributes.Builder()
            .setUsage(AudioAttributes.USAGE_MEDIA)
            .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
            .build()
        val format = AudioFormat.Builder()
            .setSampleRate(22050)
            .setChannelMask(AudioFormat.CHANNEL_OUT_MONO)
            .setEncoding(AudioFormat.ENCODING_PCM_16BIT)
            .build()
        audioTrack = AudioTrack.Builder()
            .setAudioAttributes(attributes)
            .setAudioFormat(format)
            .setBufferSizeInBytes(basicBufferSize * 2)
            .setTransferMode(AudioTrack.MODE_STREAM)
            .build()
        audioTrack?.positionNotificationPeriod = basicBufferSize / 2
        audioTrack?.setVolume(masterVolume / 100f)
        audioTrack?.setPlaybackPositionUpdateListener(object :
            AudioTrack.OnPlaybackPositionUpdateListener {
            override fun onMarkerReached(audioTrack: AudioTrack?) {
            }

            override fun onPeriodicNotification(p0: AudioTrack?) {
                // 音楽をループしたりフェードアウトしたりシーク位置を検出したり再enqueueしたり (長いので省略)
            }
        })
        JNI.seek(vgsContext, seek * 22050)
        JNI.kobushi(vgsContext, kobushi)
        decode(decodeAudioBufferFirst)
        audioTrack?.write(decodeAudioBufferFirst, 0, decodeAudioBufferFirst.size)
        audioTrack?.play()
        decodeAudioBufferLatch = 0
        decode(decodeAudioBuffers[decodeAudioBufferLatch])

(ザックリとした処理の流れ)

  • デコードした音声データ(22050Hz, mono, 16bit PCM形式)を write
  • play
  • onPeriodicNotification で次データの enqueue や デコード

原因(?)

最初に AudioTrack のバッファサイズ(setBufferSizeInBytes)と同じデータを write していますが、何故か Bluetooth イヤフォン を接続した状態だと バッファサイズの2倍のデータ を書き込まないと再生が始まらない謎の状態でした。

バッファサイズは 16KB にしているので、先頭に 32KB (約0.74秒) の無音が入ることになりますが、これぐらいなら使い勝手上の問題はないからヨシ...ということで。

対策

最初に バッファサイズの2倍の空データを write する ように修正しました。

バッファサイズの2倍のデータを write しなければ動かないのは多分OSのバグかもしれないので、その内治るかもしれません。

再現環境

  • device: Pixel 3
  • OS: Android 12 (sequrity update October 5, 2021)
  • Bluetooth earphone: Power HBQ Pro
1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0