🎵

[Unity][iOS] iOSのミュージックライブラリの楽曲を再生し、オーディオビジュアライズする

2021/01/10に公開
2

iOSのミュージックライブラリの楽曲を再生し、オーディオビジュアライズするUnityプラグインを公開しました。

https://github.com/kkkkoyo/UnityMusicPlayerVisualizer

以前、withAR主催のストレッチwithARハッカソンに参加し、YouTuberのオガトレさんとコラボ。オガトレさんの人気シリーズである「太もも痩せ音ゲー」のARアプリ化に挑戦しました。
ユーザーの端末に入っている楽曲で音ゲーができるようにしようと、UnityからiOSのミュージックライブラリの楽曲を取得し、サウンドレベルに合わせて自動で譜面が生成されるような音ゲーのプロトタイプを作りました。
今回はこの音ゲーアプリの実装に使用したネイティブプラグインの部分を整理し、公開しました。

https://twitter.com/koyoarai_/status/1340552723154886663

環境

  • Unity2020.1.13f1
  • Xcode12.2

機能

MPMediaPickerControllerで曲を取得し、AVAudioPlayerでサウンドを再生、averagePowerForChannelでサウンドレベルを取得します。

  • 音楽ライブラリへのアクセス
  • 曲の再生/停止
  • 曲情報の取得

※AppleMusicなどのストリーミング音楽はサポートしていません。

実装

.
└── MusicPlayerVisualizer
    ├── Editor
    │   └── PostBuildProcess.cs
    ├── Plugins
    │   ├── MusicPlayerPlugin.cs
    │   └── iOS
    │       ├── MediaPlayer.framework
    │       ├── UnityMusicPlayerPlugin.h
    │       └── UnityMusicPlayerPlugin.mm
    │
    └── Sample
        ├── Sample.cs
        └── Sample.unity

UnityMusicPlayerPlugin.mm

asus4/UnityMusicPlayerPluginを参考に実装しました。こちらのプラグインではMPMusicPlayerControllerに読みこみ再生をしています。しかし、このクラスでは今回やりたいサウンドデータのアクセスはできない仕様になっています。
そこで、MPMediaItemからオーディオの端末内URLを取得し、一度ファイル書き出しをします。そのオーディオデータをAVAudioPlayerで再生をすることにより、サウンドレベルを取得しています。

サウンドレベルの取得に端末内URLの取得が必要になるため、URLの取得ができないAppleMusicなどのストリーミング音楽は非対応となっています。

参考 : iPodライブラリ内の曲をopenFrameworksで読み込んでサウンドレベルを取得する

MediaPlayer.framework

ビルドした際に毎回Xcode上でframeworkを追加しないで済むように、iOSフォルダ内に置いています。

参考 : Unity Xcodeビルド時に必要フレームワークを自動的にセットする

Sample.cs

MusicPlayerPluginクラスを呼び、楽曲情報の取得・再生・停止・楽曲終了時の取得を行っています。また、オーディオレベルを元にcubeのスケールをリアルタイムで動かしています。

        void SetInfo()
        {
            var player = MusicPlayerPlugin.Instance.info;
            string title = player.title;
            string artist = player.artist;
            double duration = player.duration;
            // ... 略
        }

        void Update()
        {
            double currentTime = MusicPlayerPlugin.Instance.currentTime;
            float level = MusicPlayerPlugin.Instance.level(0);
            // ... 略
            cube.transform.localScale = Vector3.one * level;
        }

        // 再生終了時に呼ばれる
        void EndOfPlayback()
        {
            Debug.Log("EndOfPlayback");
        }
        
        // 楽曲情報が更新された際に呼ばれる
        void OnPlayingItemChanged(MusicPlayer.Info info)
        {
            SetInfo();
        }

        // State(再生・停止・再生終了)が変更した際に呼ばれる
        void OnStateChanged(MusicPlayer.PlaybackState state)
        {
            SetInfo();
        }

        public void OnPlay()
        {
            // 再生
            MusicPlayerPlugin.Instance.Play();
        }

        public void OnLoad()
        {
            // ミュージックライブラリを開く
            MusicPlayerPlugin.Instance.Load();
        }

おわりに

このUnityMusicPlayerVisualizerを利用することでお手軽にUnityからiOSのミュージックライブラリの楽曲を再生し、オーディオビジュアライズをすることができます。ぜひご利用ください!

Twitter : https://twitter.com/koyoarai_

Discussion

bbbwbbbw

こんなプラグイン探してました! ありがとうございます!

使用中に、
UnityMusicPlayerPlugin.mmの225行目を
NSString *filePath = [NSString stringWithFormat:@"%@/%@.%@", docDirPath , fileType , ex];
にすると、AppleMusicの曲もダウンロードすれば再生可能になるのに気づきました

例外や影響はまだ調べてないんですが、一旦報告です。

koyoarai_koyoarai_

おおお、ありがとうございます!
試してみて問題なさそうだったら追加してみます🙌