/// <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();
            }
        }
        /// <summary>
        /// Copy strided data from a source array into a single destination sliver.
        /// </summary>
        public override void AppendSliver(TValue[] source, int startOffset, int width, int stride, int height)
        {
            HoloDebug.Assert(source != null);
            int neededLength = startOffset + stride * (height - 1) + width;

            HoloDebug.Assert(source.Length >= neededLength);
            HoloDebug.Assert(SliverSize == width * height);
            HoloDebug.Assert(stride >= width);

            EnsureFreeBuffer();

            Slice <TTime, TValue> destination = _remainingFreeBuffer.SubsliceOfDuration(1);

            int sourceOffset      = startOffset;
            int destinationOffset = 0;

            for (int h = 0; h < height; h++)
            {
                destination.CopyFrom(source, sourceOffset, destinationOffset, width);

                sourceOffset      += stride;
                destinationOffset += width;
            }

            InternalAppend(destination);

            Trim();
        }
示例#4
0
        public Interval(Time <TTime> initialTime, Duration <TTime> duration)
        {
            HoloDebug.Assert(duration >= 0);

            InitialTime    = initialTime;
            Duration       = duration;
            _isInitialized = true;
        }
示例#5
0
        /// <summary>
        /// Append the given amount of data marshalled from the pointer P.
        /// </summary>
        public void Append(Time <TTime> absoluteTime, IntPtr p)
        {
            HoloDebug.Assert(!IsShut);
            HoloDebug.Assert(TimeIsAfterLast(absoluteTime));

            _innerStream.Append(1, p);
            _times.Add(absoluteTime);

            Trim();
        }
 /// <summary>
 /// Shut the stream; no further appends may be accepted.
 /// </summary>
 /// <param name="finalDuration">The possibly fractional duration to be associated with the stream;
 /// must be strictly equal to, or less than one sample smaller than, the discrete duration.</param>
 public override void Shut(ContinuousDuration finalDuration)
 {
     HoloDebug.Assert(!IsShut);
     // Should always have as many samples as the rounded-up finalDuration.
     // The precise time matching behavior is that a loop will play either Math.Floor(finalDuration)
     // or Math.Ceiling(finalDuration) samples on each iteration, such that it remains perfectly in
     // time with finalDuration's fractional value.  So, a shut loop should have DiscreteDuration
     // equal to rounded-up ContinuousDuration.
     HoloDebug.Assert((int)Math.Ceiling((double)finalDuration) == (int)DiscreteDuration);
     base.Shut(finalDuration);
 }
示例#7
0
        /// <summary>
        /// Append this slice's data, by copying it into this stream's private buffers.
        /// </summary>
        public void Append(Time <TTime> absoluteTime, Slice <Frame, TValue> source)
        {
            HoloDebug.Assert(!IsShut);
            HoloDebug.Assert(source.Duration == 1);
            HoloDebug.Assert(TimeIsAfterLast(absoluteTime));

            _innerStream.Append(source);
            _times.Add(absoluteTime);

            Trim();
        }
示例#8
0
        public Slice(Buf <TValue> buffer, Duration <TTime> offset, Duration <TTime> duration, int sliverSize)
        {
            HoloDebug.Assert(buffer.Data != null);
            HoloDebug.Assert(offset >= 0);
            HoloDebug.Assert(duration >= 0);
            HoloDebug.Assert((offset * sliverSize) + (duration * sliverSize) <= buffer.Data.Length);

            _buffer    = buffer;
            _offset    = offset;
            Duration   = duration;
            SliverSize = sliverSize;
        }
        /// <summary>
        /// Append the given amount of data marshalled from the pointer P.
        /// </summary>
        public override void Append(Duration <TTime> duration, IntPtr p)
        {
            HoloDebug.Assert(!IsShut);

            while (duration > 0)
            {
                Slice <TTime, TValue> tempSlice = TempSlice(duration);

                _copyIntPtrToSliceAction(p, tempSlice);
                Append(tempSlice);
                duration -= tempSlice.Duration;
            }
            _discreteDuration += duration;
        }
示例#10
0
        public override Interval <TTime> MapNextSubInterval(Interval <TTime> input)
        {
            HoloDebug.Assert(input.InitialTime >= _stream.InitialTime);
            Duration <TTime> inputDelayDuration = input.InitialTime - _stream.InitialTime;

            // now we want to take that modulo the *discrete* duration
            inputDelayDuration %= _stream.DiscreteDuration;
            Duration <TTime> mappedDuration = Math.Min((long)input.Duration, (long)(_stream.DiscreteDuration - inputDelayDuration));
            Interval <TTime> ret            = new Interval <TTime>(_stream.InitialTime + inputDelayDuration, mappedDuration);

            Spam.Audio.WriteLine("SimpleLoopingIntervalMapper.MapNextSubInterval: _stream " + _stream + ", input " + input + ", ret " + ret);

            return(ret);
        }
