iOS AVAudioSession周りの覚書
音声 x 外部ヘッドセット周りで嵌ったのでメモメモ。φ(・・
基礎知識
44,100 Hz
デジタルオーディオにおける一般的なサンプリング周波数。アナログオーディオは一秒間に441000回標本化される。
ハード側
iPhoneのスピーカー
- 通話用スピーカー
- 上についているやつ
- 内蔵スピーカー
- 右側がスピーカー、左側がマイク
BluetoothHFPとは
Bluetooth Hands-Free Profile の略。
携帯電話 - ヘッドセット間などで用いられる、電話の発着信や通話を行なうためのプロファイル。
アプリケーション側
AVAudioSessionとは?
OS(及びハードウェア)とアプリケーションの仲介を行うオブジェクト。
デフォルトでは以下の設定がされている。
- 再生はサポートされているが、録音はサポートされていない
- マナーモードにするとアプリで再生されている音はすべて無音になる (iOSのみ)
- デバイスがロックされたら音が止まる (iOSのみ)
- アプリがオーディオを再生し始めたらバックグラウンドで流れている音楽を止める
デフォルトの振る舞いを変更するには audio session category を変更する必要がある。
Audio Session Category とは?
オーディオの振る舞いを定義する Audio Session プロパティ。
playback(再生)だけとか、record(録音)だけとか、 playAndRecord(再生と録音)とか。
さらにsession modeを設定することで、より洗練した音質を提供できる。
Audio Session Mode
category がベースとなる振る舞いを設定するのに対して、 mode は専門的にするために使うカテゴリーの振る舞いを専門化できる。 例えば videoChat は playAndRecord, recod カテゴリといっしょにつかい、音声に対するトーンイコライザの最適化を提供する。また許容されるオーディオルートをビデオチャットに適したものだけに削減する。
※オーディオルート => どこから音を出すかとか、ヘッドフォンとかBluetoothとか。
- Audio Session Modes | Apple Developer Documentation
- videoChat - AVAudioSession.Mode | Apple Developer Documentation
オーディオルートの変更を検知する
オーディオのアウトプットを外付けスピーカーからBluetoothに変えた場合などを検知する場合は AVAudioSessionRouteChangeNotification を利用すればよい。
(例) 内蔵スピーカーからBluetoothに変わったときの出力
let center = NotificationCenter.default center.addObserver(self, selector: #selector(didAudioSessionRouteChanged(_:)), name: AVAudioSession.routeChangeNotification, object: nil)
@objc func audioSessionRouteChanged(_ notification: Notification) { guard let userInfo = notification.userInfo, let reasonValue = userInfo[AVAudioSessionRouteChangeReasonKey] as? UInt, let reason = AVAudioSession.RouteChangeReason(rawValue:reasonValue) else { return } let session: AVAudioSession = AVAudioSession.sharedInstance() print(session.sampleRate) // Bluetoothにイヤフォンにした場合サンプルレートが変わってるはず switch reason { case .newDeviceAvailable: print("newDeviceAvailable") for output in session.currentRoute.outputs { print(output.portType) // BluetoothHFP print(output.portName) // 製品名 or AirPodsなら自分で登録した名前 } case .oldDeviceUnavailable: print("oldDeviceUnavailable") case .unknown: print("unkonw") case .categoryChange: print("categoryChange") case .override: print("override") case .wakeFromSleep: print("wakeFromSleep") case .noSuitableRouteForCategory: print("noSuitableRouteForCategory") case .routeConfigurationChange: print("routeConfigurationChange") @unknown default: print("default") } }
理解が浅い
- AVAudioSession.CategoryOptions