Represents the type ID and size for a "chunk" in a RIFF media format file.

The Resource Interchange File Format (RIFF) is a generic meta-format for storing data in tagged chunks. It was introduced in 1991 by Microsoft and IBM, and was presented by Microsoft as the default format for Windows 3.1 multimedia files. It is based on Electronic Arts's Interchange File Format, introduced in 1985, the only difference being that multi-byte integers are in little-endian format, native to the 80x86 processor series used in IBM PCs, rather than the big-endian format native to the 68k processor series used in Amiga and Apple Macintosh computers, where IFF files were heavily used. (The specification for AIFF, the big-endian analogue of RIFF, was published by Apple Computer in 1988.) The Microsoft implementation is mostly known through file formats like AVI, ANI and WAV, which use the RIFF meta-format as their basis.

Some common RIFF file types: File extension Description WAV Windows audio file AVI Windows audio/video file ANI Animated Windows cursors RMI Windows RIFF MIDI file CDR CorelDRAW vector graphics file

Inheritance: ISupportBinaryImage
Ejemplo n.º 1
0
        /// <summary>
        /// Constructor for derived classes used to initialize and validate  <see cref="RiffChunk"/> properties.
        /// </summary>
        /// <param name="preRead">Pre-parsed <see cref="RiffChunk"/> header.</param>
        /// <param name="typeID">Expected type ID.</param>
        protected RiffChunk(RiffChunk preRead, string typeID)
        {
            if (typeID != preRead.TypeID)
            {
                throw new InvalidDataException(string.Format("{0} chunk expected but got {1}, file does not appear to be valid", typeID, preRead.TypeID));
            }

            m_typeID    = preRead.TypeID;
            m_chunkSize = preRead.ChunkSize;
        }
Ejemplo n.º 2
0
        /// <summary>Reads a new WAVE list info section from the specified stream.</summary>
        /// <param name="preRead">Pre-parsed <see cref="RiffChunk"/> header.</param>
        /// <param name="source">Source stream to read data from.</param>
        /// <exception cref="InvalidOperationException">WAVE list info section is too small, wave file corrupted.</exception>
        public ListInfoChunk(RiffChunk preRead, Stream source)
            : base(preRead, RiffTypeID)
        {
            byte[] buffer = new byte[preRead.ChunkSize];
            byte[] nullByte = { 0 };
            int    bytesRead = source.Read(buffer, 0, buffer.Length);
            int    length, index = 0;
            string key, value;

            m_infoStrings = new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase);

            if (bytesRead >= 4 && string.Compare(Encoding.ASCII.GetString(buffer, index, 4), "INFO", true) == 0)
            {
                index += 4;

                while (index < bytesRead)
                {
                    // Read key
                    length = buffer.IndexOfSequence(nullByte, index) - index + 1;
                    key    = Encoding.ASCII.GetString(buffer, index, length - 1).RemoveNull().RemoveControlCharacters();
                    index += length;

                    // Skip through null values
                    while (index < bytesRead && buffer[index] == 0)
                    {
                        index++;
                    }

                    // Read value
                    length = buffer.IndexOfSequence(nullByte, index) - index + 1;
                    value  = Encoding.ASCII.GetString(buffer, index, length - 1).RemoveNull().RemoveControlCharacters();
                    index += length;

                    // Skip through null values
                    while (index < bytesRead && buffer[index] == 0)
                    {
                        index++;
                    }

                    if (!string.IsNullOrWhiteSpace(key))
                    {
                        m_infoStrings[key] = value;
                    }
                }
            }
        }
Ejemplo n.º 3
0
        // Static Methods

        /// <summary>
        /// Attempts to read the next RIFF chunk from the <paramref name="source"/> stream.
        /// </summary>
        /// <param name="source">Source stream for next RIFF chunk.</param>
        /// <returns>Next RIFF chunk read from the <paramref name="source"/> stream.</returns>
        /// <exception cref="InvalidOperationException">RIFF chunk too small, media file corrupted.</exception>
        public static RiffChunk ReadNext(Stream source)
        {
            RiffChunk riffChunk = new RiffChunk();
            int       length    = riffChunk.BinaryLength;

            byte[] buffer = new byte[length];

            int bytesRead = source.Read(buffer, 0, length);

            if (bytesRead < length)
            {
                throw new InvalidOperationException("RIFF chunk too small, media file corrupted");
            }

            riffChunk.TypeID    = Encoding.ASCII.GetString(buffer, 0, 4);
            riffChunk.ChunkSize = LittleEndian.ToInt32(buffer, 4);

            return(riffChunk);
        }
