MP3帧头检测FFF / FFE同步问题

时间:2013-06-22 20:49:25

标签: c++ c header mp3 frames

我正在尝试解析MP3文件并检测可变比特率(VBR)MP3文件中的所有帧。我已经浏览了整个互联网,无法找到适当的解决方案来检测新的帧头同步。在其他帖子中,它说我应该寻找FFE或FFF但是在我的程序中它不会正确检测到它。我不明白我该如何寻找FFF或FFE?我得到FFE为0xF,下一个字节为0xFE但是如何得到FFF我得到了这个头来构建所需的11位1? 我查看了this,它链接在所有其他主题和网站中作为MP3参考的地方,它的源代码但是我的问题的部分是,我在CMPA *文件中假设不是在源代码下载中给出。

do 
    {
        uiFrame = getc(pFile);
        if(EOF == uiFrame)
            break;
        cntSize++;
        if(0xFF == uiFrame)
        {
            uiFrame = getc(pFile);
            if(EOF == uiFrame)
                break;
            if((0xE == uiFrame) )//|| (0xE0 == uiFrame))
            {
                if(1 != uiFrameCount)
                    printf("\nFrame Size is %d \n\n",cntSize - PrevoiusFrameSize);

                printf("\nFrame Found at Byte %d", cntSize);
                PrevoiusFrameSize = cntSize;
                CheckFlag         = 1;
                uiFrameCount++;
            }
            cntSize++;
        }
    }while(1 != CheckFlag);

当我执行上面的代码或我可以想到的任何变体时,我获得1到6帧,而如果我从上面的链接使用程序本身,它在我的测试mp3文件上显示8855帧。任何关于这个问题的帮助都会非常感激,因为我的想法和谷歌的页面都没有用来寻找答案。

感谢您的帮助。

编辑: 在马克B的快速回复后,我大部分时间都明白了这个问题,但经过编辑以反映他的答案,我现在只能检测到4帧,而不是一帧。 这是执行帧检测的代码部分,我做错了吗?

do 
    {
        uiFrame = getc(pFile);
        if(EOF == uiFrame)
            break;
        cntSize++;
        if(0xFF == uiFrame)
        {
            uiFrame = getc(pFile);
            if(EOF == uiFrame)
                break;
            uiShift=uiFrame>>4;
            if((0xE == uiShift) || (0xF == uiShift))
            {
                if(1 != uiFrameCount)
                    printf("\nFrame Size is %d \n\n",cntSize - PrevoiusFrameSize);

                printf("\nFrame Found at Byte %d", cntSize);
                PrevoiusFrameSize = cntSize;
                CheckFlag         = 1;
                uiFrameCount++;
            }
            cntSize++;
        }
    }while(1 != CheckFlag);

3 个答案:

答案 0 :(得分:0)

标头的3个半字节(又名1.5个字节),所以你需要进行一些位移。在伪代码中:

$data = 'FFEABCDEF....'
         ^^^--3 nibble header
$nibble1 = $data[0];
$nibble2 = $data[1] >> 4; // isolate 3rd nibble
if ($nibble1 == 'FF') && (($nibble2 == 'F') || ($nibble2 == 'E')) { ... }

答案 1 :(得分:0)

您需要逐帧进行。 每个帧都以32位标头开头,您需要“解码”。 请查看以下document

完成后,您将获得下一个[标题+帧]块的偏移量。

享受:)

答案 2 :(得分:0)

您可以使用以下C宏轻松地反转(4字节)帧头中的字节顺序:

#define swaplong(x)  (unsigned  long)((((x)>>24) & 0xFF) |
((((x) & 0xFF0000) >> 8) & 0xFF00) | (((x) & 0xFF00) << 8) | ((x) << 24))

然后,同步位(再次)相邻,分析更直接。