/// <summary> /// ID3v2タグを読む /// </summary> /// <param name="strm"></param> /// <param name="createImageObject"></param> /// <returns></returns> public static ID3tag readID3tag(System.IO.Stream strm, bool createImageObject) { // ヘッダ読み込み byte[] id3_header = strm.ReadBytes(HEADER_LEN); Header header = readHeader(id3_header); if (header == null) { return(null); } if (header.Size >= strm.Length) { return(null); } ID3tag tag = new ID3tag(); tag.head = header; // 拡張ヘッダがあるときサイズだけ読んでスキップ if (tag.head.Flag.HasFlag(HEADER_FLAG.EXTENSION)) { byte[] ext_header = strm.ReadBytes(EXT_HEADER_LEN); var size = tag.head.Version == ID3V2_VER.ID3V23 ? ReadUInt32(ext_header, 0) : ReadUInt28(ext_header, 0) - EXT_HEADER_LEN; // v3とv4でEXT_HEADER_LENの扱いが違う strm.Seek(size, System.IO.SeekOrigin.Current); } // 全Frameのデータ領域を読み出す byte[] frame_buf = strm.ReadBytes(header.Size); // .2, .3の場合は非同期化の解除 if (header.Version != ID3V2_VER.ID3V24 && header.Flag.HasFlag(HEADER_FLAG.UNSYNC)) { decodeUnsync(ref frame_buf); } // 各Frameのデータ読み出し var tagBodyStream = new MemoryStream(frame_buf, 0, frame_buf.Length); while (true) { try { Frame fr = readFrame(tagBodyStream, tag, createImageObject); if (fr != null) { tag.frame.Add(fr); } } catch (EndOfTagException) { break; } } return(tag); }
/// <summary> /// ID3V2タグフレームを読む /// </summary> /// <param name="strm"></param> /// <param name="tag"></param> /// <param name="createImageObject"></param> /// <returns></returns> private static Frame readFrame(Stream strm, ID3tag tag, bool createImageObject) { int frameHeaderSize = (tag.head.Version == ID3V2_VER.ID3V22) ? FRAME_HEADER_LEN_2 : FRAME_HEADER_LEN_34; if (strm.Length - strm.Position < frameHeaderSize) { throw new EndOfTagException(); } byte[] buf = strm.ReadBytes(frameHeaderSize); var frame = readFrameHeader(buf, tag.head.Version); if (frame.Size <= 0) { throw new EndOfTagException(); } if (strm.Length - strm.Position < frame.Size) { throw new EndOfTagException(); } int offset = 0; bool unsupported = false; if (frame.ID == null) { unsupported = true; } // 暗号化なんて知りませんよっと if (frame.Flag.HasFlag(FRAME_FLAG.CRYPTED)) { unsupported = true; } // 圧縮は実装してない if (frame.Flag.HasFlag(FRAME_FLAG.COMPRESSED)) { unsupported = true; } // グループ識別子を無視 if (frame.Flag.HasFlag(FRAME_FLAG.GROUPED)) { // unsupportedにはしない offset += 1; } // DATALENGTHを飛ばす if (frame.Flag.HasFlag(FRAME_FLAG.DATALENGTH)) { offset += 4; } if (unsupported) { strm.Seek(frame.Size, SeekOrigin.Current); return(null); } strm.Seek(offset, SeekOrigin.Current); byte[] buffer = strm.ReadBytes(frame.Size - offset); if (frame.Flag.HasFlag(FRAME_FLAG.UNSYNC) && tag.head.Version == ID3V2_VER.ID3V24) { decodeUnsync(ref buffer); } MemoryStream frameBodyStream = new MemoryStream(buffer); readFrameBody(frameBodyStream, frame, createImageObject); return(frame); }