正确读取被ID3标签破坏的MP3文件

时间:2016-06-12 18:20:09

标签: c++ parsing ffmpeg mp3 id3

我的semestral项目将于本周四到期,我在阅读MP3文件方面存在重大问题(该项目是关于声音分析的,不要问我究竟是什么,以及为什么我这么晚才这样做。)

首先,我读取前10个字节来检查ID3标签。如果它们存在,我将跳到第一个MP3标题 - 或者至少这是个大主意。以下是我如何计算ID3标签大小:

if (inbuf[0] == 'I' && inbuf[1] == 'D' && inbuf[2] == '3') //inbuf contains first 10 bytes from file
{
    int size = inbuf[3] * 2097152 + inbuf[4] * 16384 + inbuf[5] * 128 + inbuf[6]; //Will change to binary shifts later
    //Do something else with it - skip rest of ID3 tags etc
}

对于没有ID3标签的文件以及带有它们的一些文件,它可以正常工作,但是对于其他一些文件,ffmpeg(我用于解码)返回“无标题”错误,这意味着它没有正确捕获MP3标题。我知道,因为如果我从.mp3文件中移除ID3(例如Winamp),则不会发生错误。结论是大小计数算法并不总是有效。

所以问题是:我如何才能知道.mp3文件的整个ID3部分究竟有多大(所有可能的标签,专辑图片等等)?我到处寻找它,但我一直在寻找上面发布的这个算法。有时我还需要考虑一些大约10个字节的页脚,但它似乎经常会超过10个字节,以便最终捕获正确的MP3帧。

2 个答案:

答案 0 :(得分:2)

ID3v1标签的大小始终固定为128字节。

我会找到以下说明

  

如果您对所有这些字段的大小求和,我们会看到30 + 30 + 30 + 4 + 30 + 1等于125字节而不是128字节。丢失的三个字节可以在歌曲标题之前的标签的最开头找到。这三个字节始终为“TAG”,并且标识这确实是ID3标记。查找ID3v1 / 1.1标记的最简单方法是从文件末尾查找128字节的单词“TAG”。

来源:http://id3.org/ID3v1

还有另一个名为ID3v2的版本:

  

其中一个设计目标是ID3v2应该非常灵活和可扩展......   由于每个帧可以是16MB并且整个标记可以是256MB,因此您可能永远不会再次遇到与您尝试在旧ID3中编写有用注释限制为30个字符时相同的情况。

此ID3v2始终从音频文件的开头开始,您可以在此处阅读:http://id3.org/ID3v2Easy

ID3v2/file identifier   "ID3"
ID3v2 version           $03 00
ID3v2 flags             %abc00000
ID3v2 size              4 * %0xxxxxxx

ID3v2标签大小用四个字节编码,其中最高有效位(第7位)在每个字节中设置为零,总共28位。忽略零位,因此257字节长的标记表示为$ 00 00 02 01.

答案 1 :(得分:2)

bool LameDecoder::skipDataIfRequired()
{
    auto data = m_file.read(3);
    Q_ASSERT(data.size() == 3);
    if (data.size() != 3)
        return false;
    if (memcmp(data.constData(), "ID3", 3))
    {
        m_file.seek(0);
        return true;
    }

    // ID3v2 tag is detected; skip it

    m_file.seek(3+2+1);
    data = m_file.read(4);
    if (data.size() != 4)
        return false;

    qint32 size = (data[0] << (7*3)) | (data[1] << (7*2)) |
            (data[2] << 7) | data[3];

    m_file.seek(3+2+1+4+size);

    return true;
}