예제 #1
0
 /// <summary>
 /// Summarizes an enumerable of double messages into summarized doubles.
 /// </summary>
 /// <param name="messages">Enumerable of double messages.</param>
 /// <param name="interval">The time interval each summary value should cover.</param>
 /// <returns>List of summarized doubles.</returns>
 public static List <IntervalData <double> > Summarizer(IEnumerable <Message <double> > messages, TimeSpan interval)
 {
     return(messages
            .OrderBy(msg => msg.OriginatingTime)
            .GroupBy(msg => GetIntervalStartTime(msg.OriginatingTime, interval))
            .Select(
                group =>
     {
         var firstMessage = group.First();
         var lastMessage = group.Last();
         return IntervalData.Create(
             lastMessage.Data,                                            // Take last value as representative value for plotting
             group.Min(m => m.Data),                                      // Minimum value
             group.Max(m => m.Data),                                      // Maximum value
             firstMessage.OriginatingTime,                                // First message's OT
             lastMessage.OriginatingTime - firstMessage.OriginatingTime); // Interval between first and last messages
     }).ToList());
 }
예제 #2
0
 private static List <IntervalData <object> > Summarizer(IEnumerable <Message <T> > messages, TimeSpan interval)
 {
     return(messages
            .OrderBy(msg => msg.OriginatingTime)
            .GroupBy(msg => GetIntervalStartTime(msg.OriginatingTime, interval))
            .Select(
                group =>
     {
         var firstMessage = group.First();
         var lastMessage = group.Last();
         var representative = (object)firstMessage.Data;
         return IntervalData.Create(
             representative,
             default(object),
             default(object),
             firstMessage.OriginatingTime,                                // First message's OT
             lastMessage.OriginatingTime - firstMessage.OriginatingTime); // Interval between first and last messages
     }).ToList());
 }
예제 #3
0
        /// <summary>
        /// Summarizes an enumerable of double messages into summarized doubles.
        /// </summary>
        /// <typeparam name="T">The type of messages to summarize.</typeparam>
        /// <param name="messages">Enumerable of double messages.</param>
        /// <param name="interval">The time interval each summary value should cover.</param>
        /// <returns>List of summarized doubles.</returns>
        internal static List <IntervalData <T> > Summarizer <T>(IEnumerable <Message <T> > messages, TimeSpan interval)
        {
            return(messages
                   .OrderBy(msg => msg.OriginatingTime)
                   .GroupBy(msg => Summarizer <T, T> .GetIntervalStartTime(msg.OriginatingTime, interval))
                   .Select(
                       group =>
            {
                var firstMessage = group.First();
                var lastMessage = group.Last();

                // Use the last value as representative for summarization, with the first message
                // originating time.
                return IntervalData.Create(
                    value: lastMessage.Data,
                    minimum: group.Min(m => m.Data),
                    maximum: group.Max(m => m.Data),
                    originatingTime: firstMessage.OriginatingTime,
                    interval: lastMessage.OriginatingTime - firstMessage.OriginatingTime);
            }).ToList());
        }
예제 #4
0
        /// <summary>
        /// Summarizes an enumerable of time interval messages into summarized time intervals.
        /// </summary>
        /// <param name="messages">Enumerable of time interval messages.</param>
        /// <param name="interval">The time interval each summary value should cover.</param>
        /// <returns>List of summarized time intervals.</returns>
        public static List <IntervalData <Tuple <DateTime, DateTime> > > Summarizer(IEnumerable <Message <Tuple <DateTime, DateTime> > > messages, TimeSpan interval)
        {
            return(messages
                   .OrderBy(msg => msg.OriginatingTime)
                   .GroupBy(msg => GetIntervalStartTime(msg.OriginatingTime, interval))
                   .Select(
                       group =>
            {
                var firstMessage = group.First();
                var lastMessage = group.Last();
                var ascendingLatencies = group.OrderBy(m => m.Data.Item2 - m.Data.Item1).Select(m => m.Data);
                var minLatency = ascendingLatencies.First();
                var maxLatency = ascendingLatencies.Last();

                // Use max latency as representative value
                return IntervalData.Create(
                    maxLatency,
                    minLatency,
                    maxLatency,
                    firstMessage.OriginatingTime,
                    lastMessage.OriginatingTime - firstMessage.OriginatingTime);
            }).ToList());
        }
