internal static async Task<TagHeader> ReadTagHeader(Stream stream) { var header = new TagHeader(); byte[] headerBytes = ArrayPool<byte>.Shared.Rent(7); await stream.ReadAsync(headerBytes, 0, 7).ConfigureAwait(false); switch (Convert.ToInt32(headerBytes[0])) { case 2: header.Version = TagVersion.V22; break; case 3: header.Version = TagVersion.V23; break; case 4: header.Version = TagVersion.V24; break; default: header.Version = TagVersion.Unknown; break; } header.Unsynchronization = ((headerBytes[2] & 0x80) == 0x80); header.ExtendedHeader = ((headerBytes[2] & 0x40) == 0x40); header.Experimental = ((headerBytes[2] & 0x20) == 0x20); header.HasFooter = ((headerBytes[2] & 0x10) == 0x10); header.TagLength = headerBytes[3] * 128 * 128 * 128 + headerBytes[4] * 128 * 128 + headerBytes[5] * 128 + headerBytes[6]; ArrayPool<byte>.Shared.Return(headerBytes); return header; }
internal static async Task <TagHeader> ReadTagHeader(Stream stream) { var header = new TagHeader(); byte[] headerBytes = ArrayPool <byte> .Shared.Rent(7); await stream.ReadAsync(headerBytes, 0, 7).ConfigureAwait(false); switch (Convert.ToInt32(headerBytes[0])) { case 2: header.Version = TagVersion.V22; break; case 3: header.Version = TagVersion.V23; break; case 4: header.Version = TagVersion.V24; break; default: header.Version = TagVersion.Unknown; break; } header.Unsynchronization = ((headerBytes[2] & 0x80) == 0x80); header.ExtendedHeader = ((headerBytes[2] & 0x40) == 0x40); header.Experimental = ((headerBytes[2] & 0x20) == 0x20); header.HasFooter = ((headerBytes[2] & 0x10) == 0x10); header.TagLength = headerBytes[3] * 128 * 128 * 128 + headerBytes[4] * 128 * 128 + headerBytes[5] * 128 + headerBytes[6]; ArrayPool <byte> .Shared.Return(headerBytes); return(header); }
public static async Task <MP3File> ReadMP3FileAsync(Stream stream) { var file = new MP3File(); file.HasId3V2 = (stream.ReadByte() == Constants.ID3Header[0] && stream.ReadByte() == Constants.ID3Header[1] && stream.ReadByte() == Constants.ID3Header[2]); if (file.HasId3V2) { // Let's read the tag header. file.OriginalTagHeader = await TagHeader.ReadTagHeader(stream).ConfigureAwait(false); // Let's read the tag frames into a byte array and wrap it into a memorystream. var tags = ArrayPool <byte> .Shared.Rent(file.OriginalTagHeader.TagLength); await stream.ReadAsync(tags, 0, file.OriginalTagHeader.TagLength).ConfigureAwait(false); using (var memoryStream = new MemoryStream(tags, 0, file.OriginalTagHeader.TagLength)) { // Let's read the tag. switch (file.OriginalTagHeader.Version) { case TagVersion.V22: break; case TagVersion.V23: file.Tag = await Tag23Factory.FromStream(memoryStream, file.OriginalTagHeader.TagLength).ConfigureAwait(false); break; case TagVersion.V24: //Tag = Tag24Factory.FromBytes(tagBytes); break; case TagVersion.Unknown: break; } } ArrayPool <byte> .Shared.Return(tags); } else // No ID3v2 Tag so the Mpeg Frames presumably start at the beginning but let's make sure though { stream.Seek(0, SeekOrigin.Begin); } // Now let's find the MPEG frames, seek until we find the first 0xFF byte that // should be part of the first Mpeg frame. while (stream.Position < stream.Length && stream.ReadByte() != 0xFF) { if (stream.ReadByte() >= 0xE0) { stream.Seek(-2, SeekOrigin.Current); break; } } // We should be at the first MPEG frame file.MpegStart = (int)stream.Position; //Let's see if this file has an ID3v1 tag stream.Seek(-128, SeekOrigin.End); if (stream.ReadByte() == 0x54 && stream.ReadByte() == 0x41 && stream.ReadByte() == 0x47) { // yup, the MPEG frames end at File.Length - 128 bytes // we've read 3 bytes to see if the ID3v1 tag is present so the MPEG frames ended 3 bytes ago file.MpegEnd = (int)stream.Position - 3; } else { // nope.. no ID3v1 tag is present so the MPEG frames end at the end of the file file.MpegEnd = (int)stream.Length; } return(file); }