Exemple #1
0
        public static ISound ReadFromData(byte[] data, SoundType soundType)
        {
            switch (soundType)
            {
            case SoundType.Wav:
                return(WavSound.GetWavSound(data));

            case SoundType.Mp3:
                return(null);

            default:
                return(null);
            }
        }
Exemple #2
0
        public static ISound ReadFromFile(string path)
        {
            if (!File.Exists(path))
            {
                throw new FileNotFoundException($@"{path}: No such file or Directory");
            }


            var fileExtension = Path.GetExtension(path);

            if (!AcceptedFormats.Contains(fileExtension))             // TODO: Check through other way using Linux Style :)
            {
                throw new Exception($@"{path}: Format not accepted"); // TODO: Define new type of exception
            }
            var bytes = File.ReadAllBytes(path);

            switch (fileExtension)
            {
            case ".wav":
                return(WavSound.GetWavSound(bytes));

            case ".mp3":
                var sound2 = new Mp3Sound();

                // TODO: ID3v2

                //ID3v1
                if (Encoding.UTF8.GetString(bytes.Slice(0, 3)) != "ID3")
                {
                    var headerBits = bytes.Slice(0, 4).ToBitsArray();

                    /*var frameSync = headerBits.Take(11).ToList();
                     * if (frameSync.Sum() != frameSync.Count)
                     *  throw new Exception("Invalid MP3 file");*/

                    var mpegVersion = headerBits.Skip(11).Take(2).ToList();
                    if (mpegVersion[0] == 0)
                    {
                        sound2.MpegVersion = mpegVersion[1] == 0 ? MpegVersion.Mpeg25 : MpegVersion.Reserved;
                    }
                    else
                    {
                        sound2.MpegVersion = mpegVersion[1] == 0 ? MpegVersion.Mpeg2 : MpegVersion.Mpeg1;
                    }

                    var layerType = headerBits.Skip(13).Take(2).ToList();
                    if (layerType[0] == 0)
                    {
                        sound2.LayerType = layerType[1] == 0 ? LayerType.Reserved : LayerType.Layer3;
                    }
                    else
                    {
                        sound2.LayerType = layerType[1] == 0 ? LayerType.Layer2 : LayerType.Layer1;
                    }

                    var protectionBit = headerBits.Skip(15).Take(1).ToList()[0];
                    sound2.Protection = protectionBit == 0;

                    var bitRateBits = headerBits.Skip(16).Take(4).ToList();

                    switch (bitRateBits)
                    {
                    case var _ when bitRateBits.IsEqualTo(new List <int> {
                            0, 0, 0, 0
                        }):
                        sound2.BitRateIndex = 0;

                        break;

                    case var _ when bitRateBits.IsEqualTo(new List <int> {
                            0, 0, 0, 1
                        }):
                        if ((sound2.MpegVersion == MpegVersion.Mpeg2 || sound2.MpegVersion == MpegVersion.Mpeg25) &&
                            (sound2.LayerType == LayerType.Layer2 || sound2.LayerType == LayerType.Layer3))
                        {
                            sound2.BitRateIndex = 8;
                        }
                        else
                        {
                            sound2.BitRateIndex = 32;
                        }
                        break;

                    case var _ when bitRateBits.IsEqualTo(new List <int> {
                            0, 0, 1, 0
                        }):
                        switch (sound2.LayerType)
                        {
                        case LayerType.Layer1:
                            sound2.BitRateIndex = sound2.MpegVersion == MpegVersion.Mpeg1 ? 64 : 48;
                            break;

                        case LayerType.Layer2:
                            sound2.BitRateIndex = sound2.MpegVersion == MpegVersion.Mpeg1 ? 48 : 16;
                            break;

                        case LayerType.Layer3:
                            sound2.BitRateIndex = sound2.MpegVersion == MpegVersion.Mpeg1 ? 40 : 16;
                            break;

                        case LayerType.Reserved:
                            break;

                        default:
                            throw new ArgumentOutOfRangeException();
                        }

                        break;

                    case var _ when bitRateBits.IsEqualTo(new List <int> {
                            0, 0, 1, 1
                        }):
                        switch (sound2.LayerType)
                        {
                        case LayerType.Layer1:
                            sound2.BitRateIndex = sound2.MpegVersion == MpegVersion.Mpeg1 ? 96 : 56;
                            break;

                        case LayerType.Layer2:
                            sound2.BitRateIndex = sound2.MpegVersion == MpegVersion.Mpeg1 ? 56 : 24;
                            break;

                        case LayerType.Layer3:
                            sound2.BitRateIndex = sound2.MpegVersion == MpegVersion.Mpeg1 ? 48 : 24;
                            break;

                        case LayerType.Reserved:
                            break;

                        default:
                            throw new ArgumentOutOfRangeException();
                        }

                        break;

                    case var _ when bitRateBits.IsEqualTo(new List <int> {
                            0, 1, 0, 0
                        }):
                        switch (sound2.LayerType)
                        {
                        case LayerType.Layer1:
                            sound2.BitRateIndex = sound2.MpegVersion == MpegVersion.Mpeg1 ? 128 : 64;
                            break;

                        case LayerType.Layer2:
                            sound2.BitRateIndex = sound2.MpegVersion == MpegVersion.Mpeg1 ? 64 : 32;
                            break;

                        case LayerType.Layer3:
                            sound2.BitRateIndex = sound2.MpegVersion == MpegVersion.Mpeg1 ? 56 : 32;
                            break;

                        case LayerType.Reserved:
                            break;

                        default:
                            throw new ArgumentOutOfRangeException();
                        }

                        break;

                    case var _ when bitRateBits.IsEqualTo(new List <int> {
                            0, 1, 0, 1
                        }):
                        switch (sound2.LayerType)
                        {
                        case LayerType.Layer1:
                            sound2.BitRateIndex = sound2.MpegVersion == MpegVersion.Mpeg1 ? 160 : 80;
                            break;

                        case LayerType.Layer2:
                            sound2.BitRateIndex = sound2.MpegVersion == MpegVersion.Mpeg1 ? 80 : 40;
                            break;

                        case LayerType.Layer3:
                            sound2.BitRateIndex = sound2.MpegVersion == MpegVersion.Mpeg1 ? 64 : 40;
                            break;

                        case LayerType.Reserved:
                            break;

                        default:
                            throw new ArgumentOutOfRangeException();
                        }

                        break;

                    case var _ when bitRateBits.IsEqualTo(new List <int> {
                            0, 1, 1, 0
                        }):
                        switch (sound2.LayerType)
                        {
                        case LayerType.Layer1:
                            sound2.BitRateIndex = sound2.MpegVersion == MpegVersion.Mpeg1 ? 192 : 96;
                            break;

                        case LayerType.Layer2:
                            sound2.BitRateIndex = sound2.MpegVersion == MpegVersion.Mpeg1 ? 96 : 48;
                            break;

                        case LayerType.Layer3:
                            sound2.BitRateIndex = sound2.MpegVersion == MpegVersion.Mpeg1 ? 80 : 48;
                            break;

                        case LayerType.Reserved:
                            break;

                        default:
                            throw new ArgumentOutOfRangeException();
                        }

                        break;

                    case var _ when bitRateBits.IsEqualTo(new List <int> {
                            0, 1, 1, 1
                        }):
                        switch (sound2.LayerType)
                        {
                        case LayerType.Layer1:
                            sound2.BitRateIndex = sound2.MpegVersion == MpegVersion.Mpeg1 ? 224 : 112;
                            break;

                        case LayerType.Layer2:
                            sound2.BitRateIndex = sound2.MpegVersion == MpegVersion.Mpeg1 ? 112 : 56;
                            break;

                        case LayerType.Layer3:
                            sound2.BitRateIndex = sound2.MpegVersion == MpegVersion.Mpeg1 ? 96 : 56;
                            break;

                        case LayerType.Reserved:
                            break;

                        default:
                            throw new ArgumentOutOfRangeException();
                        }

                        break;

                    case var _ when bitRateBits.IsEqualTo(new List <int> {
                            1, 0, 0, 0
                        }):
                        switch (sound2.LayerType)
                        {
                        case LayerType.Layer1:
                            sound2.BitRateIndex = sound2.MpegVersion == MpegVersion.Mpeg1 ? 256 : 128;
                            break;

                        case LayerType.Layer2:
                            sound2.BitRateIndex = sound2.MpegVersion == MpegVersion.Mpeg1 ? 128 : 64;
                            break;

                        case LayerType.Layer3:
                            sound2.BitRateIndex = sound2.MpegVersion == MpegVersion.Mpeg1 ? 112 : 64;
                            break;

                        case LayerType.Reserved:
                            break;

                        default:
                            throw new ArgumentOutOfRangeException();
                        }

                        break;

                    case var _ when bitRateBits.IsEqualTo(new List <int> {
                            1, 0, 0, 1
                        }):
                        switch (sound2.LayerType)
                        {
                        case LayerType.Layer1:
                            sound2.BitRateIndex = sound2.MpegVersion == MpegVersion.Mpeg1 ? 288 : 144;
                            break;

                        case LayerType.Layer2:
                            sound2.BitRateIndex = sound2.MpegVersion == MpegVersion.Mpeg1 ? 160 : 80;
                            break;

                        case LayerType.Layer3:
                            sound2.BitRateIndex = sound2.MpegVersion == MpegVersion.Mpeg1 ? 128 : 80;
                            break;

                        case LayerType.Reserved:
                            break;

                        default:
                            throw new ArgumentOutOfRangeException();
                        }

                        break;

                    case var _ when bitRateBits.IsEqualTo(new List <int> {
                            1, 0, 1, 0
                        }):
                        switch (sound2.LayerType)
                        {
                        case LayerType.Layer1:
                            sound2.BitRateIndex = sound2.MpegVersion == MpegVersion.Mpeg1 ? 320 : 160;
                            break;

                        case LayerType.Layer2:
                            sound2.BitRateIndex = sound2.MpegVersion == MpegVersion.Mpeg1 ? 192 : 96;
                            break;

                        case LayerType.Layer3:
                            sound2.BitRateIndex = sound2.MpegVersion == MpegVersion.Mpeg1 ? 160 : 96;
                            break;

                        case LayerType.Reserved:
                            break;

                        default:
                            throw new ArgumentOutOfRangeException();
                        }

                        break;

                    case var _ when bitRateBits.IsEqualTo(new List <int> {
                            1, 0, 1, 1
                        }):
                        switch (sound2.LayerType)
                        {
                        case LayerType.Layer1:
                            sound2.BitRateIndex = sound2.MpegVersion == MpegVersion.Mpeg1 ? 352 : 176;
                            break;

                        case LayerType.Layer2:
                            sound2.BitRateIndex = sound2.MpegVersion == MpegVersion.Mpeg1 ? 224 : 112;
                            break;

                        case LayerType.Layer3:
                            sound2.BitRateIndex = sound2.MpegVersion == MpegVersion.Mpeg1 ? 192 : 112;
                            break;

                        case LayerType.Reserved:
                            break;

                        default:
                            throw new ArgumentOutOfRangeException();
                        }

                        break;

                    case var _ when bitRateBits.IsEqualTo(new List <int> {
                            1, 1, 0, 0
                        }):
                        switch (sound2.LayerType)
                        {
                        case LayerType.Layer1:
                            sound2.BitRateIndex = sound2.MpegVersion == MpegVersion.Mpeg1 ? 384 : 192;
                            break;

                        case LayerType.Layer2:
                            sound2.BitRateIndex = sound2.MpegVersion == MpegVersion.Mpeg1 ? 256 : 128;
                            break;

                        case LayerType.Layer3:
                            sound2.BitRateIndex = sound2.MpegVersion == MpegVersion.Mpeg1 ? 224 : 128;
                            break;

                        case LayerType.Reserved:
                            break;

                        default:
                            throw new ArgumentOutOfRangeException();
                        }

                        break;

                    case var _ when bitRateBits.IsEqualTo(new List <int> {
                            1, 1, 0, 1
                        }):
                        switch (sound2.LayerType)
                        {
                        case LayerType.Layer1:
                            sound2.BitRateIndex = sound2.MpegVersion == MpegVersion.Mpeg1 ? 416 : 224;
                            break;

                        case LayerType.Layer2:
                            sound2.BitRateIndex = sound2.MpegVersion == MpegVersion.Mpeg1 ? 320 : 144;
                            break;

                        case LayerType.Layer3:
                            sound2.BitRateIndex = sound2.MpegVersion == MpegVersion.Mpeg1 ? 256 : 144;
                            break;

                        case LayerType.Reserved:
                            break;

                        default:
                            throw new ArgumentOutOfRangeException();
                        }

                        break;

                    case var _ when bitRateBits.IsEqualTo(new List <int> {
                            1, 1, 1, 0
                        }):
                        switch (sound2.LayerType)
                        {
                        case LayerType.Layer1:
                            sound2.BitRateIndex = sound2.MpegVersion == MpegVersion.Mpeg1 ? 448 : 256;
                            break;

                        case LayerType.Layer2:
                            sound2.BitRateIndex = sound2.MpegVersion == MpegVersion.Mpeg1 ? 384 : 160;
                            break;

                        case LayerType.Layer3:
                            sound2.BitRateIndex = sound2.MpegVersion == MpegVersion.Mpeg1 ? 320 : 160;
                            break;

                        case LayerType.Reserved:
                            break;

                        default:
                            throw new ArgumentOutOfRangeException();
                        }

                        break;

                    default:
                        sound2.BitRateIndex = -1;
                        break;
                    }

                    var frequencyIndexBits = headerBits.Skip(20).Take(2).ToList();

                    switch (frequencyIndexBits)
                    {
                    case var _ when frequencyIndexBits.IsEqualTo(new List <int> {
                            0, 0
                        }):
                        sound2.RateFrequencyIndex = sound2.MpegVersion == MpegVersion.Mpeg1 ? 44100 :
                                                    sound2.MpegVersion == MpegVersion.Mpeg2 ? 22050 : 11025;

                        break;

                    case var _ when frequencyIndexBits.IsEqualTo(new List <int> {
                            0, 1
                        }):
                        sound2.RateFrequencyIndex = sound2.MpegVersion == MpegVersion.Mpeg1 ? 48000 :
                                                    sound2.MpegVersion == MpegVersion.Mpeg2 ? 24000 : 12000;

                        break;

                    case var _ when frequencyIndexBits.IsEqualTo(new List <int> {
                            1, 0
                        }):
                        sound2.RateFrequencyIndex = sound2.MpegVersion == MpegVersion.Mpeg1 ? 32000 :
                                                    sound2.MpegVersion == MpegVersion.Mpeg2 ? 16000 : 8000;

                        break;

                    case var _ when frequencyIndexBits.IsEqualTo(new List <int> {
                            1, 1
                        }):
                        sound2.RateFrequencyIndex = -1;

                        break;
                    }

                    var paddingBit = headerBits.Skip(22).Take(1).ToList();
                    sound2.Padded = paddingBit[0] == 1;

                    var privateBit = headerBits.Skip(23).Take(1).ToList();
                    sound2.PrivateBit = privateBit[0] == 1;

                    var channelModeBits = headerBits.Skip(24).Take(2).ToList();
                    if (channelModeBits[0] == 0)
                    {
                        sound2.ChannelMode = channelModeBits[1] == 0 ? ChannelMode.Stereo : ChannelMode.JointStereo;
                    }
                    else
                    {
                        sound2.ChannelMode = channelModeBits[1] == 0 ? ChannelMode.DualChannel : ChannelMode.SingleChannel;
                    }

                    var modeExtenstionBits = headerBits.Skip(26).Take(2).ToList();

                    var copyrightBits = headerBits.Skip(28).Take(1).ToList();
                    sound2.Copyright = copyrightBits[0] == 1;

                    var originalBits = headerBits.Skip(29).Take(1).ToList();
                    sound2.Original = originalBits[0] == 1;

                    var emphasisBits = headerBits.Skip(30).ToList();
                    if (emphasisBits[0] == 0)
                    {
                        sound2.EmphasisType = emphasisBits[1] == 0 ? EmphasisType.None : EmphasisType._50_15ms;
                    }
                    else
                    {
                        sound2.EmphasisType = emphasisBits[1] == 0 ? EmphasisType.Reserved : EmphasisType.Ccitj17;
                    }
                }
                else     //ID3v2
                {
                    var majorVersion = BitConverter.ToInt32(bytes.Slice(3, 1, 4), 0);
                    var minorVersion = BitConverter.ToInt32(bytes.Slice(4, 1, 4), 0);

                    var flagsBits = bytes[5].ToBitsArray();

                    var unsynchronisationFlag     = flagsBits[0] == 1;
                    var extendedHeaderFlag        = flagsBits[1] == 1;
                    var experimentalIndicatorFlag = flagsBits[2] == 1;
                    var footerPresentFlag         = flagsBits[3] == 1;

                    if (!flagsBits.Skip(4).ToList().IsEqualTo(new List <int> {
                        0, 0, 0, 0
                    }))
                    {
                        throw new Exception("MP3 Error");
                    }

                    var size = bytes[9] + bytes[8] << 7 + bytes[6] << 14 + bytes[5] << 21;

                    var currentByte = 10;

                    if (extendedHeaderFlag)
                    {
                        var extendedHeaderSize = bytes[currentByte + 3] + bytes[currentByte + 2] <<
                                                 7 + bytes[currentByte + 1] << 14 + bytes[currentByte] << 21;
                        currentByte += extendedHeaderSize;     //5; // skip flags size
                        // TODO: parse extended header - optional
                        //  https://mutagen-specs.readthedocs.io/en/latest/id3/id3v2.4.0-structure.html
                    }

                    // TODO: Frames



                    // TODO: Parse padding - optional
                    // TODO: Parse footer - optional
                }

                // TODO: Data from mp3

                var tagBytes = bytes.Reverse().Take(128).Reverse().ToArray();

                var tagString = Encoding.UTF8.GetString(tagBytes.Slice(0, 3));

                if (tagString.ToUpper() != "TAG")
                {
                    return(sound2);
                }

                var tag = new Tag
                {
                    Title      = Encoding.UTF8.GetString(tagBytes.Slice(3, 30)).Trim('\0'),
                    Artist     = Encoding.UTF8.GetString(tagBytes.Slice(33, 30)).Trim('\0'),
                    Album      = Encoding.UTF8.GetString(tagBytes.Slice(63, 30)).Trim('\0'),
                    Year       = Encoding.UTF8.GetString(tagBytes.Slice(93, 4)).Trim('\0'),
                    CommentV1  = Encoding.UTF8.GetString(tagBytes.Slice(97, 30)).Trim('\0'),
                    CommentV2  = Encoding.UTF8.GetString(tagBytes.Slice(97, 28)).Trim('\0'),
                    AlbumTrack = Encoding.UTF8.GetString(tagBytes.Slice(125, 2)).Trim('\0'),
                    Genre      = BitConverter.ToInt32(tagBytes.Slice(127, 1, 4), 0)
                };

                sound2.Tag = tag;

                return(sound2);

            default:
                return(null);
            }
        }