Ejemplo n.º 4
0
        /// <summary>Reads a new WAVE format section from the specified stream.</summary>
        /// <param name="preRead">Pre-parsed <see cref="RiffChunk"/> header.</param>
        /// <param name="source">Source stream to read data from.</param>
        /// <param name="waveFormat">Format of the data section to be parsed.</param>
        /// <exception cref="InvalidOperationException">WAVE format or extra parameters section too small, wave file corrupted.</exception>
        public WaveDataChunk(RiffChunk preRead, Stream source, WaveFormatChunk waveFormat)
            : base(preRead, RiffTypeID)
        {
            m_waveFormat   = waveFormat;
            m_sampleBlocks = new List <LittleBinaryValue[]>();
            m_chunkSize    = -1;

            int      blockSize      = waveFormat.BlockAlignment;
            int      sampleSize     = waveFormat.BitsPerSample / 8;
            int      channels       = waveFormat.Channels;
            TypeCode sampleTypeCode = m_waveFormat.GetSampleTypeCode();

            LittleBinaryValue[] sampleBlock;
            byte[] buffer = BufferPool.TakeBuffer(blockSize);

            try
            {
                int bytesRead = source.Read(buffer, 0, blockSize);

                while (bytesRead == blockSize)
                {
                    // Create a new sample block, one little-endian formatted binary sample value for each channel
                    sampleBlock = new LittleBinaryValue[channels];

                    for (int x = 0; x < channels; x++)
                    {
                        sampleBlock[x] = new LittleBinaryValue(sampleTypeCode, buffer, x * sampleSize, sampleSize);
                    }

                    m_sampleBlocks.Add(sampleBlock);

                    bytesRead = source.Read(buffer, 0, blockSize);
                }
            }
            finally
            {
                if (buffer != null)
                {
                    BufferPool.ReturnBuffer(buffer);
                }
            }
        }
Ejemplo n.º 5
0
        /// <summary>Reads a new RIFF header from the specified stream.</summary>
        /// <param name="preRead">Pre-parsed <see cref="RiffChunk"/> header.</param>
        /// <param name="source">Source stream to read data from.</param>
        /// <param name="format">Expected RIFF media format (e.g., "WAVE").</param>
        /// <exception cref="ArgumentNullException"><paramref name="format"/> cannot be null.</exception>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="format"/> must be extactly 4 characters in length.</exception>
        public RiffHeaderChunk(RiffChunk preRead, Stream source, string format)
            : base(preRead, RiffTypeID)
        {
            if (string.IsNullOrWhiteSpace(format))
            {
                throw new ArgumentNullException("value");
            }

            if (format.Length != 4)
            {
                throw new ArgumentOutOfRangeException("value", "Format must be exactly 4 characters in length");
            }

            byte[] buffer = BufferPool.TakeBuffer(4);

            try
            {
                int bytesRead = source.Read(buffer, 0, 4);

                if (bytesRead < 4)
                {
                    throw new InvalidOperationException("RIFF format section too small, media file corrupted");
                }

                // Read format stored in RIFF section
                m_format = Encoding.ASCII.GetString(buffer, 0, 4);

                if (m_format != format)
                {
                    throw new InvalidDataException(string.Format("{0} format expected but got {1}, this does not appear to be a valid {0} file", format, m_format));
                }
            }
            finally
            {
                if (buffer != null)
                {
                    BufferPool.ReturnBuffer(buffer);
                }
            }
        }
Ejemplo n.º 6
0
        /// <summary>Reads a new <see cref="WaveFormatChunk"/> from the specified stream.</summary>
        /// <param name="preRead">Pre-parsed <see cref="RiffChunk"/> header.</param>
        /// <param name="source">Source stream to read data from.</param>
        /// <exception cref="InvalidOperationException">WAVE format or extra parameters section too small, wave file corrupted.</exception>
        /// <exception cref="InvalidDataException">Invalid bit rate encountered - wave file bit rates must be a multiple of 8.</exception>
        public WaveFormatChunk(RiffChunk preRead, Stream source)
            : base(preRead, RiffTypeID)
        {
            int length = ChunkSize;
            byte[] buffer = BufferPool.TakeBuffer(length);

            try
            {
                int bytesRead = source.Read(buffer, 0, length);

                // Initialize class from buffer
                ParseBinaryImage(buffer, 0, bytesRead);

                // Read extra parameters, if any
                if (m_extraParametersSize > 0)
                {
                    m_extraParameters = new byte[m_extraParametersSize];

                    bytesRead = source.Read(m_extraParameters, 0, m_extraParametersSize);

                    if (bytesRead < m_extraParametersSize)
                        throw new InvalidOperationException("WAVE extra parameters section too small, wave file corrupted");
                }
            }
            finally
            {
                if (buffer != null)
                    BufferPool.ReturnBuffer(buffer);
            }
        }
