0

我一直在尝试通过解析 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);    
    }

}
4

3 回答 3

1

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

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

于 2017-11-25T10:34:52.917 回答
0

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

它的大小存储为大端同步安全 int32

同步安全整数是保持其最高位(位 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 字节。

于 2017-11-29T07:28:37.703 回答
-1

巧合的是,我也在研究 ID3V2 阅读器。该文档说该大小以四个 7 位字节编码。所以你需要另一个步骤将字节数组转换为整数......我不认为仅仅将这些字节作为 int 读取会起作用,因为顶部有空位。

于 2017-11-26T01:28:31.513 回答