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)); }
public static async Task <UInt32> ReadUInt32Async(this IBinaryStream stream, ByteOrder byteOrder) { var buffer = await stream.ReadAsync(4).ConfigureAwait(false); var value = 0U; for (var i = 0; i < 4; i++) { value |= (UInt32)buffer[i] << 8 * ((byteOrder == ByteOrder.BigEndian) ? (3 - i) : i); } return(value); }
public static async Task <XingFrame> CreateAsync(IBinaryStream stream, Frame frame) { var position = stream.Position; stream.Position = frame.Offset; var data = await stream.ReadAsync(40).ConfigureAwait(false); var index = data.IndexOf("Xing"); stream.Position = frame.Offset + index.Value + 4; var framesCount = (UInt32?)null; var bytesCount = (UInt32?)null; var toc = (Byte[])null; var quality = (UInt32?)null; var flags = await stream.ReadUInt32Async(ByteOrder.BigEndian).ConfigureAwait(false); if ((flags & 0x01) > 0) { framesCount = await stream.ReadUInt32Async(ByteOrder.BigEndian).ConfigureAwait(false); } if ((flags & 0x02) > 0) { bytesCount = await stream.ReadUInt32Async(ByteOrder.BigEndian).ConfigureAwait(false); } if ((flags & 0x04) > 0) { toc = await stream.ReadAsync(100).ConfigureAwait(false); } if ((flags & 0x08) > 0) { quality = await stream.ReadUInt32Async(ByteOrder.BigEndian).ConfigureAwait(false); } stream.Position = position; return(new XingFrame() { FramesCount = framesCount, BytesCount = bytesCount, Quality = quality }); }
public static async Task <Int32> ReadInt32Async(this IBinaryStream stream, Byte amount, ByteOrder byteOrder) { if (amount > 4) { throw new ArgumentOutOfRangeException(); } var buffer = await stream.ReadAsync(amount).ConfigureAwait(false); var value = 0; for (var i = 0; i < amount; i++) { value |= buffer[i] << 8 * ((byteOrder == ByteOrder.BigEndian) ? (amount - i - 1) : i); } return(value); }
public static async Task <Byte> ReadByteAsync(this IBinaryStream stream) { var buffer = await stream.ReadAsync(1).ConfigureAwait(false); return(buffer[0]); }
public static async Task <String> ReadStringAsync(this IBinaryStream stream, UInt32 length) { var buffer = await stream.ReadAsync(length).ConfigureAwait(false); return(Encoding.UTF8.GetString(buffer, 0, (Int32)length)); }
public static async Task <UInt16> ReadUInt16Async(this IBinaryStream stream, ByteOrder byteOrder) { var buffer = await stream.ReadAsync(2).ConfigureAwait(false); return((UInt16)((byteOrder == ByteOrder.BigEndian) ? ((buffer[0] << 8) | buffer[1]) : (buffer[0] | (buffer[1] << 8)))); }
public static Task <Byte[]> GetDataAsync(IBinaryStream stream, DataLocation dataLocation) { stream.Position = dataLocation.Position; return(stream.ReadAsync(dataLocation.Length)); }
public static async Task <Id3v2> ParseAsync(IBinaryStream stream) { stream.Position += 3; var id3v2 = new Id3v2(); var majorVersion = await stream.ReadByteAsync().ConfigureAwait(false); var revision = await stream.ReadByteAsync().ConfigureAwait(false); var flags = await stream.ReadByteAsync().ConfigureAwait(false); var size = Id3v2.DecodeSize(await stream.ReadUInt32Async(ByteOrder.BigEndian).ConfigureAwait(false)); var endingPosition = stream.Position + size; while (stream.Position < endingPosition) { var frameId = await stream.ReadStringAsync(4).ConfigureAwait(false); if (!Id3v2.IsValidAlphaNumeric(frameId)) { stream.Position = endingPosition; break; } var frameSize = 0U; switch (majorVersion) { case 4: frameSize = Id3v2.DecodeSize(await stream.ReadUInt32Async(ByteOrder.BigEndian).ConfigureAwait(false)); break; case 3: frameSize = await stream.ReadUInt32Async(ByteOrder.BigEndian).ConfigureAwait(false); break; default: throw new NotSupportedException(); } var frameFlags = await stream.ReadUInt16Async(ByteOrder.LittleEndian).ConfigureAwait(false); switch (frameId) { case "TIT2": id3v2.Title = Id3v2.DecodeString(await stream.ReadAsync(frameSize).ConfigureAwait(false)); break; case "TALB": id3v2.Album = Id3v2.DecodeString(await stream.ReadAsync(frameSize).ConfigureAwait(false)); break; case "TOAL": break; case "TPE1": id3v2.Artist = Id3v2.DecodeString(await stream.ReadAsync(frameSize).ConfigureAwait(false)); break; case "TPE2": id3v2.AlbumArtist = Id3v2.DecodeString(await stream.ReadAsync(frameSize).ConfigureAwait(false)); break; case "TRCK": var track = Id3v2.DecodeString(await stream.ReadAsync(frameSize).ConfigureAwait(false)); if (track != null) { id3v2.Track = ParseTrack(track); } break; case "TYER": var year = Id3v2.DecodeString(await stream.ReadAsync(frameSize).ConfigureAwait(false)); if (year != null) { id3v2.Year = ParseYear(year); } break; case "APIC": var readBytes = 0U; var encoding = (FrameEncoding)await stream.ReadByteAsync().ConfigureAwait(false); readBytes++; while (await stream.ReadByteAsync().ConfigureAwait(false) != 0) // MIME type <text string> $00 { readBytes++; } readBytes++; var pictureType = await stream.ReadByteAsync().ConfigureAwait(false); readBytes++; while (await stream.ReadByteAsync().ConfigureAwait(false) != 0) // <text string according to encoding> $00 (00) { readBytes++; } id3v2.Cover = new DataLocation(stream.Position, frameSize - readBytes - 1); stream.Position += frameSize - readBytes - 1; break; case "TCON": case "COMM": default: stream.Position += frameSize; break; } } return(id3v2); }