/// <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); }
public int Compare(TimedSlice <TTime, TValue> x, TimedSlice <TTime, TValue> y) { if (x.InitialTime < y.InitialTime) { return(-1); } else if (x.InitialTime > y.InitialTime) { return(1); } else { return(0); } }
/// <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); }