예제 #5
0
        /// <summary>
        /// Summarizes an enumerable of audio buffer messages into summarized audio data.
        /// </summary>
        /// <param name="messages">Enumerable of audio buffer messages.</param>
        /// <param name="interval">The time interval each summary value should cover.</param>
        /// <param name="channel">The audio channel to summarize.</param>
        /// <returns>List of summarized audio data.</returns>
        public static List <IntervalData <double> > Summarizer(IEnumerable <Message <AudioBuffer> > messages, TimeSpan interval, ushort channel)
        {
            var intervalData = new List <IntervalData <double> >();

            // Inspect the first message and only continue if it exists
            Message <AudioBuffer> first = messages.FirstOrDefault();

            if (first != default(Message <AudioBuffer>))
            {
                // Assume audio format is the same for all items
                WaveFormat audioFormat = first.Data.Format;

                // Get the appropriate sample converter. Assumption is 16-bit samples
                // are integer and 32-bit samples are floating point values.
                Func <byte[], int, double> sampleConverter;
                switch (audioFormat.BitsPerSample)
                {
                case 16:
                    sampleConverter = (buf, i) => BitConverter.ToInt16(buf, i);
                    break;

                case 32:
                    sampleConverter = (buf, i) => BitConverter.ToSingle(buf, i);
                    break;

                default:
                    sampleConverter = (buf, i) => buf[i];
                    break;
                }

                TimeSpan samplingInterval = TimeSpan.FromTicks(TimeSpan.TicksPerSecond / audioFormat.SamplesPerSec);
                int      byteOffset       = 0 + ((channel % audioFormat.Channels) * audioFormat.BitsPerSample / 8);

                DateTime currentIntervalStartTime = GetIntervalStartTime(first.OriginatingTime, interval);
                double   min = double.MaxValue;
                double   max = double.MinValue;

                foreach (var message in messages)
                {
                    // Each item holds an AudioBuffer containing multiple audio samples
                    AudioBuffer audioBuffer = message.Data;

                    // Start (originating time) of the first sample in the AudioBuffer
                    DateTime currentTime = message.OriginatingTime - audioBuffer.Duration;

                    // calculate min/max for specified channel over the entire audio buffer
                    for (int offset = byteOffset; offset < audioBuffer.Length; offset += audioFormat.BlockAlign)
                    {
                        DateTime intervalStartTime = GetIntervalStartTime(currentTime, interval);

                        // Check if we are still in the current interval. If not, commit the current
                        // min/max values to the current interval if they have non-default values.
                        if ((intervalStartTime != currentIntervalStartTime) && (min != double.MaxValue) && (max != double.MinValue))
                        {
                            var current = IntervalData.Create(min + ((max - min) / 2), min, max, currentIntervalStartTime, interval);
                            intervalData.Add(current);

                            // Reset min-max for next interval
                            min = double.MaxValue;
                            max = double.MinValue;

                            // Update next interval start time
                            currentIntervalStartTime = intervalStartTime;
                        }

                        // Update min-max range for the current interval
                        double sampleValue = sampleConverter(audioBuffer.Data, offset);
                        if (sampleValue < min)
                        {
                            min = sampleValue;
                        }

                        if (sampleValue > max)
                        {
                            max = sampleValue;
                        }

                        // Increment by the sampling interval
                        currentTime += samplingInterval;
                    }
                }

                // Add the last interval
                intervalData.Add(IntervalData.Create(min + ((max - min) / 2), min, max, currentIntervalStartTime, interval));
            }

            return(intervalData);
        }
