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;
}