目次
Session概要
ステレオ録音は、リスナー、ファン、ファミリーに没入感のあるサウンドを提供するパワフルな方法です。iPhoneまたはiPad上の内蔵マイクを使ってアプリで録音することができます。AVAudioSessionがモバイルデバイスからステレオオーディオを取り込むのにどう役立つかを紹介し、「インプットオリエンテーション」と呼ばれる新しい特別な考慮事項への対処の仕方、また、このAPIをアプリで活用して録音体験を向上する方法について https://developer.apple.com/videos/play/wwdc2020/10226/
AVAudioSessionの新機能
- アプリとシステムの通信やアプリ内での音声の使用方法、音声録音の設定が可能
- iOS 14, iPadOS 14からは内蔵マイクからステレオ音声を録音するオプションが追加
ステレオの利点
- 音の方向を判別可能
- 表現や芸術をより鮮明に伝えることが可能
- 臨場感の向上
新しいAPIの導入方法/inputOrientationについて


- AVAudioSessionのマイクとビーム選択の基本
- デバイスには複数のマイクがあるが、AVAudioSessionのAPI内ではマイクではなくデータソースを選んでいる
- つまり、仮想マイクで極性パターンを選択しており、全極性パターンから個々のマイクを入手するかカーディオイドビームフォーマーが選べる
- カーディオイドとは
- マイクロホンの指向性を表すパターンの一つで、マイク正面の音だけを強く拾う単一指向性のことを意味している
- マイクの指向性とは
- マイクがどの方向からの音を収音できるかという特性のこと
- ビームとは
- 収音の感度が最も高い方向のこと
- ビームフォーミング(ビームフォーマー)とは
- 複数のマイクロフォンを用いて、収音の指向性を制御する技術
- この辺はこちらの記事がわかりやすいです
- iPhoneのビームフォーミング
- デバイス上部の前面マイクで録音する場合、実際には前面と背面のマイクでより優れた方向応答性を得ている
- 音波が前から来たら背面マイクより先に前面マイクに到達するので、逆方向から来た場合より音波が大きくなる
- そのため、前方は音が大きく広報は音が小さいパターンが得られます
- もし、2つのマイクの役割を入れ替えると背面がサブカーディオイドになり逆方向の音をより広く拾えます
- このように音の方向に焦点をあわせる方法は
モノラル
です
- ステレオにする方法
- 全てのマイクから同時に録音して、特殊なモデリングプロセスで両耳のステレオ体験を実現させる
- 特別な処理を前方向に適用し、カーディオイドビームのように後方向よりも音を大きくします
- 上記を行うことで、左と右で異なる方向になり、前方方向は背面カメラの視線方向となります
- このデータソースは背面カメラでステレオ音声を録音する場合の選択です
- カーディオイド同様、逆方向にする場合は上部前面ステレオを選択します
- ユーザは様々な方向でデバイスを持つことができますが、横向きでは縦向きと同じ設定が使えません
- 上記問題を対応するために、それぞれの向きの中から希望の方向をシステムに設定するために再度モデリングプロセスを行います
- AVAudioSessionの新しいプロパティである
inputOrientation
が表示されます- 使用できる値は4方向で縦向きの上下、左の横向き、右の横向き、また2つの異なるデータソースがあるので合計8種類
- データソースの選択に基づきどの方向が前方かを選択
- 左右はinputOrientationプロパティによって決定されます
- ステレオの方向とデータソースを選択するとアプリのロジックを構築し、ユーザの要求と方向が一致するようにします
- これは、ステレオ極性パターンのみで、モノラルには入力方向に違いがありません
- アプリの種類による対応
- ビデオを録画するアプリなら入力方向を選択し、音声とビデオの左右が一致するようにします
- ビデオを録画しないアプリの場合はステレオの入力とUIの方向を合わせましょう
- ファイルの録音時、特にビデオファイルの場合は設定した方向を固定しておく必要があります


アプリの種類による対応
- ビデオを録画するアプリなら入力方向を選択し、音声とビデオの左右が一致するようにします
- ビデオを録画しないアプリの場合はステレオの入力とUIの方向を合わせましょう
- ファイルの録音時、特にビデオファイルの場合は録音中に方向が変わってしまうのを防ぐため、設定した方向を固定しておく必要があります
- 何れにせよ、エンドユーザー(特に視聴側)の要求を考えることが重要
アプリの音声の正しい方向とは
- デバイスの辺とマイクの位置に関係しているため、その関係性を知ることが重要
- まず、データソースを選択する時に前方を選びます
- 次にデータソースと入力方向の組み合わせから左と右がどちらの方向になるかを確認します
- また、使用する方向とデータソースごとにテストを行う必要がある
サンプルコード
Apple公式サンプルが公開されているので、こちらのサンプルも参照すると良いですCapturing Stereo Audio from Built-In Microphones
内蔵マイクからの録音
// How to set up recording from the built-in mic
private func enableBuiltInMic() {
...
// Find the built-in microphone.
// 内蔵マイクポートの検出
guard let availableInputs = session.availableInputs,
let builtInMic = availableInputs.first(where: { $0.portType == .builtInMic })
else {
print("The device must have a built-in microphone.")
return
}
...
do {
// 優先入力ポートとして設定
try session.setPreferredInput(builtInMic)
...
} catch {
...
}
}
// Configure stereo recording
// ステレオ極性パターンの選択
func selectDataSource(...) {
...
// Set the preferred polar pattern to stereo.
// ステレオ録音に対応するデバイスが表示されますが、対応するデバイスがない場合はバッファの動的な調整が必要
// 音声セッションを有効にし、入力チャンネルカウントを確認する
try newDataSource.setPreferredPolarPattern(.stereo)
// Set the preferred data source and polar pattern.
// データソースの選択:音声を送りたい向きに焦点を合わせて前方または後方を選ぶ
try preferredInput.setPreferredDataSource(newDataSource)
// Update the input orientation to match the current user interface orientation.
// 他のアプリがルーティングを制御している場合は、呼び出したプロパティが `PreferredinputOrientation` となっている
try session.setPreferredInputOrientation(orientation.inputOrientation)
...
}
入力方向を設定するタイミング
- ビデオを録画する場合は、先に方向を設定する
- 下記のサンプルアプリはビデオの録画をしないのでUIの回転に合わせる
- ユーザがカメラなどを選択していれば、それに基づいた焦点設定も可能
// When to select a data source & updated the stereo input orientation
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
updateDataSource()
}
@IBAction func updateDataSourceSelection(_ sender: Any) {
updateDataSource()
}
private func updateDataSource() {
// Don't update the data source if the app is currently recording.
// 録画する場合は、この段階で入力方向やデータソースを変えるべきではありません
guard controller.state != .recording else { return }
let dataSourceName = dataSources[dataSourceChooser.selectedSegmentIndex]
controller.selectDataSource( named: dataSourceName,
orientation:Orientation(windowOrientation)) { layout in
self.layoutView.layout = layout
}
}