public static bool TryReadWav(string filename, out AudioSampleData clip)
        {
            //Debug.Log($"Reading wav file {filename}");
            try
            {
                using (var fs = File.Open(filename, FileMode.Open))
                    using (var reader = new BinaryReader(fs))
                    {
                        var result = TryReadWav(reader, out clip);

                        if (result)
                        {
                            //Debug.Log($"Finished reading wav file {filename}");
                        }
                        else
                        {
                            Debug.LogError("Failed to load wav: " + filename);
                        }

                        return(result);
                    }
            }
            catch (Exception e)
            {
                Debug.LogError("Failed to load wav: " + filename);
                Debug.LogException(e);
                clip = default;
                return(false);
            }
        }
 public static void WriteWav(AudioSampleData data, string path)
 {
     using (var stream = File.Open(path, FileMode.CreateNew))
         using (var writer = new BinaryWriter(stream))
         {
             WriteWav(writer, data);
         }
 }
 public static bool TryReadWav(byte[] data, out AudioSampleData clip)
 {
     using (var stream = new MemoryStream(data))
         using (var reader = new BinaryReader(stream))
         {
             return(TryReadWav(reader, out clip));
         }
 }
        public static void WriteWav(BinaryWriter writer, AudioSampleData clip)
        {
            var       bytes      = clip.ToByteArray();
            const int sampleSize = sizeof(float);

            writer.Write(Encoding.ASCII.GetBytes("RIFF"));
            writer.Write(36 + bytes.Length);
            writer.Write(Encoding.ASCII.GetBytes("WAVE"));

            writer.Write(Encoding.ASCII.GetBytes("fmt "));
            writer.Write(16);
            writer.Write((short)3);
            writer.Write((short)clip.channels);
            writer.Write(clip.frequency);
            writer.Write(clip.frequency * clip.channels * sampleSize);
            writer.Write((short)(clip.channels * sampleSize));
            writer.Write((short)(sampleSize * 8));

            writer.Write(Encoding.ASCII.GetBytes("data"));
            writer.Write(bytes.Length);
            writer.Write(bytes);
        }
        private static bool TryReadWav(BinaryReader reader, out AudioSampleData clip)
        {
            // chunk 0
            if (reader.ReadByte() != 'R' ||
                reader.ReadByte() != 'I' ||
                reader.ReadByte() != 'F' ||
                reader.ReadByte() != 'F')
            {
                Debug.Log("chunkId != RIFF");
                clip = default;
                return(false);
            }

            var fileSize = reader.ReadInt32();

            if (reader.ReadByte() != 'W' ||
                reader.ReadByte() != 'A' ||
                reader.ReadByte() != 'V' ||
                reader.ReadByte() != 'E')
            {
                Debug.Log("riffType != WAVE");
                clip = default;
                return(false);
            }

            while (reader.ReadByte() != 'f' ||
                   reader.ReadByte() != 'm' ||
                   reader.ReadByte() != 't' ||
                   reader.ReadByte() != ' ')
            {
                // search for 'fmt '
            }

            var fmtSize = reader.ReadInt32(); // bytes for this chunk

            var fmtCode = reader.ReadInt16();

            switch (fmtCode)
            {
            case 0:
                Debug.LogWarning($"fmtCode = {fmtCode} (UNKNOWN)");
                break;

            case 1:
                break;

            default:
                Debug.LogError($"fmtCode = {fmtCode}");
                clip = default;
                return(false);
            }

            int channels      = reader.ReadInt16();
            var sampleRate    = reader.ReadInt32();
            var byteRate      = reader.ReadInt32();
            int fmtBlockAlign = reader.ReadInt16();
            int bitDepth      = reader.ReadInt16();

            switch (fmtSize)
            {
            case 16:
                break;

            case 18:
                // Read any extra values
                var extra18 = reader.ReadBytes(reader.ReadInt16());
                break;

            case 28:
                var extra28 = reader.ReadBytes(reader.ReadInt16());
                break;

            default:
                Debug.LogError($"fmtSize = {fmtSize}");
                clip = default;
                return(false);
            }

            // chunk 2
            while (reader.ReadByte() != 'd' ||
                   reader.ReadByte() != 'a' ||
                   reader.ReadByte() != 't' ||
                   reader.ReadByte() != 'a')
            {
                // search for 'data'
            }

            var bytes = reader.ReadInt32();

            // DATA!
            var byteArray = reader.ReadBytes(bytes);

            float[] asFloat;
            switch (bitDepth)
            {
            case 64:
                var asDouble = new double[bytes / 8];
                Buffer.BlockCopy(
                    byteArray,
                    0,
                    asDouble,
                    0,
                    bytes
                    );
                asFloat = Array.ConvertAll(asDouble, e => (float)e);
                break;

            case 32:
                asFloat = new float[bytes / 4];
                Buffer.BlockCopy(
                    byteArray,
                    0,
                    asFloat,
                    0,
                    bytes
                    );
                break;

            case 16:
                var asInt16 = new short[bytes / 2];
                Buffer.BlockCopy(
                    byteArray,
                    0,
                    asInt16,
                    0,
                    bytes
                    );
                asFloat = Array.ConvertAll(asInt16, e => e / (float)short.MaxValue);
                break;

            default:
                Debug.LogError($"Unsupported bit depth: {bitDepth}");
                clip = default;
                return(false);
            }

            var data = new NativeArray <float>(asFloat, Allocator.Temp);

            clip = new AudioSampleData(
                channels,
                bitDepth,
                sampleRate,
                data
                );
            return(true);
        }