/// <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); } }