Example #1
0
        public static RemoteSegmentWithData[] DedupeSegments(IList <RemoteSegmentWithData> segments)
        {
            // ugggh don't really need a dictionary but HashSet doesn't allow retrieveal of values
            var unique = new Dictionary <RemoteSegment, RemoteSegmentWithData>(segments.Count);

            foreach (var segment in segments)
            {
                var exists = unique.ContainsKey(segment);

                if (exists)
                {
                    var current = unique[segment];

                    Contract.Ensures(unique.Remove(segment));

                    var data = current.Data.Concat(segment.Data).ToArray();

                    var combined = new RemoteSegmentWithData(current.Source, current.Offsets, data);

                    unique.Add(combined, combined);
                }
                else
                {
                    unique.Add(segment, segment);
                }
            }

            return(unique.Values.ToArray());
        }
Example #2
0
        private async Task <IEnumerable <RemoteSegmentWithData> > DownloadRemoteMetadata(
            long audioRecordingId,
            IEnumerable <ImportedEvent> events)
        {
            // now download the metadata for the audio recording

            Log.Debug($"Requesting metadata for audio recording media {audioRecordingId}");
            var audioRecording = await this.audioRecordingService.GetAudioRecording(audioRecordingId);

            Log.Trace(
                $"Metadata for audio recording media {audioRecordingId} retrieved, generating segments for associated events");

            // now generate the segments
            // we need to floor the duration to ensure later rounding does round past the limit of the recording
            Log.Verbose($"Audio recording duration {audioRecording.DurationSeconds} will be floored");
            var limit   = audioRecording.DurationSeconds.Floor().AsIntervalFromZero();
            var results = new List <RemoteSegmentWithData>(20);

            foreach (var importedEvent in events)
            {
                var target = (importedEvent.EventStartSeconds.Value, importedEvent.EventEndSeconds.Value).AsInterval();

                // determine how much padding is required (dynamically scales with event size
                var padding = this.AnalysisDurationSeconds(target.Size());

                if (target.Size() + padding > MediaService.MediaDownloadMaximumSeconds)
                {
                    var newPadding = MediaService.MediaDownloadMaximumSeconds - target.Size();
                    Log.Warn(
                        $"Audio event size {audioRecordingId},{target} and padding {padding} exceeds maximum media " +
                        $"download amount - trimming padding from {padding}, to {newPadding}");
                    padding = newPadding;
                }

                // grow target to required analysis length
                // we round the grow size to the nearest integer so that we reduce caching combinatorics in the workbench
                Log.Trace($"Growing target event from {audioRecordingId},{target} by {padding} seconds");
                var analysisRange = target.Grow(limit, padding, 0);

                var segment = new RemoteSegmentWithData(audioRecording, analysisRange, importedEvent.AsArray());

                results.Add(segment);
            }

            return(DedupeSegments(results));
        }