UnityでExoPlayerを使ってアンビソニック音声ファイルを再生したかったので、作ってみました。
Androidライブラリを作成
まずAndroid StudioでAndroidライブラリのプロジェクトを作り、以下のようなクラスを作成します。このクラスはExoPlayerのインスタンスを作ったりURIの読み込みをしたりするメソッドを提供します。
import android.content.Context;
import android.net.Uri;
import com.google.android.exoplayer2.DefaultRenderersFactory;
import com.google.android.exoplayer2.ExoPlayerFactory;
import com.google.android.exoplayer2.SimpleExoPlayer;
import com.google.android.exoplayer2.audio.AudioProcessor;
import com.google.android.exoplayer2.ext.gvr.GvrAudioProcessor;
import com.google.android.exoplayer2.source.ExtractorMediaSource;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
import com.google.android.exoplayer2.util.Util;
public class UnityExoPlayer {
private final GvrAudioProcessor audioProcessor = new GvrAudioProcessor();
private final SimpleExoPlayer player;
private final ExtractorMediaSource.Factory factory;
public UnityExoPlayer(Context context) {
final DefaultRenderersFactory renderersFactory = new DefaultRenderersFactory(context) {
@Override
protected AudioProcessor[] buildAudioProcessors() {
return new AudioProcessor[]{audioProcessor};
}
};
player = ExoPlayerFactory.newSimpleInstance(renderersFactory, new DefaultTrackSelector());
factory = new ExtractorMediaSource.Factory(new DefaultDataSourceFactory(context, Util.getUserAgent(context, "UnityExoPlayer")));
}
public void prepare(String uri) {
ExtractorMediaSource mediaSource = factory.createMediaSource(Uri.parse(uri));
player.prepare(mediaSource);
}
public void play() {
player.setPlayWhenReady(true);
}
public void pause() {
player.setPlayWhenReady(false);
}
public void stop() {
player.stop();
}
public void release() {
player.release();
}
public void updateOrientation(float w, float x, float y, float z) {
audioProcessor.updateOrientation(w, x, y, z);
}
}
このコードをコンパイルするためには以下のようなbuild.gradle
のdependenciesが必要です。
dependencies {
implementation 'com.google.android.exoplayer:exoplayer-core:2.8.1'
implementation 'com.google.vr:sdk-audio:1.150.0'
}
そしたらGradleのassemble
ビルドを動かしてaarファイルを作ります。
Unityプロジェクトへaarファイルを入れる
↑で作ったaarには、ExoPlayerとGVR Audioのクラスは含まれていないため、別途aarファイルを持ってきてUnityプロジェクトに入れます。aarは以下のリンク先からダウンロードできます。2018/06/15時点の最新版はそれぞれExoPlayerが2.8.1、GVR Audioは1.150.0です。
Unity側のクラスを作成
次に、↑のJavaクラスをC#から呼び出すためのラッパーを書きます。
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class UnityExoPlayer
{
private AndroidJavaObject javaInstance;
public UnityExoPlayer()
{
using (AndroidJavaClass javaUnityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
{
using (var currentActivity = javaUnityPlayer.GetStatic<AndroidJavaObject>("currentActivity"))
{
// ↓ここのクラス名はパッケージ名に合わせて書き換える
javaInstance = new AndroidJavaObject("com.niusounds.unityexoplayer.UnityExoPlayer", currentActivity);
}
}
}
public void Prepare(string uri)
{
javaInstance.Call("prepare", uri);
}
public void Play()
{
javaInstance.Call("play");
}
public void Pause()
{
javaInstance.Call("pause");
}
public void Stop()
{
javaInstance.Call("stop");
}
public void SetTexture(int texPtr)
{
javaInstance.Call("setTexture", texPtr);
}
public void Release()
{
javaInstance.Call("release");
}
public void UpdateOrientation(float w, float x, float y, float z)
{
javaInstance.Call("updateOrientation", w, x, y, z);
}
}
使う
ここまでできたら、UnityExoPlayer
クラスを使うことでExoPlayerを使った空間音響の再生ができるようになります。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ExoPlayerComponent : MonoBehaviour
{
private UnityExoPlayer player;
void Awake()
{
player = new UnityExoPlayer();
}
void Start()
{
player.Prepare("/path/to/audio");
player.Play();
}
void Update()
{
var orientation = Quaternion.Inverse(Camera.main.transform.rotation);
player.UpdateOrientation(orientation.w, orientation.x, orientation.y, orientation.z);
}
}
動画対応について
player.Prepare
に動画のURIを渡せば、アンビソニック音声付き動画の音声だけは再生できます。あとはUnityのテクスチャをどうにかしてExoPlayerに渡してUnityシーン中の球の表面に映像を出せればアンビソニック付き360動画の完全なプレイヤーが作れるのですが…どなたか挑戦した方がいたら教えてください。