using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Collections;
namespace WindowsFormsApplication1
{
public class ID3V2
{
private MP3Stream mp3Stream;
private string _header;
/// <summary>
/// 3 byte ; 必须为 ID3
/// </summary>
public string Header
{
get { return _header; }
}
private string _version;
/// <summary>
/// 1 byte ; 版本号 对ID3V2.3 来说就是 3
/// </summary>
public string Version
{
get { return _version; }
}
private string _revision;
/// <summary>
/// 1 byte ; 副版本号 为 0
/// </summary>
public string Revision
{
get { return _revision; }
}
private byte _flag;
/// <summary>
/// 1 byte ; 标志位 ,此版本只定义了前 3 bit ,一般为0
/// </summary>
public byte Flag
{
get { return _flag; }
}
private bool _hasExtendHeader;
/// <summary>
/// 是否使用Unsynchronisation
/// </summary>
public bool HasExtendHeader
{
get { return _hasExtendHeader; }
}
private bool _isUnsynchronisation;
/// <summary>
/// 是否有扩展头部
/// </summary>
public bool IsUnsynchronisation
{
get { return _isUnsynchronisation; }
}
private bool _isForTest;
/// <summary>
/// 是否为测试标签
/// </summary>
public bool IsForTest
{
get { return _isForTest; }
}
private int _size;
/// <summary>
/// 标签大小
/// </summary>
public int Size
{
get { return _size; }
}
private ArrayList _frames = new ArrayList();
public ArrayList Frames
{
get { return _frames; }
}
public ID3V2(MP3Stream stream)
{
mp3Stream = stream;
_header = mp3Stream.ReadText(3, Encoding.ASCII);
_version = mp3Stream.ReadByte().ToString();
_revision = mp3Stream.ReadByte().ToString();
_flag = mp3Stream.ReadByte();
_isUnsynchronisation = (_flag & 0X80) == 0X80;
_hasExtendHeader = (_flag & 0X40) == 0X40;
_isForTest = (_flag & 0X20) == 0X20;
_size = mp3Stream.ReadByte() * 0x200000;
_size += mp3Stream.ReadByte() * 0x4000;
_size += mp3Stream.ReadByte() * 0x80;
_size += mp3Stream.ReadByte();
// Extended Header Must Read Here
if (_hasExtendHeader)
{
mp3Stream.Seek(10, SeekOrigin.Current);
}
ReadFrame();
}
/// <summary>
/// 读取标签帧
/// </summary>
/// <returns></returns>
private void ReadFrame()
{
byte Buf = 0;
int length = _size;
// If ID3v2 is ID3v2.2 FrameID, FrameLength of Frames is 3 byte
// otherwise it's 4 character
int FrameIDLen = Version == "2" ? 3 : 4;
// Minimum frame size is 10 because frame header is 10 byte
while (length > 10)
{
// check for padding( 00 bytes )
Buf = mp3Stream.ReadByte();
if (Buf == 0)
{
length--;
continue;
}
// if readed byte is not zero. it must read as FrameID
mp3Stream.Seek(-1, SeekOrigin.Current);
TagFame frame = new TagFame(mp3Stream);
_frames.Add(frame);
length -= (frame.Size + 10);
}
// check for padding( 00 bytes )
if (length > 0)
mp3Stream.Seek(length, SeekOrigin.Current);
}
}
public class TagFame
{
private string _frameID;
/// <summary>
/// 帧名称
/// </summary>
public string FrameID
{
get { return _frameID; }
}
private int _size;
/// <summary>
/// 帧大小
/// </summary>
public int Size
{
get { return _size; }
}
private byte _flag1;
/// <summary>
/// 1 byte ; 标志位 ,此版本只定义了前3bit:abc00000
/// a:标签保护;
/// b:文件保护;
/// c:只读标志;
/// </summary>
public byte Flag1
{
get { return _flag1; }
}
private byte _flag2;
/// <summary>
/// 1 byte ; 标志位 ,此版本只定义了前3bit:ijk00000
/// i:压缩标志;
/// j:加密标志;
/// k:组标志;
/// </summary>
public byte Flag2
{
get { return _flag2; }
}
private string _data;
public string Data
{
get { return _data;}
}
public TagFame(MP3Stream stream)
{
_frameID = stream.ReadText(4, Encoding.ASCII);
_size = (int)stream.ReadUInt(4);
_flag1 = stream.ReadByte();
_flag2 = stream.ReadByte();
_data = stream.ReadText(_size, Encoding.Default);
}
}
}