private byte[] FindHeader() { byte thisByte = br.ReadByte(); while (br.BaseStream.Position < br.BaseStream.Length) { if (System.Convert.ToInt32(thisByte) == 255) { bool[] thatByte = BitReader.ToBitBool(br.ReadByte()); br.BaseStream.Position--; if (thatByte[0] && thatByte[1] && thatByte[2]) { // we found the sync. this.headerPosition = br.BaseStream.Position - 1; byte [] retByte = new byte [4]; retByte[0] = thisByte; retByte[1] = br.ReadByte(); retByte[2] = br.ReadByte(); retByte[3] = br.ReadByte(); return(retByte); } else { thisByte = br.ReadByte(); } } else { thisByte = br.ReadByte(); } } return(null); }
public id3v2Frame ReadFrame(BinaryReader br, int version) { char[] tagSize; // I use this to read the bytes in from the file int[] bytes; // for bit shifting ulong newSize = 0; // for the final number int nameSize = 4; if (version == 2) { nameSize = 3; } else if ((version == 3) || (version == 4)) { nameSize = 4; } id3v2Frame f1 = new id3v2Frame(); f1.frameName = new string (br.ReadChars(nameSize)); f1.MajorVersion = version; // in order to check for padding I have to build a string of 4 (or 3 if v2.2) null bytes // there must be a better way to do this char nullChar = System.Convert.ToChar(0); StringBuilder sb = new StringBuilder(0, nameSize); sb.Append(nullChar); sb.Append(nullChar); sb.Append(nullChar); if (nameSize == 4) { sb.Append(nullChar); } if (f1.frameName == sb.ToString()) { f1.padding = true; return(f1); } if (version == 2) { // only have 3 bytes for size ; tagSize = br.ReadChars(3); // I use this to read the bytes in from the file bytes = new int[3]; // for bit shifting newSize = 0; // for the final number // The ID3v2 tag size is encoded with four bytes // where the most significant bit (bit 7) // is set to zero in every byte, // making a total of 28 bits. // The zeroed bits are ignored // // Some bit grinding is necessary. Hang on. bytes[3] = tagSize[2] | ((tagSize[1] & 1) << 7); bytes[2] = ((tagSize[1] >> 1) & 63) | ((tagSize[0] & 3) << 6); bytes[1] = ((tagSize[0] >> 2) & 31); newSize = ((UInt64)bytes[3] | ((UInt64)bytes[2] << 8) | ((UInt64)bytes[1] << 16)); //End Dan Code } else if (version == 3 || version == 4) { // version 2.4 tagSize = br.ReadChars(4); // I use this to read the bytes in from the file bytes = new int[4]; // for bit shifting newSize = 0; // for the final number // The ID3v2 tag size is encoded with four bytes // where the most significant bit (bit 7) // is set to zero in every byte, // making a total of 28 bits. // The zeroed bits are ignored // // Some bit grinding is necessary. Hang on. bytes[3] = tagSize[3] | ((tagSize[2] & 1) << 7); bytes[2] = ((tagSize[2] >> 1) & 63) | ((tagSize[1] & 3) << 6); bytes[1] = ((tagSize[1] >> 2) & 31) | ((tagSize[0] & 7) << 5); bytes[0] = ((tagSize[0] >> 3) & 15); newSize = ((UInt64)bytes[3] | ((UInt64)bytes[2] << 8) | ((UInt64)bytes[1] << 16) | ((UInt64)bytes[0] << 24)); //End Dan Code } f1.frameSize = newSize; if (version > 2) { // versions 3+ have frame tags. if (version == 3) { bool [] c; // read teh tags c = BitReader.ToBitBool(br.ReadByte()); f1.F_TagAlterPreservation = c[0]; f1.F_FileAlterPreservation = c[1]; f1.F_ReadOnly = c[2]; c = BitReader.ToBitBool(br.ReadByte()); f1.F_Compression = c[0]; f1.F_Encryption = c[1]; f1.F_GroupingIdentity = c[2]; } else if (version == 4) { //%0abc0000 %0h00kmnp //a - Tag alter preservation // 0 Frame should be preserved. // 1 Frame should be discarded. // b - File alter preservation // 0 Frame should be preserved. //1 Frame should be discarded. // c - Read only // h - Grouping identity // 0 Frame does not contain group information // 1 Frame contains group information // k - Compression // 0 Frame is not compressed. // 1 Frame is compressed using zlib [zlib] deflate method. // If set, this requires the 'Data Length Indicator' bit // to be set as well. // m - Encryption // 0 Frame is not encrypted. // 1 Frame is encrypted. // n - Unsynchronisation // 0 Frame has not been unsynchronised. // 1 Frame has been unsyrchronised. // p - Data length indicator // 0 There is no Data Length Indicator. // 1 A data length Indicator has been added to the frame. bool [] c; // read teh tags c = BitReader.ToBitBool(br.ReadByte()); f1.F_TagAlterPreservation = c[1]; f1.F_FileAlterPreservation = c[2]; f1.F_ReadOnly = c[3]; c = BitReader.ToBitBool(br.ReadByte()); f1.F_GroupingIdentity = c[1]; f1.F_Compression = c[4]; f1.F_Encryption = c[5]; f1.F_Unsynchronisation = c[6]; f1.F_DataLengthIndicator = c[7]; } if (f1.frameSize > 0) { f1.frameContents = br.ReadBytes((int)f1.frameSize); } } return(f1); }
private void ReadFooter() { // bring in the first three bytes. it must be ID3 or we have no tag // TODO add logic to check the end of the file for "3D1" and other // possible starting spots string id3start = new string (br.ReadChars(3)); // check for a tag if (!id3start.Equals("3DI")) { // TODO we are f****d. not really we just don't ahve a tag // and we need to bail out gracefully. //throw id3v23ReaderException; } else { // we have a tag this.hasTag = true; } // read id3 version. 2 bytes: // The first byte of ID3v2 version is it's major version, // while the second byte is its revision number this.MajorVersion = System.Convert.ToInt32(br.ReadByte()); this.MinorVersion = System.Convert.ToInt32(br.ReadByte()); // here is where we get fancy. I am useing silisoft's php code as // a reference here. we are going to try and parse for 2.2, 2.3 and 2.4 // in one pass. hold on!! if ((this.hasTag) && (this.MajorVersion <= 4)) // probably won't work on higher versions { // (%ab000000 in v2.2, %abc00000 in v2.3, %abcd0000 in v2.4.x) //read next byte for flags bool [] boolar = BitReader.ToBitBool(br.ReadByte()); // set the flags if (this.MajorVersion == 2) { this.FA_Unsynchronisation = boolar[0]; this.FB_ExtendedHeader = boolar[1]; } else if (this.MajorVersion == 3) { // set the flags this.FA_Unsynchronisation = boolar[0]; this.FB_ExtendedHeader = boolar[1]; this.FC_ExperimentalIndicator = boolar[2]; } else if (this.MajorVersion == 4) { // set the flags this.FA_Unsynchronisation = boolar[0]; this.FB_ExtendedHeader = boolar[1]; this.FC_ExperimentalIndicator = boolar[2]; this.FD_Footer = boolar[3]; } // read teh size // this code is courtesy of Daniel E. White w/ minor modifications by me Thanx Dan //Dan Code char[] tagSize = br.ReadChars(4); // I use this to read the bytes in from the file int[] bytes = new int[4]; // for bit shifting ulong newSize = 0; // for the final number // The ID3v2 tag size is encoded with four bytes // where the most significant bit (bit 7) // is set to zero in every byte, // making a total of 28 bits. // The zeroed bits are ignored // // Some bit grinding is necessary. Hang on. bytes[3] = tagSize[3] | ((tagSize[2] & 1) << 7); bytes[2] = ((tagSize[2] >> 1) & 63) | ((tagSize[1] & 3) << 6); bytes[1] = ((tagSize[1] >> 2) & 31) | ((tagSize[0] & 7) << 5); bytes[0] = ((tagSize[0] >> 3) & 15); newSize = ((UInt64)10 + (UInt64)bytes[3] | ((UInt64)bytes[2] << 8) | ((UInt64)bytes[1] << 16) | ((UInt64)bytes[0] << 24)); //End Dan Code this.headerSize = newSize; } }
private void ReadHeader( ) { // bring in the first three bytes. it must be ID3 or we have no tag // TODO add logic to check the end of the file for "3D1" and other // possible starting spots string id3start = new string (br.ReadChars(3)); // check for a tag if (!id3start.Equals("ID3")) { // TODO we are f****d. //throw id3v2ReaderException; this.hasTag = false; return; } else { this.hasTag = true; // read id3 version. 2 bytes: // The first byte of ID3v2 version is it's major version, // while the second byte is its revision number this.MajorVersion = System.Convert.ToInt32(br.ReadByte()); this.MinorVersion = System.Convert.ToInt32(br.ReadByte()); //read next byte for flags bool [] boolar = BitReader.ToBitBool(br.ReadByte()); // set the flags this.FA_Unsynchronisation = boolar[0]; this.FB_ExtendedHeader = boolar[1]; this.FC_ExperimentalIndicator = boolar[2]; // read teh size // this code is courtesy of Daniel E. White w/ minor modifications by me Thanx Dan //Dan Code char[] tagSize = br.ReadChars(4); // I use this to read the bytes in from the file int[] bytes = new int[4]; // for bit shifting ulong newSize = 0; // for the final number // The ID3v2 tag size is encoded with four bytes // where the most significant bit (bit 7) // is set to zero in every byte, // making a total of 28 bits. // The zeroed bits are ignored // // Some bit grinding is necessary. Hang on. bytes[3] = tagSize[3] | ((tagSize[2] & 1) << 7); bytes[2] = ((tagSize[2] >> 1) & 63) | ((tagSize[1] & 3) << 6); bytes[1] = ((tagSize[1] >> 2) & 31) | ((tagSize[0] & 7) << 5); bytes[0] = ((tagSize[0] >> 3) & 15); newSize = ((UInt64)10 + (UInt64)bytes[3] | ((UInt64)bytes[2] << 8) | ((UInt64)bytes[1] << 16) | ((UInt64)bytes[0] << 24)); //End Dan Code this.headerSize = newSize; } }