用C解析ID3V2帧

时间:2017-11-25 09:19:30

标签: c parsing bit-manipulation id3v2

我一直试图通过解析mp3文件并检索每个帧的大小来检索ID3V2标记帧。到目前为止,我没有运气。

我已经有效地将内存分配给缓冲区以帮助读取文件,并且已经成功打印出标题版本,但是很难检索到标题和帧大小。对于标题帧大小,我得到1347687723,虽然在十六进制编辑器中查看文件,但我看到05 2B 19。

我的代码的两个片段:

typedef struct{ //typedef structure used to read tag information
char tagid[3];              //0-2  "ID3"
unsigned char tagversion;   //3    $04
unsigned char tagsubversion;//4     00
unsigned char flags;        //5-6   %abc0000
uint32_t size;              //7-10  4 * %0xxxxxxx
}ID3TAG;

if(buff){
    fseek(filename,0,SEEK_SET); 
    fread(&Tag, 1, sizeof(Tag),filename); 
    if(memcmp(Tag.tagid,"ID3", 3) == 0)
    {
        printf("ID3V2.%02x.%02x.%02x \nHeader Size:%lu\n",Tag.tagversion, 
    Tag.tagsubversion, Tag.flags ,Tag.size);    
    }

}

2 个答案:

答案 0 :(得分:2)

由于内存对齐,编译器在标志大小之间设置了2个字节的填充。如果您的结构直接放在内存中,则大小将位于地址6(从结构的开头)。由于4字节大小的元素必须是4的地址倍数,编译器会添加2个字节,因此 size 会移动到4个地址的最接近的倍数,即8。所以当你读到从您的文件中,大小包含字节8-11。如果您尝试打印 *(& Tag.size - 2),您一定会得到正确的结果。

要解决此问题,您可以逐个阅读字段。

答案 1 :(得分:0)

ID3v2标头结构在所有ID3v2版本(ID3v2.0,ID3v2.3和ID3v2.4)中都是一致的。

其大小存储为 big-endian synch-safe int32

  

Synchsafe整数是      保持最高位(位7)归零的整数,产生7位      八个可用的。因此,32位同步整数可以存储28      一点点信息。

     

例:
     编码为16位同步整数的255(%11111111)是383        (%00000001 01111111)。

来源:http://id3.org/id3v2.4.0-structure§6.2

下面是一个简单,真实的C#实现,您可以轻松地适应C

public int DecodeSynchSafeInt32(byte[] bytes)
{
    return                 
        bytes[0] * 0x200000 +   //2^21
        bytes[1] * 0x4000 +     //2^14
        bytes[2] * 0x80 +       //2^7
        bytes[3];
}

=>使用您在十六进制编辑器(00 05 EB 19)上读取的值,实际标签大小应为112025字节。