예제 #6
0
        /// <summary>
        /// Summarizes an enumerable of double messages into summarized doubles.
        /// </summary>
        /// <typeparam name="TKey">The type of the series key.</typeparam>
        /// <typeparam name="T">The type of messages to summarize.</typeparam>
        /// <param name="messages">Enumerable of double messages.</param>
        /// <param name="interval">The time interval each summary value should cover.</param>
        /// <returns>List of summarized doubles.</returns>
        internal static List <IntervalData <Dictionary <TKey, T> > > SeriesSummarizer <TKey, T>(IEnumerable <Message <Dictionary <TKey, T> > > messages, TimeSpan interval)
        {
            return(messages
                   .OrderBy(msg => msg.OriginatingTime)
                   .GroupBy(msg => Summarizer <T, T> .GetIntervalStartTime(msg.OriginatingTime, interval))
                   .Select(
                       group =>
            {
                var firstMessage = group.First();
                var lastMessage = group.Last();
                var min = new Dictionary <TKey, T>();
                var max = new Dictionary <TKey, T>();

                foreach (var message in group)
                {
                    foreach (var kvp in message.Data)
                    {
                        // Update min
                        if (!min.ContainsKey(kvp.Key))
                        {
                            min.Add(kvp.Key, kvp.Value);
                        }
                        else if (kvp.Value is IComparable <T> comparable)
                        {
                            if (comparable.CompareTo(min[kvp.Key]) == -1)
                            {
                                min[kvp.Key] = kvp.Value;
                            }
                        }
                        else if (kvp.Value is IComparable untypedComparable)
                        {
                            if (untypedComparable.CompareTo(min[kvp.Key]) == -1)
                            {
                                min[kvp.Key] = kvp.Value;
                            }
                        }
                        else
                        {
                            throw new InvalidOperationException("Cannot summarize over values that are not comparable.");
                        }

                        // Update max
                        if (!max.ContainsKey(kvp.Key))
                        {
                            max.Add(kvp.Key, kvp.Value);
                        }
                        else if (kvp.Value is IComparable <T> comparable)
                        {
                            if (comparable.CompareTo(max[kvp.Key]) == 1)
                            {
                                max[kvp.Key] = kvp.Value;
                            }
                        }
                        else if (kvp.Value is IComparable untypedComparable)
                        {
                            if (untypedComparable.CompareTo(max[kvp.Key]) == 1)
                            {
                                max[kvp.Key] = kvp.Value;
                            }
                        }
                        else
                        {
                            throw new InvalidOperationException("Cannot summarize over values that are not comparable.");
                        }
                    }
                }

                // Use the last value as representative for summarization, with the first message
                // originating time.
                return IntervalData.Create(
                    value: lastMessage.Data,
                    minimum: min,
                    maximum: max,
                    originatingTime: firstMessage.OriginatingTime,
                    interval: lastMessage.OriginatingTime - firstMessage.OriginatingTime);
            }).ToList());
        }
예제 #7
0
        /// <summary>
        /// Combines two numeric series interval data values.
        /// </summary>
        /// <typeparam name="TKey">The type of the series key.</typeparam>
        /// <typeparam name="T">The type of messages to summarize.</typeparam>
        /// <param name="left">The first value to combine.</param>
        /// <param name="right">The second value to combine.</param>
        /// <returns>The combined value.</returns>
        internal static IntervalData <Dictionary <TKey, T> > SeriesCombiner <TKey, T>(IntervalData <Dictionary <TKey, T> > left, IntervalData <Dictionary <TKey, T> > right)
        {
            Comparer <T> comparer = Comparer <T> .Default;
            var          min      = new Dictionary <TKey, T>();

            foreach (var key in left.Minimum.Keys.Union(right.Minimum.Keys).Distinct())
            {
                if (left.Minimum.ContainsKey(key))
                {
                    if (right.Minimum.ContainsKey(key))
                    {
                        min.Add(key, comparer.Compare(left.Minimum[key], right.Minimum[key]) < 0 ? left.Minimum[key] : right.Minimum[key]);
                    }
                    else
                    {
                        min.Add(key, left.Minimum[key]);
                    }
                }
                else
                {
                    min.Add(key, right.Minimum[key]);
                }
            }

            var max = new Dictionary <TKey, T>();

            foreach (var key in left.Maximum.Keys.Union(right.Maximum.Keys).Distinct())
            {
                if (left.Maximum.ContainsKey(key))
                {
                    if (right.Maximum.ContainsKey(key))
                    {
                        max.Add(key, comparer.Compare(left.Maximum[key], right.Maximum[key]) > 0 ? left.Maximum[key] : right.Maximum[key]);
                    }
                    else
                    {
                        max.Add(key, left.Maximum[key]);
                    }
                }
                else
                {
                    max.Add(key, right.Maximum[key]);
                }
            }

            Dictionary <TKey, T> value;
            DateTime             originatingTime;

            // Take the value which occurs last, and the time which occurs first
            if (left.OriginatingTime <= right.OriginatingTime)
            {
                value           = right.Value;
                originatingTime = left.OriginatingTime;
            }
            else
            {
                value           = left.Value;
                originatingTime = right.OriginatingTime;
            }

            // Take the whichever end time occurs last and use it to find the interval
            TimeSpan interval = (right.EndTime > left.EndTime ? right.EndTime : left.EndTime) - originatingTime;

            return(IntervalData.Create(value, min, max, originatingTime, interval));
        }