AirPods Proの空間オーディオについての技術メモ
iOS 14と同時にAirPods Proの新しいファームウェアがリリースされ、空間オーディオと呼ばれる新機能が追加されて話題になっていますね。
今回は、空間オーディオの技術的な部分を学び、サンプルアプリを作って試してみました。
「空間オーディオ」とは
まず、Appleが言う「空間オーディオ」とはどういう機能なのか
1. 5.1ch / 7.1ch / Dolby Atomosなどのサラウンド音声の再生に対応
2. 頭の動きを追従して音像の位置をリアルタイムに変化させる「ダイナミック・ヘッドトラッキング」機能の追加
この2つを総称して「空間オーディオ」という言葉を使っているようです。
1. については、恐らくiPhone/iPad側でマルチチャンネルソースをリアルタイムに2chバイノーラル にエンコードしてAirPods Proにストリームしているのだと思われます。(この辺の詳しい技術仕様が見つけられず、、、)
2. については、AirPods Proにはジャイロセンサーが内臓されているので、それを使ってユーザーの頭の向きを推定し、音の空間的な定位を固定する、ということです。iOSデバイス側にもジャイロセンサーは搭載されているので、ディスプレイを動かしたとしてもディスプレイに対する頭の位置は計算できるので、常に音源定位は固定できる、ということですね。
このため、iOS14からCMHeadphoneMotionManagerというAirPods Proのジャイロセンサーの値が取得できるAPIが公開されています。このAPIは、CoreMotion上に実装されていて、swiftでは以下のような形でジャイロセンサーの値を取得することが出来ます。
import UIKit
import CoreMotion
class ViewController: UIViewController, CMHeadphoneMotionManagerDelegate {
var motionManager: CMHeadphoneMotionManager!
override func viewDidLoad() {
super.viewDidLoad()
motionManager = CMHeadphoneMotionManager()
motionManager.delegate = self
if !motionManager.isDeviceMotionAvailable { return }
motionManager.startDeviceMotionUpdates(to: OperationQueue.main, withHandler: { (motion, error) in
guard let motion = motion, error == nil else { return }
print("qx: \(motion.attitude.quaternion.x)")
print("qy : \(motion.attitude.quaternion.y)")
print("qz : \(motion.attitude.quaternion.z)")
print("qw : \(motion.attitude.quaternion.w)")
})
}
func headphoneMotionManagerDidConnect(_ manager: CMHeadphoneMotionManager) {
print("Headphone Connected")
}
func headphoneMotionManagerDidDisconnect(_ manager: CMHeadphoneMotionManager) {
print("Headphone Disconnected")
}
}
UnityのAudio Spatializerと組み合わせたテストアプリをつくってみる
この「空間オーディオ」、映画のようなマルチチャンネルフォーマットのオーディオ以外に何か活用方法はあるのかな、と考えた時に、今後、インタラクティブなARやVRなどの3Dアプリケーションと組み合わせて使うことはあり得そうだなと思いました。
そういった3Dアプリケーションの場合、自分としてはiOSネイティブよりもUnityなどのゲームエンジンで作る場合の方が多そうなので、Unityのオブジェクトベースのサラウンド機能と組み合わせた簡単なサンプルアプリを作ってみることにしました。
まず、AirPods Proのジャイロセンサーの値をUnity(C#)で使用するには、ネイティブプラグインを作る必要があるのですが、既に作っている方がいらっしゃったので、有り難く使用させていただきました。
今回は、空間に3Dパンニングされた複数の音源を配置し、AirPods Proのジャイロセンサーの値に応じて仮想の頭を動かして、空間上での聞こえ方をシミュレーションできる簡単なテストアプリをつくってみることにしました。
Oculus Audio Spatializer を使ってみる
Unityにはデフォルトで3Dパンナーが付いているので、それを使っても良いのですが、距離と方向による音量の減衰しかしていないようで、立体感はそこまで感じにくかったので、Oculusが提供しているSpatializerを使ってみることにしました。
ちなみに、UnityはAudio Spatializer SDKを提供し、サードパーティや個人が自由にSpatializerを作れるようにしてくれているので、多数のプラグインが存在するようです。(あまりこの辺詳しくなく、今後リサーチしたい)
Oculus Audio Spatializerの使い方としては、
1. Project Settings > AudioのSpatializer PluginをOculusSpatializerを選択
2. AudioSourceコンポーネントは通常通り使いつつ、同じオブジェクトにONSP Audio Sourceを追加
3. OculusSpatializerReflectionエフェクトを追加したMixerにAudioSourceを流し込み、反射や残響の設定を行う
基本的にはこれだけです。以下のサイトが分かりやすく、詳しかったです。
まとめ
今回、作成したテストアプリがこちらです。(手元のiPad Pro 11"でしかテストしてないので他のデバイスだと表示崩れなどあるかと思います。)
今回はとてもシンプルなテストでしたが、空間上の音源の定位を固定できる体験は面白く、サウンドを使ったナビゲーションアプリ?など、音を活用したアプリケーションは今後色々登場してきそうだなと思いました。
また、Oculus Audio Spatializerなど、Sparializerプラグイン周りのリサーチも改めてやると、サウンドの表現の可能性が広がりそうだなと感じました。