internal override Id3Tag ReadTag(Stream stream) { if (!HasTag(stream)) { return(null); } var tag = new Id3Tag { MajorVersion = 2, MinorVersion = 3, Family = Id3TagFamily.Version2x, IsSupported = true, }; stream.Seek(4, SeekOrigin.Begin); var headerBytes = new byte[6]; stream.Read(headerBytes, 0, 6); var headerContainer = new Id3v2Header(); tag.AdditionalData = headerContainer; byte flags = headerBytes[1]; var header = new Id3v2StandardHeader { Revision = headerBytes[0], Unsyncronization = (flags & 0x80) > 0, ExtendedHeader = (flags & 0x40) > 0, Experimental = (flags & 0x20) > 0 }; headerContainer.Header = header; int tagSize = SyncSafeNumber.DecodeSafe(headerBytes, 2, 4); var tagData = new byte[tagSize]; stream.Read(tagData, 0, tagSize); int currentPos = 0; if (header.ExtendedHeader) { SyncSafeNumber.DecodeSafe(tagData, currentPos, 4); currentPos += 4; var extendedHeader = new Id3v2ExtendedHeader { PaddingSize = SyncSafeNumber.DecodeNormal(tagData, currentPos + 2, 4) }; if ((tagData[currentPos] & 0x80) > 0) { extendedHeader.Crc32 = SyncSafeNumber.DecodeNormal(tagData, currentPos + 6, 4); currentPos += 10; } else { currentPos += 6; } headerContainer.ExtendedHeader = extendedHeader; } while (currentPos < tagSize && tagData[currentPos] != 0x00) { string frameId = AsciiEncoding.GetString(tagData, currentPos, 4); currentPos += 4; int frameSize = SyncSafeNumber.DecodeNormal(tagData, currentPos, 4); currentPos += 4; var frameFlags = (ushort)((tagData[currentPos] << 0x08) + tagData[currentPos + 1]); currentPos += 2; var frameData = new byte[frameSize]; Array.Copy(tagData, currentPos, frameData, 0, frameSize); FrameHandler mapping = FrameHandlers[frameId]; if (mapping != null && mapping.Decoder != null) { Id3Frame frame = mapping.Decoder(frameData); tag.Frames.Add(frame); } currentPos += frameSize; } return(tag); }
internal override Id3Tag ReadTag(Stream stream, out object additionalData) { if (!HasTag(stream)) { additionalData = null; return(null); } Id3Tag tag = CreateTag(); stream.Seek(4, SeekOrigin.Begin); var headerBytes = new byte[6]; stream.Read(headerBytes, 0, 6); var headerContainer = new Id3V2Header(); additionalData = headerContainer; byte flags = headerBytes[1]; var header = new Id3V2StandardHeader { Revision = headerBytes[0], Unsyncronization = (flags & 0x80) > 0, ExtendedHeader = (flags & 0x40) > 0, Experimental = (flags & 0x20) > 0 }; headerContainer.Header = header; int tagSize = SyncSafeNumber.DecodeSafe(headerBytes, 2, 4); var tagData = new byte[tagSize]; stream.Read(tagData, 0, tagSize); var currentPos = 0; if (header.ExtendedHeader) { SyncSafeNumber.DecodeSafe(tagData, currentPos, 4); currentPos += 4; var extendedHeader = new Id3V2ExtendedHeader { PaddingSize = SyncSafeNumber.DecodeNormal(tagData, currentPos + 2, 4) }; if ((tagData[currentPos] & 0x80) > 0) { extendedHeader.Crc32 = SyncSafeNumber.DecodeNormal(tagData, currentPos + 6, 4); currentPos += 10; } else { currentPos += 6; } headerContainer.ExtendedHeader = extendedHeader; } while (currentPos < tagSize && tagData[currentPos] != 0x00) { string frameId = Encoding.ASCII.GetString(tagData, currentPos, 4); currentPos += 4; int frameSize = SyncSafeNumber.DecodeNormal(tagData, currentPos, 4); currentPos += 4; var frameFlags = (ushort)((tagData[currentPos] << 0x08) + tagData[currentPos + 1]); currentPos += 2; var frameData = new byte[frameSize]; Array.Copy(tagData, currentPos, frameData, 0, frameSize); FrameHandler mapping = FrameHandlers[frameId]; if (mapping != null) { Id3Frame frame = mapping.Decoder(frameData); tag.AddUntypedFrame(frame); } currentPos += frameSize; } return(tag); }