/// <summary>
        /// Internally append this slice (which must be allocated from our free buffer); this does the work
        /// of coalescing, updating _data and other fields, etc.
        /// </summary>
        Slice <TTime, TValue> InternalAppend(Slice <TTime, TValue> dest)
        {
            // dest must be from our free buffer
            HoloDebug.Assert(dest.Buffer.Data == _remainingFreeBuffer.Buffer.Data);

            if (_data.Count == 0)
            {
                _data.Add(new TimedSlice <TTime, TValue>(InitialTime, dest));
            }
            else
            {
                TimedSlice <TTime, TValue> last = _data[_data.Count - 1];
                if (last.Slice.Precedes(dest))
                {
                    _data[_data.Count - 1] = new TimedSlice <TTime, TValue>(last.InitialTime, last.Slice.UnionWith(dest));
                }
                else
                {
                    Spam.Audio.WriteLine("BufferedSliceStream.InternalAppend: last did not precede; last slice is " + last.Slice + ", last slice time " + last.InitialTime + ", dest is " + dest);
                    _data.Add(new TimedSlice <TTime, TValue>(last.InitialTime + last.Slice.Duration, dest));
                }
            }

            _discreteDuration   += dest.Duration;
            _remainingFreeBuffer = _remainingFreeBuffer.SubsliceStartingAt(dest.Duration);

            return(dest);
        }
        /// <summary>
        /// Append this slice's data, by copying it into this stream's private buffers.
        /// </summary>
        public override void Append(Slice <TTime, TValue> source)
        {
            HoloDebug.Assert(!IsShut);

            // Try to keep copying source into _remainingFreeBuffer
            while (!source.IsEmpty())
            {
                EnsureFreeBuffer();

                // if source is larger than available free buffer, then we'll iterate
                Slice <TTime, TValue> originalSource = source;
                if (source.Duration > _remainingFreeBuffer.Duration)
                {
                    source = source.Subslice(0, _remainingFreeBuffer.Duration);
                }

                // now we know source can fit
                Slice <TTime, TValue> dest = _remainingFreeBuffer.SubsliceOfDuration(source.Duration);
                source.CopyTo(dest);

                // dest may well be adjacent to the previous slice, if there is one, since we may
                // be appending onto an open chunk.  So here is where we coalesce this, if so.
                dest = InternalAppend(dest);

                // and update our loop variables
                source = originalSource.SubsliceStartingAt(source.Duration);

                Trim();
            }
        }