/// <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(); }
public Interval(Time <TTime> initialTime, Duration <TTime> duration) { HoloDebug.Assert(duration >= 0); InitialTime = initialTime; Duration = duration; _isInitialized = true; }
/// <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); }
/// <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(); }
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; }
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); }
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); }
public Duration(long count) { HoloDebug.Assert(count >= 0); _count = count; }
/// <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)); }
/// <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; }