create AudioClip from byte[] in Unity

Dear all,

I have problem. I am sending wav file from one unity project to another. I get sound from it in byte[ ]. Then convert byte[ ] to float[ ]:

Sender Code:

AudioBytes = File.ReadAllBytes(@"C:\Users\vishav3\Desktop\recordedWav\Send.wav");
            mySocket.GetStream().Write(AudioBytes, 0, AudioBytes.Length);

Reciever Code:

void Connection()
    {
        Debug.Log("connection");
        List<byte> bigbuffer = new List<byte>();

        byte[] tempbuffer = new byte[1024];
        NetworkStream stream = client.GetStream();

        while (stream.Read(tempbuffer, 0, tempbuffer.Length) > 0)
        {
            bigbuffer.AddRange(tempbuffer);
            Debug.Log("Read");
            if (!stream.DataAvailable)
            {
                break;
            }
        }

        // now you can convert to a native byte array
        byte[] completedbuffer = new byte[bigbuffer.Count];

        bigbuffer.CopyTo(completedbuffer);

        //Do something with the data
        //string decodedmsg = Encoding.ASCII.GetString(completedbuffer);
        Debug.Log("length" + completedbuffer.Length);
        float_msg = ConvertByteToFloat(completedbuffer);
        PlayOnce = true;

    }

Conversion from Byte to Float:

private float[] ConvertByteToFloat(byte[] array)
            {
                float[] floatArr = new float[array.Length / 4];
                for (int i = 0; i < floatArr.Length; i++)
                {
                    if (BitConverter.IsLittleEndian)
                        Array.Reverse(array, i * 4, 4);
                    floatArr[i] = BitConverter.ToSingle(array, i*4) / 0x80000000;
                }
                return floatArr;
            }


            float[] f = ConvertByteToFloat(bytes);

Then create AudioClip:

clip = AudioClip.Create("ClipName", float_msg.Length, channels, sampleRate, false);
            clip.SetData(float_msg, 0);
            audioSource.clip = clip;
            audioSource.Play();
            PlayOnce = false;

But playing sound is complete noise. Where i am doing it wrong? Any kind of suggestions would be helpful.

If you check the documentation, AudioClip.SetData expects the audio samples, but when you do File.ReadAllBytes, you take the header and the audio samples. It is potentially why you hear noises. You can use AudioClip.GetData to get the samples from an AudioClip. Be sure to have the correct sample rate and channels count, or else you will still hear noises.

@The_Island Thanks for the response… but i am hearing nothing when i am using AudioClip.GetData.

I made a script creating an AudioClip from GetData. Can you make sure this works in your project? If this works then, the issue is probably in the code sending the data.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class StreamAudioTest : MonoBehaviour
{
    public AudioSource receiverSource;

    public AudioClip clip;

    // Start is called before the first frame update
    void Start()
    {
        int channels = clip.channels;
        int frequency = clip.frequency;
        float[] samples = new float[clip.samples * clip.channels];
        clip.GetData(samples, 0);

        CreateAndPlay(samples, channels, frequency);
    }

    void CreateAndPlay(float[] samples, int channels, int frequency)
    {
        var clip = AudioClip.Create("ClipName", samples.Length, channels, frequency, false);
        clip.SetData(samples, 0);
        receiverSource.clip = clip;
        receiverSource.Play();
    }
}

If not, when you check the array from AudioClip.GetData, does the array has other value than zero? If yes, did you try setting Decompress on load in the importer like the note mentioned?

@The_Island I am getting all zeros in the array. Why?

Did you try to set Decompress on load in the importer? Otherwise, can you share the file either here or message me directly?

I checked the audio file and it seems ok.

I thought you had the audio file imported in the sender project, but it is not the case from what I understand. Do you need to play the file while streaming? Is it an issue to download it and play it after? We don’t support importing or streaming an audio file at runtime, but if you are doing this in the Editor only and can wait for the complete file, you can use AssetDatabase.ImportAsset. Even though we don’t support this out of the box, it doesn’t mean you can’t do this yourself. You need to get the PCM data from your file. You can search around for a WAV parser to get the audio samples and feed them to the AudioClip using SetData. If your audio was compressed, you would need to decompress it, but it is not your case. So you can focus on the parser, and you should be fine.

Endian safe solution:

private float[] ConvertByteToFloat(byte[] array)
{
   float[] floatArr = new float[array.Length / 4];
   for (int i = 0; i < floatArr.Length; i++)
   {
       if (BitConverter.IsLittleEndian)
           Array.Reverse(array, i * 4, 4);
       floatArr[i] = BitConverter.ToSingle(array, i*4) / 0x80000000;
   }
   return floatArr;
}


private byte[] ConvertFloatToByte(float[] array)
{
   byte[] byteArr = new byte[array.Length * 4];
   for (int i = 0; i < array.Length; i++)
   {
       var bytes = BitConverter.GetBytes(array[i] * 0x80000000);
       Array.Copy(bytes, 0, byteArr, i * 4, bytes.Length);
       if (BitConverter.IsLittleEndian)
           Array.Reverse(byteArr, i * 4, 4);
   }
   return byteArr;
}