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

MP3 Frame Header Detection FFF/FFE sync issue

本文关键字:FFE 同步 问题 FFF 检测 MP3      更新时间:2023-10-16

我正在尝试解析一个MP3文件,并检测可变比特率(VBR)MP3文件中的所有帧。我在互联网上到处找了找,找不到合适的解决方案来检测新的帧头同步。从其他帖子中,它说我应该寻找FFE或FFF,但在我的程序中,它无法正确检测到它。我不明白我该如何寻找FFF或FFE?我得到的FFE是0xF,下一个字节是0xFE,但如何得到FFF?我从中得到标题,以构建所需的11位1?我已经查看了这个链接在所有其他主题和网站中作为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 nn",cntSize - PrevoiusFrameSize);
                printf("nFrame Found at Byte %d", cntSize);
                PrevoiusFrameSize = cntSize;
                CheckFlag         = 1;
                uiFrameCount++;
            }
            cntSize++;
        }
    }while(1 != CheckFlag);

当我执行上面的代码或我能想到的任何变体时,我会获得1到6帧,而如果我从上面的链接使用程序本身,它会在我的测试mp3文件上显示8855帧。如果能在这件事上提供任何帮助,我将不胜感激,因为我已经没有办法在谷歌上寻找答案了。

谢谢你的帮助。

编辑:在马克B迅速回复后,我基本上理解了这个问题,但在编辑以反映他的回答后,我现在只检测到4帧,而不是1帧。这是做帧检测的代码部分,我做错了什么吗?

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 nn",cntSize - PrevoiusFrameSize);
                printf("nFrame Found at Byte %d", cntSize);
                PrevoiusFrameSize = cntSize;
                CheckFlag         = 1;
                uiFrameCount++;
            }
            cntSize++;
        }
    }while(1 != CheckFlag);

标头的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')) { ... }

您需要一帧一帧地进行。每一帧都以一个需要"解码"的32位标头开始。检查以下文件

完成后,您将获得到下一个[header+frame]块的偏移量。

享受:)

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

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

然后同步化比特是相邻的(再次),并且分析更加直接。