/// <summary>
        /// Read the next RIFF element invoking the correct delegate.
        /// Returns true if an element can be read
        /// </summary>
        /// <param name="bytesleft">Reference to number of bytes left in the current list</param>
        /// <param name="chunk">Method to invoke if a chunk is found</param>
        /// <param name="list">Method to invoke if a list is found</param>
        /// <returns></returns>
        public bool ReadElement(ref int bytesleft, ProcessChunkElement chunk, ProcessListElement list)
        {
            // Are we done?
            if (TWODWORDSSIZE > bytesleft)
            {
                return false;
            }            //Console.WriteLine(m_stream.Position.ToString() + ", " + bytesleft.ToString());            // We have enough bytes, read
            int FourCC;
            int size;            ReadTwoInts(out FourCC, out size);            // Reduce bytes left
            bytesleft -= TWODWORDSSIZE;            // Do we have enough bytes?
            if (bytesleft < size)
            {
                // Skip the bad data and throw an exception
                SkipData(bytesleft);
                bytesleft = 0;
                throw new RiffParserException("Element size mismatch for element " + FromFourCC(FourCC)
                + " need " + size.ToString() + " but have only " + bytesleft.ToString());
            }            // Examine the element, is it a list or a chunk
            string type = FromFourCC(FourCC);
            if (0 == String.Compare(type, LIST4CC))
            {
                // We have a list
                ReadOneInt(out FourCC);                if (null == list)
                {
                    SkipData(size - 4);
                }
                else
                {
                    // Invoke the list method
                    list(this, FourCC, size - 4);
                }                // Adjust size
                bytesleft -= size;
            }
            else
            {
                // Calculated padded size - padded to WORD boundary
                int paddedSize = size;
                if (0 != (size & 1)) ++paddedSize;                if (null == chunk)
                {
                    SkipData(paddedSize);
                }
                else
                {
                    chunk(this, FourCC, size, paddedSize);
                }                // Adjust size
                bytesleft -= paddedSize;
            }            return true;
        }        #region Stream access        /// <summary>
        /// Non-thread-safe method to read two ints from the stream
        /// </summary>
        /// <param name="FourCC">Output FourCC int</param>
        /// <param name="size">Output chunk/list size</param>
        public unsafe void ReadTwoInts(out int FourCC, out int size)
        {
            try {
                int readsize = m_stream.Read(m_eightBytes, 0, TWODWORDSSIZE);                if (TWODWORDSSIZE != readsize) {
                    throw new RiffParserException("Unable to read. Corrupt RIFF file " + FileName);
                }                fixed (byte* bp = &m_eightBytes[0]) {
                    FourCC = *((int*)bp);
                    size = *((int*)(bp + DWORDSIZE));
                }
            }
            catch (Exception ex)
            {
                throw new RiffParserException("Problem accessing RIFF file " + FileName, ex);
            }
        }        /// <summary>
        /// Non-thread-safe read a single int from the stream
        /// </summary>
        /// <param name="FourCC">Output int</param>
        public unsafe void ReadOneInt(out int FourCC)
        {
            try {
                int readsize = m_stream.Read(m_fourBytes, 0, DWORDSIZE);                if (DWORDSIZE != readsize) {
                    throw new RiffParserException("Unable to read. Corrupt RIFF file " + FileName);
                }                fixed (byte* bp = &m_fourBytes[0]) {
                    FourCC = *((int*)bp);
                }
            }
            catch (Exception ex)
            {
                throw new RiffParserException("Problem accessing RIFF file " + FileName, ex);
            }
        }        /// <summary>
        /// Skip the specified number of bytes
        /// </summary>
        /// <param name="skipBytes">Number of bytes to skip</param>
        public void SkipData(int skipBytes)
        {
            try {
                m_stream.Seek(skipBytes, SeekOrigin.Current);
            }
            catch (Exception ex)
            {
                throw new RiffParserException("Problem seeking in file " + FileName, ex);
            }
        }        /// <summary>
        /// Read the specified length into the byte array at the specified
        /// offset in the array
        /// </summary>
        /// <param name="data">Array of bytes to read into</param>
        /// <param name="offset">Offset in the array to start from</param>
        /// <param name="length">Number of bytes to read</param>
        /// <returns>Number of bytes actually read</returns>
        public int ReadData(Byte[] data, int offset, int length)
        {
            try {
                return m_stream.Read(data, offset, length);
            }
            catch (Exception ex)
            {
                throw new RiffParserException("Problem reading data in file " + FileName, ex);
            }
        }        /// <summary>
        /// Close the RIFF file
        /// </summary>
        public void CloseFile()
        {
            if (null != m_stream)
            {
                m_stream.Close();
                m_stream = null;
            }
        }        #endregion        #region FourCC conversion methods        public static string FromFourCC(int FourCC)
        {
            char[] chars = new char[4];
            chars[0] = (char)(FourCC & 0xFF);
            chars[1] = (char)((FourCC >> 8) & 0xFF);
            chars[2] = (char)((FourCC >> 16) & 0xFF);
            chars[3] = (char)((FourCC >> 24) & 0xFF);            return new string(chars);
        }        public static int ToFourCC(string FourCC)
        {
            if (FourCC.Length != 4)
            {
                throw new Exception("FourCC strings must be 4 characters long " + FourCC);
            }            int result = ((int)FourCC[3]) << 24
                        | ((int)FourCC[2]) << 16
                        | ((int)FourCC[1]) << 8
                        | ((int)FourCC[0]);            return result;
        }        public static int ToFourCC(char[] FourCC)
        {
            if (FourCC.Length != 4)
            {
                throw new Exception("FourCC char arrays must be 4 characters long " + new string(FourCC));
            }            int result = ((int)FourCC[3]) << 24
                        | ((int)FourCC[2]) << 16
                        | ((int)FourCC[1]) << 8
                        | ((int)FourCC[0]);            return result;
        }        public static int ToFourCC(char c0, char c1, char c2, char c3)
        {
            int result = ((int)c3) << 24
                        | ((int)c2) << 16
                        | ((int)c1) << 8
                        | ((int)c0);            return result;
        }
        #endregion    }
}