2013-11-02 64 views
2

我正在開發一個基於java的音頻項目,它需要我根據它們的數據(而不是文件擴展名)來確定音頻文件類型,而且我已經用MP3播放了一面牆。據我所知,MP3文件被分解成幀,其中每個幀有一個4字節的頭,包含11幀的幀同步和各種其他數據。現在我的代碼可以準確地識別WAVE文件,但是當我開始讀取測試MP3文件的字節時,我無法在任何地方找到11111111字節(11個幀同步位中的前8個)。無法讀取MP3幀頭字節?

try { 
     FileInputStream fis = new FileInputStream(f); 
     ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
     byte[] buff = new byte[11]; 
     byte[] byteData; 
     int bytes = 0; 

     while ((bytes = fis.read(buff)) != -1) { 
      baos.write(buff, 0, buff.length); 
     } 

     byteData = baos.toByteArray(); 

     fis.close(); 
     baos.close(); 

     if ((int)byteData[0] == 255) { 
      type = "MP3"; 
     } else if (("" + (char)byteData[8] + (char)byteData[9] + 
       (char)byteData[10] + (char)byteData[11]) == "WAVE") { 
      type = "WAVE"; 
     } 

    } 

回答

2

你也許會發現前三個字節的MP3文件是:

49 44 33 

這就是 '幻數' 與ID3v2標籤的MP3 .... at least according to wikipedia

編輯

好的,所以我看了看我的系統,並且MP3中包含了我的魔法數字:

73 68 51 

其中ascii是'ID3'。

注意,你有一些問題,你的字節操作....當你測試字節值對int類型,你需要確保你做轉換權....測試:

byte x = ....; 
if (x == 255) {...} 

對於'x'的任何值都不會成立,因爲(byte)x的範圍是-128到+127。

爲了讓你需要做的測試工作:

if ((x & 0xff) == 255) { .... } 

我已經修改了你的方法,我的系統上測試的東西,並試圖WAV文件和一些MP3的。這是我有的代碼:

public static final String getValid(File f) throws IOException { 
    FileInputStream fis = new FileInputStream(f); 
    byte[] buff = new byte[12]; 
    int bytes = 0, pos = 0; 

    while (pos < buff.length && (bytes = fis.read(buff, pos, buff.length - pos)) > 0) { 
     pos += bytes; 
    } 

    fis.close(); 

    // this is your test.... which should bitmask the value too: 
    if ((buff[0] & 0x000000ff) == 255) { 
     return "MP3 " + f; 
    } 
    // My testing indicates this is the MP3 magic number 
    if ( 'I' == (char)buff[0] 
     && 'D' == (char)buff[1] 
     && '3' == (char)buff[2]) { 
     return "MP3 ID3 Magic" + f; 
    } 
    // This is the magic number from wikipedia (spells '1,!') 
    if (49 == buff[0] && 44 == buff[1] && 33 == buff[2]) { 
     return "MP3 ID3v2" + f; 
    } 
    if ( 'W' == (char)buff[8] 
     && 'A' == (char)buff[9] 
     && 'V' == (char)buff[10] 
     && 'E' == (char)buff[11]) { 
     return "WAVE " + f; 
    } 

    return "unknown " + f; 

} 
+0

現在我讀的第一個字節是'-1 -5 -78',它不會終止while循環。在我存儲信息的方式中可能存在錯誤嗎? – Chris

+0

是的,你做錯了事,我要編輯我的答案......但首先,你的意圖是隻讀取前11個字節? – rolfl

+0

是的,該文件的全部內容在別處讀取。我意識到當前返回的字節是正確的,因爲'-1 -5'包含我正在尋找的最初的11位。但我仍不完全確定這是否是處理MP3驗證的最佳方法。 – Chris