private static async Task <Tuple <List <Frame>, BitrateType, TimeSpan, UInt32> > CollectSamplesAsync(IBinaryStream stream, UInt32 streamLength, UInt32?amount) { var samples = new List <Frame>(); var bitrateType = BitrateType.Constant; var duration = new TimeSpan(); var bitrateSum = 0U; var originalPosition = stream.Position; while (stream.Position + 20 < streamLength) { if (amount.HasValue && (samples.Count == amount.Value)) { break; } var possibleFrameHeader = await stream.PeekUInt32Async(ByteOrder.BigEndian).ConfigureAwait(false); if ((possibleFrameHeader & 0xFFFE0000) == 0xFFFA0000) { var bitrate = Frame.GetBitrate(possibleFrameHeader); var frequency = Frame.GetFrequency(possibleFrameHeader); var padding = Frame.GetPadding(possibleFrameHeader); var version = Frame.GetVersion(possibleFrameHeader); var layer = Frame.GetLayer(possibleFrameHeader); if ((bitrate != 0) && (frequency != 0)) { var frame = new Frame(stream.Position, version, layer, bitrate, frequency, padding); if (samples.Count == 0) { var firstFrameContent = await stream.ReadAsync(frame.Length).ConfigureAwait(false); bitrateType = firstFrameContent.IndexOf("Xing").HasValue ? BitrateType.Variable : BitrateType.Constant; } else { stream.Position += frame.Length; duration += frame.Duration; bitrateSum += frame.Bitrate; } samples.Add(frame); continue; } } // this situation means that we've read some samples and haven't found valid sample right after the last valid sample // and it means that the file in wrong format, corrupted or we've found all samples. if (samples.Count > 0) { break; } stream.Position += 1; if (stream.Position - originalPosition > 1024) { break; } } return(new Tuple <List <Frame>, BitrateType, TimeSpan, UInt32>(samples, bitrateType, duration, (samples.Count > 0) ? (UInt32)(bitrateSum / samples.Count) : 0)); }