public override void Shut(ContinuousDuration finalDuration)
        {
            base.Shut(finalDuration);
            // swap out our mappers, we're looping now
            if (_useContinuousLoopingMapper)
            {
                _intervalMapper = new LoopingIntervalMapper <TTime, TValue>(this);
            }
            else
            {
                _intervalMapper = new SimpleLoopingIntervalMapper <TTime, TValue>(this);
            }

#if SPAMAUDIO
            foreach (TimedSlice <TTime, TValue> timedSlice in _data)
            {
                Spam.Audio.WriteLine("BufferedSliceStream.Shut: next slice time " + timedSlice.InitialTime + ", slice " + timedSlice.Slice);
            }
#endif
        }
        public BufferedSliceStream(
            Time <TTime> initialTime,
            BufferAllocator <TValue> allocator,
            int sliverSize,
            Action <IntPtr, Slice <TTime, TValue> > copyIntPtrToSliceAction,
            Action <Slice <TTime, TValue>, IntPtr> copySliceToIntPtrAction,
            Action <Slice <TTime, TValue>, Action <IntPtr, int> > rawSliceAccessAction,
            Duration <TTime> maxBufferedDuration = default(Duration <TTime>),
            bool useContinuousLoopingMapper      = false)
            : base(initialTime, sliverSize)
        {
            _allocator = allocator;
            _copyIntPtrToSliceAction    = copyIntPtrToSliceAction;
            _copySliceToIntPtrAction    = copySliceToIntPtrAction;
            _rawSliceAccessAction       = rawSliceAccessAction;
            _maxBufferedDuration        = maxBufferedDuration;
            _useContinuousLoopingMapper = useContinuousLoopingMapper;

            // as long as we are appending, we use the identity mapping
            // TODO: support delay mapping
            _intervalMapper = new IdentityIntervalMapper <TTime, TValue>(this);
        }