public static id3tag read_id3tag(System.IO.Stream strm, bool createImageObject) { id3tag tag = new id3tag(); byte[] id3_header = new byte[10];// ID3タグヘッダ用 strm.ReadOrThrow(id3_header, 0, 10); id3v2header header = read_header(id3_header); if (header == null) { return(null); } if (header.size >= strm.Length) { return(null); } tag.head = header; if ((tag.head.flag & FLAG_HEAD_EXTENSION) > 0)// 拡張ヘッダがあるときサイズだけ読んでスキップ { byte[] ext_header = new byte[4]; strm.Read(ext_header, 0, 4); int size; if (tag.head.version == 3) // v2.3 { size = ((ext_header[0] * 256 + ext_header[1]) * 256 + ext_header[2]) * 256 + ext_header[3]; } else // v2.4 { size = ((ext_header[0] * 128 + ext_header[1]) * 128 + ext_header[2]) * 128 + ext_header[3] - 4; } strm.Seek(size, System.IO.SeekOrigin.Current); } /* frame */ byte[] frame_buf = new byte[tag.head.size]; strm.Read(frame_buf, 0, tag.head.size); if (((tag.head.flag & FLAG_HEAD_UNSYNC) > 0) && tag.head.version == 3) { frame_buf = DecodeUnsync(frame_buf); } MemoryStream tagBodyStream = new MemoryStream(frame_buf, 0, frame_buf.Length); int count = 0; while (true) { //offset < tag.head.size frame fr = read_frame(tagBodyStream, tag, createImageObject); if (fr == null) { break; } count++; tag.frame.Add(fr); } return(tag); }
static frame read_frame(Stream strm, id3tag tag, bool createImageObject) { int i; int headsize = (tag.head.version == 2) ? 6 : 10; if (strm.Length < headsize) { return(null); } byte[] buf = new byte[headsize]; strm.Read(buf, 0, headsize); frame fr = new frame(); fr.id_x = 0; // どれでもない uint _size; switch (tag.head.version) { case 2: fr.id = Encoding.ASCII.GetString(buf, 0, 3); _size = ((uint)buf[3] * 256 + buf[4]) * 256 + buf[5]; fr.flag = 0; for (i = 0; i < FRAMES.Length; i++) { if (fr.id == FRAMES[i].name2) { fr.id_x = i; break; } } break; case 3: fr.id = Encoding.ASCII.GetString(buf, 0, 4); _size = (((uint)buf[4] * 256 + buf[5]) * 256 + buf[6]) * 256 + buf[7]; fr.flag = ((uint)buf[8] << 7) + (((uint)buf[9] >> 4) & 0x0F) + (((uint)buf[9] << 1) & 0x40); for (i = 0; i < FRAMES.Length; i++) { if (fr.id == FRAMES[i].name3) { fr.id_x = i; break; } } break; case 4: fr.id = Encoding.ASCII.GetString(buf, 0, 4); _size = (((uint)buf[4] * 128 + buf[5]) * 128 + buf[6]) * 128 + buf[7]; fr.flag = ((uint)buf[8] << 8) + buf[9]; for (i = 0; i < FRAMES.Length; i++) { if (fr.id == FRAMES[i].name4) { fr.id_x = i; break; } } break; default: return(null); } if (_size > strm.Length) { return(null); } fr.size = (int)_size; if ((fr.flag & FLAG_FRAME_CRYPTED) > 0) { return(null); // 暗号化なんて知りませんよっと } if ((fr.flag & FLAG_FRAME_COMPRESSED) > 0) { return(null); // 圧縮は実装してない } if (fr.size == 0) { return(null); } if (fr.id == "") { return(null); } int readsize = headsize + fr.size; if (readsize > strm.Length) { return(null); } int offset = 0; byte[] tmp = new byte[fr.size]; // + 2 strm.Read(tmp, 0, fr.size); if (((fr.flag & FLAG_FRAME_UNSYNC) > 0) && tag.head.version == 4) { tmp = DecodeUnsync(tmp); } if ((fr.flag & FLAG_FRAME_DATALENGTH) > 0) // 元サイズ情報を飛ばす { offset = 4; fr.size -= 4; } /* * if ((fr.flag & FLAG_FRAME_CRYPTED) > 0) // 暗号方式を飛ばす * { * offset += 1; * fr.size -= 1; * } */ MemoryStream frameBodyStream = new MemoryStream(tmp, offset, tmp.Length - offset); readFrameBody(frameBodyStream, fr, createImageObject); return(fr); }