11

我开始用 C++ 阅读 mp3 文件。

一切都很顺利,直到我阅读了 ID3-Tag 的规格。ID3v2-Header 中有一些关于其大小的信息存储在所谓的同步安全整数中。这是一个四字节整数,其中每个字节的最高有效位设置为零。

我发现了如何将它转换为普通整数,但我不能停止问自己为什么整数值以如此不必要的复杂方式存储。

我希望有人可以告诉我为什么以这种方式存储它。

4

3 回答 3

29

要了解为什么使用同步安全整数,了解一点 MP3 数据的格式以及媒体播放器如何播放 MP3 文件会很有帮助。MP3 数据以一系列帧的形式存储在文件中。每个帧都包含一小部分以 MP3 格式编码的数字音乐以及一些关于帧本身的元数据。在每个 MP3 帧的开头,11 位(有时是 12 位)都设置为 1。这称为同步,这是媒体播放器在尝试播放 MP3 文件或流时寻找的模式。如果播放器找到这个 11 位序列,那么它就知道它找到了一个可以解码和播放的 MP3 帧。

参见:www.id3.org/mp3Frame

如您所知,ID3 标签包含有关整个轨道的数据。ID3 标签——在 2.x 和更高版本中——位于文件的开头,甚至可以嵌入到 MP3 流中(尽管这并不经常这样做)。ID3 标签的头部包含一个 32 位大小的字段,表示标签中有多少字节。无符号 32 位整数可以容纳的最大值是 0xFFFFFFFF。因此,如果我们将 0xFFFFFFFF 写入 size 字段,我们将声明一个非常大的标签(实际上太大了)。当播放器尝试播放文件或流时,它会查找 MP3 数据帧的 11 位序列,但会在 ID3 标签头中找到 size 字段并尝试播放标签,因为 size 字段的前 11位设置。这通常听起来不太好,具体取决于您的音乐品味。解决方案是创建一个不包含全 1 的 11 位序列的整数格式。因此是同步安全的整数格式。

在 C/C++ 中,可以使用类似以下的方法将同步安全整数转换为整数:

int ID3_sync_safe_to_int( uint8_t* sync_safe )
{
    uint32_t byte0 = sync_safe[0];
    uint32_t byte1 = sync_safe[1];
    uint32_t byte2 = sync_safe[2];
    uint32_t byte3 = sync_safe[3];

    return byte0 << 21 | byte1 << 14 | byte2 << 7 | byte3;
}

希望这可以帮助。

于 2011-04-13T16:56:33.530 回答
3

除了上述答案,我想从我的博客中添加一个页面:http: //phoxis.org/2010/05/08/synch-safe/

于 2011-05-09T17:41:52.177 回答
1

6.2. 同步安全整数

在标签的某些部分,使用非同步方案很不方便,因为事先不知道非同步数据的大小,这对于大小描述符来说尤其成问题。ID3v2 中的解决方案是使用同步安全整数,其中永远不会有任何错误同步。同步安全整数是保持其最高位(位 7)为零的整数,使八位中的七位可用。因此,一个 32 位同步安全整数可以存储 28 位信息。

来自http://www.id3.org/id3v2.4.0-structure

它与给定文档中所谓的“不同步”密切相关,您应该阅读整个第 6 章。所有这些都与最大限度地与各种软件和硬件的兼容性有关。

于 2011-03-07T17:51:46.013 回答