THETA Sの全天球配信を強化する(3) 3Dサウンドを再現したい
- WebRTC
- 2016/06/06
こんにちは、インフォコム技術企画室のがねこです。前回は3Dサウンドを配信するための自作ガジェットと、処理の仕組みを紹介しました。今回は3Dサウンドを受信して、それをVR映像と合わせて再生するまでの流れをご紹介します。
複数音声の受信
まずWebRTCの通信を行うPeerConnectionを経由して、ステレオ音声×4を受け取ります。残念ながら順不同(※もしかしたらルールがあるかもしれません)なので、人が聞きながらどの位置の音なのかを対応づけます。
各<audio>タグが、前後左右の音に対応しています。
4つのステレオサウンドの配置調整
4つのaudioタグの一つだけを鳴らしながら、それがどの位置の音を人間が聞き分けて、画面上でドラッグ&ドロップして並べ替えます。本当はこのような職人芸は不要にしたかったのですが、今回は間に合いませんでした。
ヘッドトラッキングに合わせた音量調整
Oculus Riftのヘッドトラキングを利用して人の顔の向きを取得し、向きに応じて各<audio>タグの音量を動的に調整します。例えば前後の場合は、対応する<audio>タグを1つだけ鳴らします。
同様に左右の場合も、対応する<audio>タグを1つだけ鳴らします。
そして斜めの場合(つまり、ほとんどの場合)は、対応する2つの<audio>タグの音量を調整して鳴らします。
実際の処理は次のようになっています。こちらもメンバーのtokさんが考案、実装してくれました。
// WebVR1.0 APIでHMDを取得する
var vrDisplay;
navigator.getVRDisplays().then(function (displays) {
if (displays.length === 0) {
console.log('WebVR API is NOT supported.');
return;
}
vrDisplay = displays[0];
console.log('WebVR API is supported!!!');
}).catch(function (err) {
console.error('Could not get VRDisplays', err.stack);
});
function animate() {
requestAnimationFrame( animate );
update();
}
function update() {
// WebVR1.0 APIでHMDが向いている方向を取得
var pose = vrDisplay.getPose();
var orientation = pose.orientation;
// クォータニオンからオイラー角へ変換
var euler = new THREE.Euler();
euler.setFromQuaternion(new THREE.Quaternion(orientation[0],orientation[1],orientation[2],orientation[3]), 'ZXY');
var yaw = euler.y * 180 / Math.PI;
updateVolumeByHMD(yaw);
// この後、HMDへの描画処理などが続く
}
function updateVolumeByHMD(yaw) {
// 水平角の値を調整
azimuth = yaw;
if(azimuth > 180) azimuth = 180;
else if(azimuth < -180) azimuth = -180;
// 角度別に、ボリュームバランスを調整
if(azimuth <= 0 && azimuth > -90) { /* 右前 */
var sectionAzimuth = -1 * azimuth;
var sectionMax = 90;
frontAudio.volume = (sectionMax - sectionAzimuth) / sectionMax;
backAudio.volume = 0;
leftAudio.volume = 0;
rightAudio.volume = sectionAzimuth / sectionMax;
} else if(azimuth <= -90 && azimuth >= -180) { /* 右後 */
var sectionAzimuth = -1 * (azimuth + 90);
var sectionMax = 90;
frontAudio.volume = 0;
backAudio.volume = sectionAzimuth / sectionMax;
leftAudio.volume = 0;
rightAudio.volume = (sectionMax - sectionAzimuth) / sectionMax;
} else if(azimuth > 90 && azimuth <= 180) { /* 左後 */
var sectionAzimuth = azimuth - 90;
var sectionMax = 90;
frontAudio.volume = 0;
backAudio.volume = sectionAzimuth / sectionMax;
leftAudio.volume = (sectionMax - sectionAzimuth) / sectionMax;
rightAudio.volume = 0;
} else if(azimuth > 0 && azimuth <= 90) { /* 左前 */
var sectionAzimuth = azimuth;
var sectionMax = 90;
frontAudio.volume = (sectionMax - sectionAzimuth) / sectionMax;
backAudio.volume = 0;
leftAudio.volume = sectionAzimuth / sectionMax;
rightAudio.volume = 0;
}
}
こうすることで、見ている映像と違和感のない3Dサウンドを視聴者に体験させることができます。
利用環境について
Chromium
ステレオサウンドを扱うためにChromeを利用していますが、ChromeでWebVRを扱うには安定板ではなく、 Chromium のWebVR機能を追加したビルドを利用する必要があります。今回利用したのはこちらになります。
- https://drive.google.com/folderview?id=0BzudLt22BqGRbW9WTHMtOWMzNjQ (chromiumwebvrv1_win64.7z)
- バージョンは Chromium(WebVR Build)は52.0.2715.0 でした
- chrome://flags の「#enable-webvr」を有効にして再起動する必要があります
three.js
WebGL + WebVRを手軽に扱うために、three.js を利用しています。
- https://github.com/mrdoob/three.js/
- 今回利用したのは r77 でした
最後に
今回ご紹介した3Dサウンド対応の全天球配信VRを、2016年6月8日~6月10日に行われる AppsJapanのWebRTCパビリオンに展示します。Interopに併設されるイベントですので、お越しの際にはぜひ体験してみてください。お待ちしています!
(自作の風鈴連続鳴らし器。会場で展示される、かもしれません)