Ejemplo n.º 7
0
        /// <summary>Reads a new WAVE format section from the specified stream.</summary>
        /// <param name="preRead">Pre-parsed <see cref="RiffChunk"/> header.</param>
        /// <param name="source">Source stream to read data from.</param>
        /// <param name="waveFormat">Format of the data section to be parsed.</param>
        /// <exception cref="InvalidOperationException">WAVE format or extra parameters section too small, wave file corrupted.</exception>
        public WaveDataChunk(RiffChunk preRead, Stream source, WaveFormatChunk waveFormat)
            : base(preRead, RiffTypeID)
        {
            m_waveFormat = waveFormat;
            m_sampleBlocks = new List<LittleBinaryValue[]>();
            m_chunkSize = -1;

            int blockSize = waveFormat.BlockAlignment;
            int sampleSize = waveFormat.BitsPerSample / 8;
            int channels = waveFormat.Channels;
            TypeCode sampleTypeCode = m_waveFormat.GetSampleTypeCode();
            LittleBinaryValue[] sampleBlock;
            byte[] buffer = new byte[blockSize];

            int bytesRead = source.Read(buffer, 0, blockSize);

            while (bytesRead == blockSize)
            {
                // Create a new sample block, one little-endian formatted binary sample value for each channel
                sampleBlock = new LittleBinaryValue[channels];

                for (int x = 0; x < channels; x++)
                {
                    sampleBlock[x] = new LittleBinaryValue(sampleTypeCode, buffer, x * sampleSize, sampleSize);
                }

                m_sampleBlocks.Add(sampleBlock);

                bytesRead = source.Read(buffer, 0, blockSize);
            }
        }
Ejemplo n.º 8
0
        /// <summary>Reads a new RIFF header from the specified stream.</summary>
        /// <param name="preRead">Pre-parsed <see cref="RiffChunk"/> header.</param>
        /// <param name="source">Source stream to read data from.</param>
        /// <param name="format">Expected RIFF media format (e.g., "WAVE").</param>
        /// <exception cref="ArgumentNullException"><paramref name="format"/> cannot be null.</exception>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="format"/> must be extactly 4 characters in length.</exception>
        public RiffHeaderChunk(RiffChunk preRead, Stream source, string format)
            : base(preRead, RiffTypeID)
        {
            if (string.IsNullOrWhiteSpace(format))
                throw new ArgumentNullException("value");

            if (format.Length != 4)
                throw new ArgumentOutOfRangeException("value", "Format must be exactly 4 characters in length");

            byte[] buffer = BufferPool.TakeBuffer(4);

            try
            {
                int bytesRead = source.Read(buffer, 0, 4);

                if (bytesRead < 4)
                    throw new InvalidOperationException("RIFF format section too small, media file corrupted");

                // Read format stored in RIFF section
                m_format = Encoding.ASCII.GetString(buffer, 0, 4);

                if (m_format != format)
                    throw new InvalidDataException(string.Format("{0} format expected but got {1}, this does not appear to be a valid {0} file", format, m_format));
            }
            finally
            {
                if (buffer != null)
                    BufferPool.ReturnBuffer(buffer);
            }
        }