Exemple #3
0
        public static WavSound GetWavSound(byte[] bytes)
        {
            var sound = new WavSound {
                RawBinary = bytes.ToList()
            };

            var currentIndex = 0;

            sound.ChunkId = Encoding.UTF8.GetString(bytes.Slice(currentIndex, 4));
            currentIndex += 4;
            bool bigEndian;

            switch (sound.ChunkId)
            {
            case SoundConstants.RIFF:
                bigEndian = false;
                break;

            case SoundConstants.RIFX:
                bigEndian = true;
                break;

            default:
                throw new Exception($"Unknown format: {sound.ChunkId}");
            }
            sound.ChunkSize = bytes.Slice(currentIndex, 4).GetUInt(bigEndian) + 8;
            currentIndex   += 4;
            sound.Format    = Encoding.UTF8.GetString(bytes.Slice(currentIndex, 4));
            currentIndex   += 4;
            if (sound.Format != "WAVE")
            {
                throw new Exception("This is not a WAV File");
            }

            var fmtChunkReceived = false;

            while (currentIndex < bytes.Length)
            {
                var chunkId = Encoding.UTF8.GetString(bytes.Slice(currentIndex, 4));
                currentIndex += 4;
                switch (chunkId)
                {
                case SoundConstants.FMT_ID:
                    fmtChunkReceived    = true;
                    sound.SubChunk1Id   = chunkId;
                    sound.SubChunk1Size = bytes.Slice(currentIndex, 4).GetUInt(bigEndian);
                    currentIndex       += 4;
                    var bytesRead = 0;
                    if (sound.SubChunk1Size < 16)
                    {
                        throw new Exception("Wrong WAV file format");
                    }

                    sound.AudioFormat = bytes.Slice(currentIndex, 2, 4).GetUShort(bigEndian);
                    currentIndex     += 2;
                    sound.NumChannels = bytes.Slice(currentIndex, 2, 4).GetUShort(bigEndian);
                    currentIndex     += 2;
                    sound.SampleRate  = bytes.Slice(currentIndex, 4).GetUInt(bigEndian);
                    currentIndex     += 4;
                    sound.ByteRate    = bytes.Slice(currentIndex, 4).GetUInt(bigEndian);
                    currentIndex     += 4;
                    sound.BlockAlign  = bytes.Slice(currentIndex, 2, 4).GetUShort(bigEndian);
                    currentIndex     += 2;
                    sound.BitDepth    = bytes.Slice(currentIndex, 2, 4).GetUShort(bigEndian);
                    currentIndex     += 2;
                    bytesRead        += 16;

                    if (sound.AudioFormat == SoundConstants.WAVE_FORMAT_EXTENSIBLE && sound.SubChunk1Size >= 18)
                    {
                        sound.ExtraChunkSize = bytes.Slice(currentIndex, 2, 4).GetUShort(bigEndian);
                        bytesRead           += 2;
                        currentIndex        += 2;
                        if (sound.ExtraChunkSize >= 22)
                        {
                            sound.ExtraData = bytes.Slice(currentIndex, 22, 4);
                            currentIndex   += 22;
                            bytesRead      += 22;
                            var rawGuid = sound.ExtraData.Slice(6, 16, 4);
                            var tail    = bigEndian
                                    ? new byte[] { 0x0, 0x0, 0x0, 0x10, 0x80, 0x0, 0x0, 0xAA, 0x00, 0x38, 0x9B, 0x71 }
                                    : new byte[] { 0x0, 0x0, 0x10, 0x0, 0x80, 0x0, 0x0, 0xAA, 0x0, 0x38, 0x9B, 0x71 };
                            if (rawGuid.EndsWith(tail))
                            {
                                sound.AudioFormat = rawGuid.Skip(rawGuid.Length - 4).ToArray().GetUShort(bigEndian);
                            }
                        }
                        else
                        {
                            throw new Exception("Wave error");
                        }
                    }
                    if (!SoundConstants.KNOWN_WAVE_FORMATS.Contains(sound.AudioFormat))
                    {
                        throw new Exception("Unknown wave format");
                    }

                    if (sound.SubChunk1Size > bytesRead)
                    {
                        currentIndex += (int)(sound.SubChunk1Size - bytesRead);
                    }

                    if (!new List <ushort> {
                        8, 16, 32, 64, 96, 128
                    }.Contains(sound.BitDepth))
                    {
                        throw new Exception($"Unsupported bit depth: {sound.BitDepth}-Bit");
                    }
                    break;

                case SoundConstants.FACT_ID:
                    if (currentIndex + 4 < bytes.Length)
                    {
                        currentIndex += 4 + bytes.Slice(currentIndex, 4, 4).GetUShort(bigEndian);
                    }
                    break;

                case SoundConstants.DATA_ID:
                    if (!fmtChunkReceived)
                    {
                        throw new Exception("No ftm chunk before data");
                    }
                    sound.SubChunk2Id   = chunkId;
                    sound.SubChunk2Size = bytes.Slice(currentIndex, 4, 4).GetUInt(bigEndian);
                    currentIndex       += 4;

                    var bytesPerSample = (ushort)(sound.BitDepth / 8);
                    var type           = sound.BitDepth == 8 ?
                                         "u1" :
                                         (bigEndian ? ">" : "<") +
                                         (sound.AudioFormat == SoundConstants.WAVE_FORMAT_PCM ? "i" : "f") +
                                         bytesPerSample;
                    sound.Data    = bytes.Skip(currentIndex).Take((int)sound.SubChunk2Size).ToArray().FromBuffer(type);
                    currentIndex += (int)sound.SubChunk2Size;
                    // if (sound.NumChannels > 1)
                    break;

                case SoundConstants.LIST_ID:
                    if (currentIndex + 4 < bytes.Length)
                    {
                        currentIndex += 4 + bytes.Slice(currentIndex, 4, 4).GetUShort(bigEndian);
                    }
                    break;

                case var _ when new List <string> {
                        SoundConstants.JUNK_ID, SoundConstants.FAKE_ID
                }.Contains(sound.SubChunk1Id):
                    if (currentIndex + 4 < bytes.Length)
                    {
                        currentIndex += 4 + bytes.Slice(currentIndex, 4, 4).GetUShort(bigEndian);
                    }
                    break;

                default:
                    // warning
                    if (currentIndex + 4 < bytes.Length)
                    {
                        currentIndex += 4 + bytes.Slice(currentIndex, 4, 4).GetUShort(bigEndian);
                    }
                    break;
                }
            }

            sound.Duration = sound.ChunkSize * 1.0 / (sound.SampleRate * sound.NumChannels * sound.BitDepth / 8.0);
            return(sound);
        }