NAudioを使ってIEEE Floatの音声データをAudio Clipに変換する【Unity】【NAudio】

概要

KoeiromapをUnity(WebGL)やStreamで使用するために、NAudioを使って変k何処理を行います。

APIから返ってくるデータフォーマットは以下になります。

KoeiromapをUnityで使用できるライブラリ「Koeiromap-Unity」を公開しています

github.com

はじめに

以下の記事で APIからUnityのAudio Clipに変換する処理を書いていますが、一時的にファイルに保存しているため、ファイルにアクセスができないWebGLでは使用できません。
そのため、Streamで再生するための変換処理が必要でした。今回はStreamで再生するためにNAudioを使って実装を行いました

ayousanz.hatenadiary.jp

デモ

以下のように動きます

ayutaz.github.io

環境

  • Unity 2021.3.16f1
  • NAudio Core 2.1.0

NAudioのインストール

  1. nugetのNAudio.Core の Download package から .nupkgをダウンロードしてきます。
  2. 拡張子を .zipに変更して解答します
  3. 解答したフォルダの naudio.core.2.1.0\lib\netstandard2.0\NAudio.Core.dll にある dllをUnityにインポートします

base64エンコードされた文字列からAudio Clipを作成

AudioClipを作成する処理の流れは以下です。

  1. base64エンコードされた文字列からbyte配列に変換
  2. byte配列から MemoryStreamに変換
  3. MemoryStreamからAudioClipに変換

base64エンコードされた文字列からbyte配列に変換

Convert.FromBase64String(string data) で変換を行います。

learn.microsoft.com

byte配列から MemoryStreamに変換

        private static MemoryStream ConvertByteArrayToMemoryStream(byte[] wavData)
        {
            if (wavData == null) throw new ArgumentNullException(nameof(wavData));

            // WAVデータをメモリストリームにコピー
            var memoryStream = new MemoryStream(wavData);

            // ストリームの位置をリセット
            memoryStream.Seek(0, SeekOrigin.Begin);

            return memoryStream;
        }

learn.microsoft.com

MemoryStreamからAudioClipに変換

private static AudioClip ConvertMemoryStreamToAudioClip(MemoryStream memoryStream)
        {
            if (memoryStream == null) throw new ArgumentNullException(nameof(memoryStream));

            // NAudioライブラリを使用して、WAVデータを読み込みます
            using var reader = new WaveFileReader(memoryStream);
            if (reader.WaveFormat.Encoding != WaveFormatEncoding.IeeeFloat)
                throw new InvalidOperationException("Only IEEE Float format is supported.");

            var channels = reader.WaveFormat.Channels;
            var sampleRate = reader.WaveFormat.SampleRate;
            var sampleCount = reader.Length / (sizeof(float) * channels);
            var samples = new float[sampleCount];

            for (var i = 0; i < sampleCount; i++)
            for (var j = 0; j < channels; j++)
            {
                var sample = reader.ReadNextSampleFrame()[j];
                samples[i * channels + j] = sample;
            }

            // AudioClipの作成
            var audioClip = AudioClip.Create("ConvertedClip", (int)sampleCount / channels, channels, sampleRate,
                false);
            audioClip.SetData(samples, 0);

            return audioClip;
        }

github.com