Как найти заголовки аудиоклипа MP3? - PullRequest
0 голосов
/ 13 апреля 2019

Основная проблема, которую я пытаюсь решить, состоит в том, чтобы найти длину аудиоклипа MP3, представленную в виде байтового массива.Чтобы найти длину, мне нужно найти число frames в клипе.Согласно спецификации MP3 , кадр представляет собой байт с 11 последовательными битами, установленными в 1;т. е. байт со значением 255, за которым следует байт с его старшим 3 битом, установленным в 1 (десятичное значение 224).Таким образом, по существу, когда я нахожу значение байта 255, я проверяю, имеет ли следующий байт значение 224. Но, учитывая этот критерий, я не могу найти заголовки фреймов в массиве.Кроме того, упомянутый документ также упомянул, что следующий байт после 255 может время от времени иметь свой 4 MSB, установленный в 1. Таким образом, я должен искать значение 240 после 255. В обоих случаях я не могу найти какой-либо кадрзаголовки.Пожалуйста, сообщите, если я делаю это правильно.

Это мой код:

public class AudioUtils
{  
    public static int getAudioLength(byte[] audio, AudioFormat audioFormat, int samples, int sampleRate)
    {
        if (!audioFormat.getId().equals(AudioFormat.MP3))
            throw new UnsupportedOperationException(String.format("Audio length computation for audio of format %s is not supported", audioFormat.getFormat()));

        int frames = getNumberOfFrames(audio);
        return ((frames * samples) / sampleRate);
    }

    private static int getNumberOfFrames(byte[] audio)
    {
        int frames = 0;
        for (int i = 0; i < audio.length; i++)
        {
            byte b = audio[i];
            int byteInt = b & 0xff; // convert byte to int
            if (byteInt == 255)
            {
                // If there is another byte in the array
                if (i + 1 < audio.length && (audio[i + 1] & 0xff) == 224)
                {
                    // We have found an header. Increment the frames count.
                    frames++;
                }
            }
        }

        return frames;
    }
}

1 Ответ

1 голос
/ 14 апреля 2019

Поскольку слово синхронизации имеет только 11 битов, а содержимое оставшихся 5 битов неизвестно, необходимо сравнить только первые 3 бита второго байта.Распространенный способ сделать это - использовать двоичный оператор '&', чтобы установить биты, которые вы хотите игнорировать, равными 0 (называемые маскированием), и установить те же биты в 0 в константе, с которой вы пытаетесь сравнить.

В приведенном ниже примере второй байт маскируется с помощью 0xe0 и сравнивается с тем же значением.

for (int i = 0; i < audio.length - 1; i++)
{
    if (audio[i] == 0xff && (audio[i+1] & 0xe0) == 0xe0)
    {
        frames++;
    }
} 
...