Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/390.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 向后搜索以处理无效的MP3头?_Java_Loops_Mp3_Inputstream_Seek - Fatal编程技术网

Java 向后搜索以处理无效的MP3头?

Java 向后搜索以处理无效的MP3头?,java,loops,mp3,inputstream,seek,Java,Loops,Mp3,Inputstream,Seek,我正在编写一个应用程序来解码MP3帧。我很难找到标题 MP3头是32位的,以签名开始:11111111 在下面的内部循环中,我寻找这个签名。找到此签名后,我检索下两个字节,然后将头的后三个字节传递到自定义MpegFrame()类中。该类验证头的完整性并从中解析信息MpegFrame.isValid()返回一个布尔值,指示帧头的有效性/完整性。如果标头无效,则再次执行外部循环,并再次查找签名 使用CBRMP3执行我的程序时,只找到部分帧。应用程序报告许多无效帧 我相信无效帧可能是位被跳过的结果。标

我正在编写一个应用程序来解码
MP3
帧。我很难找到标题

MP3
头是32位的,以签名开始:
11111111

在下面的内部循环中,我寻找这个签名。找到此签名后,我检索下两个字节,然后将头的后三个字节传递到自定义
MpegFrame()
类中。该类验证头的完整性并从中解析信息
MpegFrame.isValid()
返回一个布尔值,指示帧头的有效性/完整性。如果标头无效,则再次执行外部循环,并再次查找签名

使用
CBR
MP3
执行我的程序时,只找到部分帧。应用程序报告许多无效帧

我相信无效帧可能是位被跳过的结果。标头的长度为4字节。当标头被确定为无效时,我跳过所有4个字节,并开始从接下来的4个字节中查找签名。在如下情况下:
11111111 11101101 11111111111 11101001
,头签名出现在头两个字节中,但第三个字节包含一个使头无效的错误。如果我跳过所有字节,因为我确定以第一个字节开头的头无效,那么我将错过以第三个字节开头的pottential头(因为第三和第四个字节包含签名)

我无法在
输入流中向后搜索,因此我的问题如下:当我确定以字节1和2开头的头无效时,如何运行以字节2而不是字节5开头的签名查找循环?

在下面的代码中,
b
是考虑中的可能头的第一个字节,
b1
是第二个字节,
b2
是第三个字节,
b3
是第四个字节

int bytesRead = 0;

//10 bytes of Tagv2
int j = 0;

byte[] tagv2h = new byte[10];
j = fis.read(tagv2h);
bytesRead += j;

ByteBuffer bb = ByteBuffer.wrap(new byte[]{tagv2h[6], tagv2h[7],tagv2h[8], tagv2h[9]});
bb.order(ByteOrder.BIG_ENDIAN);
int tagSize = bb.getInt();

byte[] tagv2 = new byte[tagSize];
j = fis.read(tagv2);
bytesRead += j;

while (bytesRead < MPEG_FILE.length()) {

        boolean foundHeader = false;

        // Seek frame
        int b = 0;
        int b1 = 0;
        while ((b = fis.read()) > -1) {
            bytesRead++;
            if (b == 255) {
                b1 = fis.read();
                if (b1 > -1) {
                    bytesRead++;
                    if (((b1 >> 5) & 0x7) == 0x7) {
                        System.out.println("Found header.");
                        foundHeader = true;
                        break;
                    }
                }
            }
        }

        if (!foundHeader) {
            continue;
        }

        int b2 = fis.read();
        int b3 = fis.read();

        MpegFrame frame = new MpegFrame(b1, b2, b3, false);
        if (!frame.isValid()) {
            System.out.println("Invalid header @ " + (bytesRead-4));
            continue;
        }

}
int字节读取=0;
//10字节的Tagv2
int j=0;
字节[]tagv2h=新字节[10];
j=fis.read(tagv2h);
字节读取+=j;
ByteBuffer bb=ByteBuffer.wrap(新字节[]{tagv2h[6],tagv2h[7],tagv2h[8],tagv2h[9]});
bb.order(ByteOrder.BIG_ENDIAN);
int tagSize=bb.getInt();
字节[]tagv2=新字节[tagSize];
j=fis.read(tagv2);
字节读取+=j;
while(bytesRead-1){
bytesRead++;
如果(b==255){
b1=fis.read();
如果(b1>-1){
bytesRead++;
如果((b1>>5)&0x7)==0x7){
System.out.println(“找到的标题”);
foundHeader=true;
打破
}
}
}
}
如果(!foundHeader){
继续;
}
int b2=fis.read();
int b3=fis.read();
MpegFrame frame=新的MpegFrame(b1、b2、b3、false);
如果(!frame.isValid()){
System.out.println(“无效头@”+(bytesRead-4));
继续;
}
}

您可以将输入流包装在一个文件中,这样您就可以向后推送一些字节并重新解析它们。

我最后编写了一个函数来移动无效头的字节,以便重新解析它。我在一个循环中调用该函数,在这个循环中我基本上
Seek
查找有效帧

当找到有效帧时,
Seek()
返回true(通过调用
Seek()
找到的最后一帧存储在其他位置)<代码>检查标头()
验证标头的完整性
SkipAudioData()
读取帧的所有音频数据,将流标记放在帧的末尾

private boolean Seek() throws IOException {
    while(!(CheckHeader() && SkipAudioData())){
        if(!ShiftHeader()){
            return false;
        }
    }
    return true;
}


private boolean ShiftHeader() {
    try {
        if (bytesRead >= MPEG_FILE.length()) {
            return false;
        }
    } catch (Exception ex) {
        ex.printStackTrace();
        return false;
    }

    header[0] = header[1];
    header[1] = header[2];
    header[2] = header[3];

    try {
        int b = fis.read();
        if (b > -1) {
            header[3] = b;
            return true;
        }
    } catch (IOException ex) {
        return false;
    } catch (Exception ex) {
        return false;
    }

    return false;
}