16ビットバイト配列をオーディオクリップデータに正しく変換する方法は?

Nov 26 2020

私はMediaFoundataionを使用しており、サウンドサンプルフレームをバイトからオーディオフロートデータに変換する必要があります。それを行うために、私はそのような方法を使用します(私はグーグルのどこかで見つけました):

    private static float[] Convert16BitByteArrayToAudioClipData(byte[] source, int headerOffset, int dataSize)
    {
        int wavSize = BitConverter.ToInt32(source, headerOffset);
        headerOffset += sizeof(int);
        Debug.AssertFormat(wavSize > 0 && wavSize == dataSize, "Failed to get valid 16-bit wav size: {0} from data bytes: {1} at offset: {2}", wavSize, dataSize, headerOffset);

        int x = sizeof(Int16); // block size = 2
        int convertedSize = wavSize / x;

        float[] data = new float[convertedSize];

        Int16 maxValue = Int16.MaxValue;
        int i = 0;

        while (i < convertedSize)
        {
            int offset = i * x + headerOffset;
            data[i] = (float)BitConverter.ToInt16(source, offset) / maxValue;
            ++i;
        }

        Debug.AssertFormat(data.Length == convertedSize, "AudioClip .wav data is wrong size: {0} == {1}", data.Length, convertedSize);

        return data;
    }

私はそれをこのように使用します:

...
byte[] source = ...; // lenght 43776

... = Convert16BitByteArrayToAudioClipData(source , 0, 0);
...

サイズ43776の配列を渡した結果、whileインデックスi = 21886オフセット値でループoffset = 43776が発生すると、この次のメソッドで例外が発生するため、このメソッドは正しく機能しないようです。

data[i] = (float)BitConverter.ToInt16(source /*43776*/, offset /*43776*/) / maxValue;

この値を同じにすることはできなかったためです。

質問は-この方法を修正する方法は?それとも誰かが代わりに何を使うべきかアドバイスすることができますか?

編集

    private static float[] Convert16BitByteArrayToAudioClipData(byte[] source)
    {
        float[] data = new float[source.Length];

        for (int i = 0; i < source.Length; i++)
        {
            data[i] = (float) source[i];
        }

        return data;
    }

回答

1 RomanR. Nov 26 2020 at 13:58

整数は-1 .. +1浮動小数点値になる必要があります

    private static float[] Convert16BitByteArrayToAudioClipData(byte[] source)
    {
        float[] data = new float[source.Length];

        for (int i = 0; i < source.Length; i++)
        {
            data[i] = ((float) source[i] / Int16.MaxValue); // <<---
        }

        return data;
    }
AlekseyTimoshchenko Dec 01 2020 at 13:54

最終的に私はそれをこのようにしました:

    public static float[] Convert16BitByteArrayToAudioClipData(byte[] source)
    {
        int x = sizeof(Int16); 
        int convertedSize = source.Length / x;
        float[] data = new float[convertedSize];
        Int16 maxValue = Int16.MaxValue;

        for (int i = 0; i < convertedSize; i++)
        {
            int offset = i * x;
            data[i] = (float)BitConverter.ToInt16(source, offset) / maxValue;
            ++i;
        }

        return data;
    }