public void InitWave(string waveFile)
        {
            RiffTags riff = new RiffTags(waveFile);

            if (riff.FileType != "WAVE")
            {
                throw new Exception("Input is not a WAVE file!");
            }

            WaveFmt fmt = WaveFmt.Read(riff["fmt "].Data);

            if (fmt.Format != 1)
            {
                throw new Exception("Input is not PCM format!");
            }
            if (fmt.Channels != 2)
            {
                throw new Exception("Input does not have 2 channels!");
            }
            if (fmt.BitsPerSample != 16)
            {
                throw new Exception("Input does not have 16 bits per sample!");
            }
            //if (fmt.SampleRate > 4000)
            //	throw new Exception("Sample rate must be 4000Hz or less!");

            byte[]  data    = riff["data"].Data;
            short[] samples = new short[data.Length / 2];
            Buffer.BlockCopy(data, 0, samples, 0, data.Length);

            renderer.Samples = samples;

            WaveFile = waveFile;
            Samples  = samples;
            Duration = TimeSpan.FromSeconds(data.Length / ((fmt.BitsPerSample * fmt.Channels * fmt.SampleRate) / 8d));
        }
        public static bool LoadWAV(string fileName, out byte[] pcm, out SDL_AudioSpec spec)
        {
            pcm  = new byte[0];
            spec = new SDL_AudioSpec();

            byte[] bytes   = File.ReadAllBytes(fileName);
            int    pointer = 0;

            WaveHeader header = bytes.Consume <WaveHeader>(ref pointer);

            if (header.RiffId != WaveId_RIFF)
            {
                return(false);
            }
            if (header.WaveId != WaveId_WAVE)
            {
                return(false);
            }

            while (pointer < bytes.Length)
            {
                WaveChunkHeader chunkHeader = bytes.Consume <WaveChunkHeader>(ref pointer);

                if (chunkHeader.Id == WaveId_fmt)
                {
                    WaveFmt fmt = bytes.ReadStruct <WaveFmt>(pointer);
                    spec = new SDL_AudioSpec()
                    {
                        freq     = (int)fmt.SampleRate,
                        channels = (byte)fmt.Channels,
                    };

                    if (fmt.FormatTag != 1)
                    {
                        return(false);
                    }

                    switch (fmt.BitsPerSample)
                    {
                    case 8: {
                        spec.format = AUDIO_U8;
                    } break;

                    case 16: {
                        spec.format = AUDIO_S16LSB;
                    } break;
                    }
                    ;
                }
                else if (chunkHeader.Id == WaveId_data)
                {
                    pcm = bytes.Subarray(pointer, (int)chunkHeader.Size);
                }

                pointer += (int)chunkHeader.Size;
            }

            if (spec.format == AUDIO_U8)
            {
                byte[] newPCM = new byte[pcm.Length * 2];
                for (int i = 0; i < pcm.Length; i++)
                {
                    short sample16 = (short)((pcm[i] - 0x80) << 8);
                    newPCM[i * 2 + 0] = (byte)(sample16 & 0xFF);
                    newPCM[i * 2 + 1] = (byte)(sample16 >> 8);
                }
                pcm         = newPCM;
                spec.format = AUDIO_S16LSB;
            }

            return(true);
        }