示例#11
0
        public void AppendSliver(Time <TTime> absoluteTime, TValue[] source, int startOffset, int width, int stride, int height)
        {
            HoloDebug.Assert(!IsShut);

            if (_times.Count > 0 && _times[_times.Count - 1] == absoluteTime)
            {
                // BUGBUG? Is this a sign of major slowdown?
                return;
            }

            HoloDebug.Assert(TimeIsAfterLast(absoluteTime));

            _innerStream.AppendSliver(source, startOffset, width, stride, height);
            _times.Add(absoluteTime);

            Trim();
        }
        /// <summary>
        /// Trim off any content beyond the maximum allowed to be buffered.
        /// </summary>
        /// <remarks>
        /// Internal because wrapper streams want to delegate to this when they are themselves Trimmed.</remarks>
        void Trim()
        {
            if (_maxBufferedDuration == 0 || _discreteDuration <= _maxBufferedDuration)
            {
                return;
            }

            while (DiscreteDuration > _maxBufferedDuration)
            {
                Duration <TTime> toTrim = DiscreteDuration - _maxBufferedDuration;
                // get the first slice
                TimedSlice <TTime, TValue> firstSlice = _data[0];
                if (firstSlice.Slice.Duration <= toTrim)
                {
                    _data.RemoveAt(0);
#if DEBUG
                    // check to make sure our later stream data doesn't reference this one we're about to free
                    foreach (TimedSlice <TTime, TValue> slice in _data)
                    {
                        HoloDebug.Assert(slice.Slice.Buffer.Data != firstSlice.Slice.Buffer.Data);
                    }
#endif
                    _allocator.Free(firstSlice.Slice.Buffer);
                    _discreteDuration -= firstSlice.Slice.Duration;
                    _initialTime      += firstSlice.Slice.Duration;
                }
                else
                {
                    TimedSlice <TTime, TValue> newFirstSlice = new TimedSlice <TTime, TValue>(
                        firstSlice.InitialTime + toTrim,
                        new Slice <TTime, TValue>(
                            firstSlice.Slice.Buffer,
                            firstSlice.Slice.Offset + toTrim,
                            firstSlice.Slice.Duration - toTrim,
                            SliverSize));
                    _data[0]           = newFirstSlice;
                    _discreteDuration -= toTrim;
                    _initialTime      += toTrim;
                }
            }
        }
        /// <summary>
        /// Map the interval time to stream local time, and get the next slice of it.
        /// </summary>
        /// <param name="interval"></param>
        /// <returns></returns>
        public override Slice <TTime, TValue> GetNextSliceAt(Interval <TTime> interval)
        {
            Interval <TTime> firstMappedInterval = _intervalMapper.MapNextSubInterval(interval);

            if (firstMappedInterval.IsEmpty)
            {
                return(Slice <TTime, TValue> .Empty);
            }

            HoloDebug.Assert(firstMappedInterval.InitialTime >= InitialTime);
            HoloDebug.Assert(firstMappedInterval.InitialTime + firstMappedInterval.Duration <= InitialTime + DiscreteDuration);

            TimedSlice <TTime, TValue> foundTimedSlice = GetInitialTimedSlice(firstMappedInterval);
            Interval <TTime>           intersection    = foundTimedSlice.Interval.Intersect(firstMappedInterval);

            HoloDebug.Assert(!intersection.IsEmpty);
            Slice <TTime, TValue> ret = foundTimedSlice.Slice.Subslice(
                intersection.InitialTime - foundTimedSlice.InitialTime,
                intersection.Duration);

            return(ret);
        }
        TimedSlice <TTime, TValue> GetInitialTimedSlice(Interval <TTime> firstMappedInterval)
        {
            // we must overlap somewhere
            HoloDebug.Assert(!firstMappedInterval.Intersect(new Interval <TTime>(InitialTime, DiscreteDuration)).IsEmpty);

            // Get the biggest available slice at firstMappedInterval.InitialTime.
            // First, get the index of the slice just after the one we want.
            TimedSlice <TTime, TValue> target = new TimedSlice <TTime, TValue>(firstMappedInterval.InitialTime, Slice <TTime, TValue> .Empty);
            int originalIndex = _data.BinarySearch(target, TimedSlice <TTime, TValue> .Comparer.Instance);
            int index         = originalIndex;

            if (index < 0)
            {
                // index is then the index of the next larger element
                // -- we know there is a smaller element because we know firstMappedInterval fits inside stream interval
                index = (~index) - 1;
                HoloDebug.Assert(index >= 0);
            }

            TimedSlice <TTime, TValue> foundTimedSlice = _data[index];

            return(foundTimedSlice);
        }
示例#15
0
 public Duration(long count)
 {
     HoloDebug.Assert(count >= 0);
     _count = count;
 }
示例#16
0
 /// <summary>Merge two adjacent samples into a single sample.</summary>
 public Slice <TTime, TValue> UnionWith(Slice <TTime, TValue> next)
 {
     HoloDebug.Assert(Precedes(next));
     return(new Slice <TTime, TValue>(_buffer, _offset, Duration + next.Duration, SliverSize));
 }
示例#17
0
 /// <summary>
 /// Shut the stream; no further appends may be accepted.
 /// </summary>
 /// <param name="finalDuration">The possibly fractional duration to be associated with the stream;
 /// must be strictly equal to, or less than one sample smaller than, the discrete duration.</param>
 public virtual void Shut(ContinuousDuration finalDuration)
 {
     HoloDebug.Assert(!IsShut);
     _isShut             = true;
     _continuousDuration = finalDuration;
 }