public static TimeSpan Read(Stream stream, int length)
        {
            var  id3v2Tag          = Id3v2Tag.ReadTag(stream);
            long dataStartPosition = stream.Position;
            var  firstFrame        = Mp3Frame.LoadFromStream(stream);

            if (firstFrame == null)
            {
                throw new InvalidDataException("Invalid MP3 file - no MP3 Frames Detected");
            }
            double bitRate    = firstFrame.BitRate;
            var    xingHeader = XingHeader.LoadXingHeader(firstFrame);

            // If the header exists, we can skip over it when decoding the rest of the file
            if (xingHeader != null)
            {
                dataStartPosition = stream.Position;
            }

            // workaround for a longstanding issue with some files failing to load
            // because they report a spurious sample rate change
            var secondFrame = Mp3Frame.LoadFromStream(stream);

            if (secondFrame != null &&
                (secondFrame.SampleRate != firstFrame.SampleRate ||
                 secondFrame.ChannelMode != firstFrame.ChannelMode))
            {
                // assume that the first frame was some kind of VBR/LAME header that we failed to recognise properly
                dataStartPosition = secondFrame.FileOffset;
                // forget about the first frame, the second one is the first one we really care about
                firstFrame = secondFrame;
            }

            long   mp3DataLength = length - dataStartPosition - 128;
            double totaltime     = mp3DataLength * 8.0 / firstFrame.BitRate;

            return(TimeSpan.FromSeconds(totaltime));
        }
        /// <summary>
        /// Load Xing Header
        /// </summary>
        /// <param name="frame">Frame</param>
        /// <returns>Xing Header</returns>
        public static XingHeader LoadXingHeader(Mp3Frame frame)
        {
            XingHeader xingHeader = new XingHeader();

            xingHeader.frame = frame;
            int offset = 0;

            if (frame.MpegVersion == MpegVersion.Version1)
            {
                if (frame.ChannelMode != ChannelMode.Mono)
                {
                    offset = 32 + 4;
                }
                else
                {
                    offset = 17 + 4;
                }
            }
            else if (frame.MpegVersion == MpegVersion.Version2)
            {
                if (frame.ChannelMode != ChannelMode.Mono)
                {
                    offset = 17 + 4;
                }
                else
                {
                    offset = 9 + 4;
                }
            }
            else
            {
                return(null);
                // throw new FormatException("Unsupported MPEG Version");
            }

            if ((frame.RawData[offset + 0] == 'X') &&
                (frame.RawData[offset + 1] == 'i') &&
                (frame.RawData[offset + 2] == 'n') &&
                (frame.RawData[offset + 3] == 'g'))
            {
                xingHeader.startOffset = offset;
                offset += 4;
            }
            else if ((frame.RawData[offset + 0] == 'I') &&
                     (frame.RawData[offset + 1] == 'n') &&
                     (frame.RawData[offset + 2] == 'f') &&
                     (frame.RawData[offset + 3] == 'o'))
            {
                xingHeader.startOffset = offset;
                offset += 4;
            }
            else
            {
                return(null);
            }

            XingHeaderOptions flags = (XingHeaderOptions)ReadBigEndian(frame.RawData, offset);

            offset += 4;

            if ((flags & XingHeaderOptions.Frames) != 0)
            {
                xingHeader.framesOffset = offset;
                offset += 4;
            }
            if ((flags & XingHeaderOptions.Bytes) != 0)
            {
                xingHeader.bytesOffset = offset;
                offset += 4;
            }
            if ((flags & XingHeaderOptions.Toc) != 0)
            {
                xingHeader.tocOffset = offset;
                offset += 100;
            }
            if ((flags & XingHeaderOptions.VbrScale) != 0)
            {
                xingHeader.vbrScale = ReadBigEndian(frame.RawData, offset);
                offset += 4;
            }
            xingHeader.endOffset = offset;
            return(xingHeader);
        }