#UnityでMP3をちょっとトリッキーに扱いたい
Unityくんは優秀なので、wwwで外部のサウンドファイルを指定すれば勝手にデコードしてオーディオクリップにしてくれます。
しかし……
「スタンドアロン(パソコン)でもMP3使いたいな~」とか
「アーカイブ化したファイルから読み込ませたいんだよね」とか
Unityくんは、そんな隙間ニーズには対応してくれていないのです。
(MP3はこないだまで有料規格だったしね……色々あるんだろうね)
という訳で、自力でどうにかしましょう。
#Windows用アプリケーションを作る場合
NAudioという偉大なモノがあるので楽勝ですね。
先達たちに感謝。
https://github.com/naudio/NAudio
https://so-zou.jp/software/tech/programming/c-sharp/media/audio/naudio/
#Windows用アプリケーションではない場合
NAudio! おまえはクロスプラットフォームではないのだね……。
https://github.com/naudio/NAudio/issues/184
https://stackoverflow.com/questions/6186559/will-naudio-support-mac-osx
ということで、私はC#で書かれたプラットフォームに依存しないMP3デコーダーの情報を探してネットの海を彷徨うことになりました。
※しかし、全然情報なくてビックリだね。同じニーズは割とあると思うんだけど、検索しても日本語の情報はゼロ、英語でも検索からは全然情報が見つからず。わざわざ同じ苦労する人がいないように記事書いてます。
そして、最終的に辿り着いたのがコイツ。
https://github.com/naudio/NLayer
コイツをNAudioと一緒に使いましょう。まぁ、NAudioの説明をよく読んでれば探し回る必要もなかったんだけど……。
https://github.com/naudio/NAudio/blob/master/Docs/ConvertMp3ToWav.md
NLayer is a fully managed MP3 decoder, meaning it can run on any version of Windows (or indeed any .NET platform).
……ちゃんと書いてたね。NLayerを使えば『.NETが使える環境なら何でもいける(or indeed any .NET platform)』って。見落としてました。.NET(Mono)はクロスプラットフォームなので、この組み合わせで動きます。
情報捜索で潰れた私の土曜日は何だったんや……。
#具体的な手順
1 NAudioとNLayerの関数を使えるようにしよう
NAudioとNLayerをGitHubから[Clone or download]→[Download ZIP]でダウンロード。ZIPを解凍したら中身をそのままプロジェクトのAssetフォルダ内のどこかにどーん。(もちろん常識的な人はAssetフォルダ内にScriptフォルダを作ってるだろうから、整理整頓のためにもその中に入れよう)。これでNAudioやNLayerの名前空間を呼び出せばいつでも使えるようになった!
※この手のC#ソースを複数使ってるとソースごとのAssemblyInfo.csとかの記述が二重に被ってエラー出たりするので、消しておきましょう。(AssemblyInfoについて調べると分かると思いますが、基本的に動作には直接影響しないので消して大丈夫です)
2 関数を使ってデコードしよう!
mp3形式のStreamをwav形式のbyte配列に変換する関数
private byte[] Mp3ToWav(Stream st)
{
using (MemoryStream ms = new MemoryStream())
{
using (var reader = new NAudio.Wave.Mp3FileReader(st, wf => new NLayer.NAudioSupport.Mp3FrameDecompressor(wf)))
{
if (reader.WaveFormat.Encoding == NAudio.Wave.WaveFormatEncoding.IeeeFloat)
{
NAudio.Wave.WaveFloatTo16Provider w32to16 = new NAudio.Wave.WaveFloatTo16Provider(reader);
byte[] tmp=new byte[10000];
w32to16.Read(tmp,0,10000);
NAudio.Wave.WaveFileWriter.WriteWavFileToStream(ms, w32to16);
}
if (reader.WaveFormat.Encoding == NAudio.Wave.WaveFormatEncoding.Pcm)
{
NAudio.Wave.WaveFileWriter.WriteWavFileToStream(ms, reader);
}
}
return ms.ToArray();
}
}
……せや、wavのbyte配列をAudioClipにする方法説明してなかった。
https://github.com/deadlyfingers/UnityWav
コイツを使いましょう。例の如く(手順1を参照)AssetフォルダにDLしたファイルをぶち込めばOK。
で、上の関数とUnityWavを組み合わせて
mp3ファイルのStreamをAudioClipに変換する関数
public AudioClip Mp3ToAudioClip(Stream st)
{
return WavUtility.ToAudioClip (Mp3ToWav(stream));
}
できあがり。