/// <summary>
        /// Reads data from this stream
        /// </summary>
        /// <param name="buffer"></param>
        /// <param name="offset"></param>
        /// <param name="count"></param>
        /// <returns></returns>
        public override int Read(byte[] buffer, int offset, int count)
        {
            lock (this)
            {
                // 1. attempt to fill the circular buffer with enough data to meet our request
                while (BufferEndPosition < position + count)
                {
                    int sourceReadCount = count;
                    if (sourceReadCount % sourceStream.BlockAlign != 0)
                    {
                        sourceReadCount = (count + sourceStream.BlockAlign) - (count % sourceStream.BlockAlign);
                    }

                    int sourceRead = sourceStream.Read(GetSourceBuffer(sourceReadCount), 0, sourceReadCount);
                    circularBuffer.Write(GetSourceBuffer(sourceReadCount), 0, sourceRead);
                    if (sourceRead == 0)
                    {
                        // assume we have run out of data
                        break;
                    }
                }

                // 2. discard any unnecessary stuff from the start
                if (bufferStartPosition < position)
                {
                    circularBuffer.Advance((int)(position - bufferStartPosition));
                    bufferStartPosition = position;
                }

                // 3. now whatever is in the buffer we can return
                int bytesRead = circularBuffer.Read(buffer, offset, count);
                position += bytesRead;
                // anything left in buffer is at start position
                bufferStartPosition = position;

                return(bytesRead);
            }
        }