Exemplo n.º 1
0
        /// <summary>Reads a new WAVE format section from the specified stream.</summary>
        /// <param name="preRead">Pre-parsed RIFF chunk 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[]>();

            int blockSize = waveFormat.BlockAlignment;
            int sampleSize = waveFormat.BitsPerSample / 8;
            byte[] buffer = new byte[blockSize];
            int channels = waveFormat.Channels;
            LittleBinaryValue[] sampleBlock;

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

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

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

                m_sampleBlocks.Add(sampleBlock);

                bytesRead = source.Read(buffer, 0, blockSize);
            }
        }
Exemplo n.º 2
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)
        {
            Format = format;

            int length = BinaryLength - preRead.BinaryLength;
            byte[] buffer = new byte[length];

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

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

            // Read and validate format stored in RIFF section
            Initialize(buffer, 0, bytesRead);

            if (Format != Format)
                throw new InvalidDataException(string.Format("{0} format expected but got {1}, this does not appear to be a valid {0} file", Format, format));
        }
Exemplo n.º 3
0
        /// <summary>Reads a new WAVE format section from the specified stream.</summary>
        /// <param name="preRead">Pre-parsed RIFF chunk 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>
        public WaveFormatChunk(RiffChunk preRead, Stream source)
            : base(preRead, RiffTypeID)
        {
            int length = ChunkSize;
            byte[] buffer = new byte[length];

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

            if (bytesRead < length)
                throw new InvalidOperationException("WAVE format section too small, wave file corrupted.");

            m_audioFormat = EndianOrder.LittleEndian.ToInt16(buffer, 0);
            m_channels = EndianOrder.LittleEndian.ToInt16(buffer, 2);
            m_sampleRate = EndianOrder.LittleEndian.ToInt32(buffer, 4);
            m_byteRate = EndianOrder.LittleEndian.ToInt32(buffer, 8);
            m_blockAlignment = EndianOrder.LittleEndian.ToInt16(buffer, 12);
            m_bitsPerSample = EndianOrder.LittleEndian.ToInt16(buffer, 14);

            if (m_bitsPerSample % 8 != 0)
                throw new InvalidDataException("Invalid bit rate encountered - wave file bit rates must be a multiple of 8");

            if (length > 16)
            {
                m_extraParametersSize = EndianOrder.LittleEndian.ToInt16(buffer, 16);

                // 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.");
                }
            }
        }
Exemplo n.º 4
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 = new byte[] { 0 };
            int bytesRead = source.Read(buffer, 0, buffer.Length);
            int length, index = 0;
            string key, value;

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

            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;
                }
            }
        }
Exemplo 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);
            }
        }
Exemplo 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);
            }
        }
Exemplo 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 = 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);
            }
        }
Exemplo n.º 8
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 = new byte[length];

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

            // Initialize class from buffer
            Initialize(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.");
            }
        }
Exemplo n.º 9
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 = EndianOrder.LittleEndian.ToInt32(buffer, 4);

            return riffChunk;
        }
Exemplo n.º 10
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;
 }
Exemplo n.º 11
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;
        }