LoginSignup
9
5

More than 3 years have passed since last update.

アーカイブ化したmp3をデコードしよう【Unity】

Last updated at Posted at 2019-04-15

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));
  }

できあがり。

9
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
5