🔬

Audio Session の mixWithOthers 調査隊

2024/01/29に公開

はじめに

AVAudioSessionのmixWithOthersは情報に揺れがあるような気がしたので調査する。

環境

iOS 17.3
iPhone XR
Xcode 15.2

調査方法

B(Background用)とF(Foreground用)のアプリを用意する。BとFの設定をいろいろ変えて次のことを行う。

  1. Bで音楽を再生する。
  2. Bをバックグランドにする。音楽は継続する。
  3. Fを立ち上げて音楽を再生する。Bの音楽が停止するか継続するか調べる。

当然、Bはバックグラウンド再生が可能なようにしておく。

結果

【F】
.ambient
【F】
.soloAmbient
【F】
.playback
mixWithOthersなし
【F】
.playback
mixWithOthersあり
【B】
.playback
mixWithOthersなし
Bは継続 Bは停止 Bは停止 Bは継続
【B】
.playback
mixWithOthersあり
Bは継続 Bは継続 Bは継続 Bは継続

まとめ(暫定)

共存派と独立派に分類するとシンプルになる。

共存派は

  • .ambient、
  • .playback mixWithOthersあり

独立派は

  • .soloAmbient
  • .playback mixWithOthersなし

で、

共存派 x 共存派 は両方音が出る
共存派 x 独立派 は両方音が出る(フォアグラウンド/バックグラウンドは関係ない)
独立派 x 独立派 はバックグラウンド側の音が消される

気になること

soloAmbientのアプリがフォアグラウンドのとき、バックグラウンドにあるアプリが「私の音は共存しても問題ない」と言って音を出し続けるが、これはOKなのか。
つまり「他のアプリと共存させる。たとえ私がバックグラウンドでも。(倒置)」という設定が可能である。これがピンとこない。

考察

ここからはいろんな資料を見ていく。が、その前にmixWithOthersの解釈は3通り考えられるので名前をつける。

  • 【OR説】どちらかが共存派なら両方音を出す。これは現状の仕様。
  • 【F説】mixWithOthersはフォアグラウンドアプリのだけ有効(バックグラウンドアプリのmixWithOthersは無効)
  • 【B説】mixWithOthersはバックグラウンドアプリのだけ有効(フォアグラウンドアプリのmixWithOthersは無効)

各資料に対して、これはF説を言っているのではないか、これはOR説を言っているのではないか、と検証していく。

Configuring Your Audio Session

https://developer.apple.com/library/archive/documentation/Audio/Conceptual/AudioSessionProgrammingGuide/AudioSessionBasics/AudioSessionBasics.html

the default behavior associated with the AVAudioSessionCategoryPlayback category interrupts other system audio when the session is activated. In most cases, a playback app needs this behavior. However, if you want your audio to mix with other system audio, you can override this behavior by setting the AVAudioSessionCategoryOptionMixWithOthers option on the session.

フォアグラウンド側の視点で書かれているのでかなりF説よりだが、バックグラウンド側での設定が無効であるとは書いてない。しかし、F説の内容を言おうとしているのであれば、バックグラウンド側での設定が有効なのか無効なのかの疑いが発生する可能性を知る由もない。とりあえずF説よりの気持ちであることは確認できた。

Responding to Interruptions

https://developer.apple.com/library/archive/documentation/Audio/Conceptual/AudioSessionProgrammingGuide/HandlingAudioInterruptions/HandlingAudioInterruptions.html

An audio interruption is the deactivation of your app’s audio session—which immediately stops your audio. Interruptions happen when a competing audio session from an app is activated and that session is not categorized by the system to mix with yours.

相手のほうが強いという前提なので、自分がバックグラウンドで相手がフォアグラウンドと解釈できる。相手のmixWithOthersによって自分の対応が変わる。また自分のmixWithOthersに関する記述がなく、自分のmixWithOthersがONでも消されてしまうのでF説。

Table B-1 Audio Session category behavior

