Не удается прочитать байты заголовка кадра MP3?

Я работаю над аудиопроектом в java, который требует, чтобы я определял типы аудиофайлов на основе их данных (в отличие от расширения файла), и я ударил стену с MP3. Насколько я понимаю, файлы MP3 разбиты на кадры, где каждый кадр имеет 4-байтовый заголовок, содержащий 11 для синхронизации кадров и набор других данных. Прямо сейчас мой код может точно идентифицировать файл WAVE, но когда я начинаю читать байты своего тестового файла MP3, я нигде не могу найти 11111111 байт (первые 8 из 11 битов синхронизации кадра).

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

    }

person Chris    schedule 02.11.2013    source источник


Ответы (1)


Вы, вероятно, обнаружите, что первые три байта файла MP3:

49 44 33

Это «магическое число» для MP3 с тегами ID3v2... по крайней мере, согласно википедии

РЕДАКТИРОВАТЬ

Итак, я посмотрел на свою систему, и 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;

}
person rolfl    schedule 02.11.2013
comment
Прямо сейчас первые байты, которые я читаю, это -1 -5 -78, что каким-то образом не завершает цикл while. Может ли быть ошибка в том, как я храню информацию? - person Chris; 02.11.2013
comment
Да, вы делаете что-то неправильно, я собираюсь отредактировать свой ответ .... но во-первых, вы намерены читать только первые 11 байтов? - person rolfl; 02.11.2013
comment
Да, полное содержимое файла читается в другом месте. Я понял, что текущие возвращаемые байты верны, так как -1 -5 содержат начальные 11 бит, которые я ищу. Однако я все еще не совсем уверен, что это лучший способ приблизиться к проверке MP3. - person Chris; 02.11.2013
comment
Отредактировал мой ответ. Обратите внимание на две вещи: нет необходимости в ByteArrayOutputStream, а также в манипулировании байтами. - person rolfl; 02.11.2013
comment
49 44 33 происходит из столбца «Шестнадцатеричная подпись» связанной статьи Википедии (эквивалентно десятичному 73 68 51 и US-ASCII ID3). - person lumato - Reinstate Monica; 07.02.2019