Ejemplo n.º 9
0
        /// <summary>Reads a new WAVE list info section from the specified stream.</summary>
        /// <param name="preRead">Pre-parsed <see cref="RiffChunk"/> header.</param>
        /// <param name="source">Source stream to read data from.</param>
        /// <exception cref="InvalidOperationException">WAVE list info section is too small, wave file corrupted.</exception>
        public ListInfoChunk(RiffChunk preRead, Stream source)
            : base(preRead, RiffTypeID)
        {
            byte[] buffer = new byte[preRead.ChunkSize];
            byte[] nullByte = { 0 };
            int bytesRead = source.Read(buffer, 0, buffer.Length);
            int length, index = 0;
            string key, value;

            m_infoStrings = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);

            if (bytesRead >= 4 && string.Compare(Encoding.ASCII.GetString(buffer, index, 4), "INFO", true) == 0)
            {
                index += 4;

                while (index < bytesRead)
                {
                    // Read key
                    length = buffer.IndexOfSequence(nullByte, index) - index + 1;
                    key = Encoding.ASCII.GetString(buffer, index, length - 1).RemoveNull().RemoveControlCharacters();
                    index += length;

                    // Skip through null values
                    while (index < bytesRead && buffer[index] == 0)
                        index++;

                    // Read value
                    length = buffer.IndexOfSequence(nullByte, index) - index + 1;
                    value = Encoding.ASCII.GetString(buffer, index, length - 1).RemoveNull().RemoveControlCharacters();
                    index += length;

                    // Skip through null values
                    while (index < bytesRead && buffer[index] == 0)
                        index++;

                    if (!string.IsNullOrWhiteSpace(key))
                        m_infoStrings[key] = value;
                }
            }
        }
Ejemplo n.º 10
0
        // Static Methods

        /// <summary>
        /// Attempts to read the next RIFF chunk from the <paramref name="source"/> stream.
        /// </summary>
        /// <param name="source">Source stream for next RIFF chunk.</param>
        /// <returns>Next RIFF chunk read from the <paramref name="source"/> stream.</returns>
        /// <exception cref="InvalidOperationException">RIFF chunk too small, media file corrupted.</exception>
        public static RiffChunk ReadNext(Stream source)
        {
            RiffChunk riffChunk = new RiffChunk();
            int length = riffChunk.BinaryLength;

            byte[] buffer = new byte[length];

            int bytesRead = source.Read(buffer, 0, length);

            if (bytesRead < length)
                throw new InvalidOperationException("RIFF chunk too small, media file corrupted");

            riffChunk.TypeID = Encoding.ASCII.GetString(buffer, 0, 4);
            riffChunk.ChunkSize = LittleEndian.ToInt32(buffer, 4);

            return riffChunk;
        }
Ejemplo n.º 11
0
 /// <summary>
 /// Creates a copy of the <see cref="RiffChunk"/>.
 /// </summary>
 /// <returns>A new copy of the <see cref="RiffChunk"/>.</returns>
 public RiffChunk Clone()
 {
     RiffChunk riffChunk = new RiffChunk(m_typeID);
     riffChunk.ChunkSize = m_chunkSize;
     return riffChunk;
 }
Ejemplo n.º 12
0
        /// <summary>
        /// Constructor for derived classes used to initialize and validate  <see cref="RiffChunk"/> properties.
        /// </summary>
        /// <param name="preRead">Pre-parsed <see cref="RiffChunk"/> header.</param>
        /// <param name="typeID">Expected type ID.</param>
        protected RiffChunk(RiffChunk preRead, string typeID)
        {
            if (typeID != preRead.TypeID)
                throw new InvalidDataException(string.Format("{0} chunk expected but got {1}, file does not appear to be valid", typeID, preRead.TypeID));

            m_typeID = preRead.TypeID;
            m_chunkSize = preRead.ChunkSize;
        }
Ejemplo n.º 13
0
        // Static Methods

        /// <summary>
        /// Attempts to read the next RIFF chunk from the <paramref name="source"/> stream.
        /// </summary>
        /// <param name="source">Source stream for next RIFF chunk.</param>
        /// <returns>Next RIFF chunk read from the <paramref name="source"/> stream.</returns>
        /// <exception cref="InvalidOperationException">RIFF chunk too small, media file corrupted.</exception>
        public static RiffChunk ReadNext(Stream source)
        {
            RiffChunk riffChunk = new RiffChunk();
            int length = riffChunk.BinaryLength;

            byte[] buffer = BufferPool.TakeBuffer(length);

            try
            {
                int bytesRead = source.Read(buffer, 0, length);

                if (bytesRead < length)
                    throw new InvalidOperationException("RIFF chunk too small, media file corrupted");

                riffChunk.TypeID = Encoding.ASCII.GetString(buffer, 0, 4);
                riffChunk.ChunkSize = EndianOrder.LittleEndian.ToInt32(buffer, 4);

                return riffChunk;
            }
            finally
            {
                if (buffer != null)
                    BufferPool.ReturnBuffer(buffer);
            }
        }