https://developer.apple.com/library/archive/documentation/Audio/Conceptual/AudioSessionProgrammingGuide/AudioSessionCategoriesandModes/AudioSessionCategoriesandModes.html#//apple_ref/doc/uid/TP40007875-CH10-SW1

ここにはオーディオセッションの各カテゴリの性質の表がある。playbackのところの「切り替えるスイッチ」というのがおそらくmixWithOthersのこと。でその項目をみると

Interrupts nonmixable app’s audio

とある。interruptという言葉を使っているのでフォアグラウンド側の視点であるが、相手のことをnonmixableと言っていて、F説にならない。
Interrupts other app’s audio ならF説だが、中断する相手をnonmixableに限定すると言っていて、相手のmixWithOthers(など)も関係すると解釈できるのでOR説。

AVAudioSessionCategoryOptionMixWithOthers の公式説明

https://developer.apple.com/documentation/avfaudio/avaudiosessioncategoryoptions/avaudiosessioncategoryoptionmixwithothers

An option that indicates whether audio from this session mixes with audio from active sessions in other audio apps.

フォアグラウンド/バックグラウンドの記述がないのでシンプルにOR説と解釈できる。ちなみにactiveはフォアグラウンドの意味ではなくて、バックグラウンドでも(再生できる設定なら)オーディオセッションはactiveだろうから、activeは何の根拠にもならないと思う。

ソースコードでmixWithOthersの定義を見に行ったところ

@var AVAudioSessionCategoryOptionMixWithOthers
    Controls whether other active audio apps will be interrupted or mixed with when your app's
    audio session goes active. Details depend on the category.
    AVAudioSessionCategoryPlayAndRecord or AVAudioSessionCategoryMultiRoute:
         MixWithOthers defaults to false, but can be set to true, allowing other applications to
         play in the background while your app has both audio input and output enabled.
    AVAudioSessionCategoryPlayback:
         MixWithOthers defaults to false, but can be set to true, allowing other applications to
         play in the background. Your app will still be able to play regardless of the setting
         of the ringer switch.
    Other categories:
         MixWithOthers defaults to false and cannot be changed.
    MixWithOthers is only valid with AVAudioSessionCategoryPlayAndRecord,
    AVAudioSessionCategoryPlayback, and AVAudioSessionCategoryMultiRoute.

(原文ママ)

名前が AVAudioSessionCategoryOptionMixWithOthers となっているのでObjective-C時代からのコピペでここまで生きてきたのではないか、 創業者の想いが反映されているのではないか と勝手な期待ができる。

これはF説の解釈が出来る。
your app's audio session goes activeのときotherがbe interruptedとある。is activeではなくてgoes activeなのでフォアグラウンドの挙動と読めるし、他のものがbe interruptedといっているのでF説。
また、AVAudioSessionCategoryPlaybackの説明で、mixWithOthersがONのときはallowing other applications to play in the backgroundと、はっきりbackgroundと書いてあるのでやはりF説。

まとめ

F説のほうはちゃんとストーリー性のある説明であった。本当はF説では?
OR説の資料は、現状がOR説の挙動になっているので仕方なくそれに合わせて資料を作成した可能性がある。

================

Appleに問い合わせ

開発者向けの質問機能でAppleに問い合わせた

Q

When the app in the foreground has mixWithOthers OFF and the app in the background has mixWithOthers ON, the app in the background says "my sounds are fine to coexist" and keeps playing sound. Is this Apple's intended behavior?

A

Yes, mixWithOthers basically means prefers not to be interrupted when another audio session activates. Instead of being interrupted, it mixes with other audio sessions.

iPadの2画面での検証

また、iPadの2画面で検証したらどうなるんだろうと思ったのでやってみた。

アプリA: .playback、mixWithOthersあり
アプリB: .playback、mixWithOthersなし

でアプリAとアプリBを左右に表示して

  • アプリAで再生してからアプリBを再生
  • アプリBで再生してからアプリAを再生

をやってみたが、やはり、両方のアプリの音が共存する。

Discussion