8-900-374-94-44
[email protected]
Slide Image
Меню

Структура mp3 файла: Внутри MP3. А как оно всё устроено? / Хабр

Внутри MP3. А как оно всё устроено? / Хабр

Однажды мне понадобилось решить простенькую (как мне тогда казалось) задачу – в PHP-скрипте узнать длительность mp3-файла. Я слышал о ID3 тегах и сразу подумал, что информация о длительности хранится либо в тегах, либо в заголовках mp3-файла. Поверхностные поиски в интернете показали что за пару-тройку минут решить эту задачу не получится. Поскольку от природы я довольно любопытен а время не поджимало — решил не использовать сторонние инструменты а разобраться в одном из самых популярных форматов самостоятельно.

Если Вам интересно, что там внутри – добро пожаловать под кат (трафик).

В данной статье мы не будем подробно останавливаться на извлечении ID3v2 тегов – это можно вынести в отдельную статью, так как там есть различные нюансы. А так же на фрагментах заголовков, которые практически не используются в настоящее время (например, часть Emphasis заголовка mp3-фрейма). Так же мы не рассматриваем структуру самих аудиоданных — тех самых, которые слышим из колонок.


ID3 (от англ. Identify a MP3) — формат метаданных, наиболее часто используемый в звуковых файлах в формате MP3. ID3 подпись содержит данные о названии трека, альбома, имени исполнителя и т. д., которые используются мультимедиапроигрывателями и другими программами, а также аппаратными проигрывателями, для отображения информации о файле и автоматического упорядочивания аудиоколлекции.

Wikipedia

Существует две абсолютно разных версии ID3-данных: ID3v1 и ID3v2.

ID3v1 – имеет фиксированный размер в 128 байт, которые дописываются в конец mp3-файла. Там можно хранить: название трека, исполнитель, альбом, год, комментарий, номер трека (для версии 1.1) и жанр.

Довольно быстро всем стало понятно, что 128 байт – очень уж небольшое место для хранения таких данных. И поэтому, со временем, появилась и успешно используется вторая версия данных – ID3v2.
В отличии от первой версии, теги v2 имеют переменную длину и размещаются в начале файла, что позволяет поддерживать потоковое воспроизведение.

(Формат ID3v2.4 позволяет так же хранить данные и в конце файла).
Данные ID3v2 состоят из заголовка и последующих фреймов ID3v2. Например, в версии ID3v2.3 существует более 70 типов фреймов.


  • маркер всегда равен ‘ID3’
  • В данный момент имеются три версии ID3v2.2, ID3v2.3 и ID3v2.4
    Версия v2.2 считается устаревшей.
    v2.3 – самая популярная версия.
    v2.4 – набирает популярность. Одно из отличий от v2.3 в том, что позволяет использовать кодировку UTF-8 (а не только UTF-16)
  • Флаги. В настоящее время используются только три (5,6,7) бита:
    bin: %abc00000
    a ‘unsynchronisation’ – используется только с MPEG-2 и MPEG-2.5 форматами.
    b ‘Extended header’ – указывает на наличие расширенного заголовка
    с ‘Experimental indicator’ – эксперементальный индикатор
  • Длина. Особенность указания длины данных ID3v2 в том, что в каждом байте 7-й бит не используется и всегда установлен в 0.

Рассмотрим пример:

В данном случае вместе с заголовком ID3v2 (10 байт) – данные ID3v2 занимают 1024 байта.

После ID3v2-заголовка идут собственно теги. Подробный разбор чтения тегов ID3v2, как сказано выше, я решил не включать в эту статью.

Теперь у нас есть информация о наличии и длине тегов ID3 и мы можем приступать в разбору mp3-фрейма и понять-таки – где же хранится длительность. А заодно понять и всё остальное.

Весь mp3-файл состоит из фреймов, которые можно извлекать только последовательно. Фрейм содержит в себе заголовок и аудио-данные. Поскольку мы не ставим себе целью написать прошивку для магнитофона – нас интересует именно заголовок фрейма.

О нем подробнее (куча таблиц и сухой информации)

Размер заголовка – 4 байта.

Описание:

  • [0-10] Маркер – 11 бит, заполненные единицами (Frame sync)
  • [11-12] Индекс версии MPEG (Audio version ID)
  • [13-14] Индекс версии Layer (Layer index)

    Кстати, MP3 – это MPEG-1 Layer III
  • [15] Бит защиты (Protection bit)
    1 – нет защиты
    0 – заголовок защищен 16-бит. CRC (следует за заголовком)
  • [16-19] Индекс битрейта (Bitrate index)

    В таблице хранятся значения битрейта в килобит/сек. Однако в данном формате подразумевается, что 1 килобит = 1000 бит, а не 1024. Таким образом 96 Кбит/сек = 96000 бит/сек.
  • [20-21] Индекс частоты дискретизации (Sampling rate index)
  • [22] Бит смещения (Padding bit)
    Если он установлен, то данные смещаются на 1 байт. Это важно для расчета размера фрейма.
  • [23] Бит private (только для информации)
  • [24-25] Режим канала (Channel mode)
  • [26-27] Расширение режима канала. (Mode extension) Используется только с Joint stereo
  • [28] Копирайт (Copyright bit) – только для информации
  • [29] Оригинал (Original bit) – только для информации.
  • [30-31] Акцент (Emphasis) – в данный момент практически не используется.

Режимы сжатия данных или какой бывает битрейт

Существует 3 режима сжатия данных:

CBR (constant bitrate) – постоянный битрейт. Не меняется на всем протяжении трека.

VBR (variable bitrate) – переменный битрейт. При этом сжатии битрейт постоянно меняется на протяжении трека.

ABR (average bitrate) – усредненный битрейт. Это понятие используется только при кодировании файла. На «выходе» получается файл с VBR.

CBR

Если файл закодирован с постоянным битрейтом – то мы уже можем

наконец-то!

получить длительность нашего трека по следующей формуле:

Длительность = Размер аудиоданных / Битрейт (в битах!) * 8

Например, файл имеет размер 350670 байт. Есть ID3v1 теги (128 байт) и ID3v2 теги (1024 байта). Битрейт = 96. Следовательно размер аудиоданных равен 350670 – 128 – 1024 = 349518 байт.
Длительность = 349518 / 96000 * 8 = 29,1265 = 29 секунд

VBR

Необходимо пояснить – как определить режим сжатия. Всё просто. Если файл сжат с VBR – то добавляется VBR-заголовок. По его наличию мы и можем понять, что используется переменный битрейт.
Есть два вида заголовков: Xing и VBRI.
Xing размещается со смещением от начала первого mp3-фрейма в позиции, согласно таблице:

Например: у нас ID3v2 тег занимает 1024 байта. Если наш mp3-файл имеет режим канала «Стерео» — то заголовок VBR Xing будет начинаться со смещения 1024 + 32 = 1056 байт.

Заголовок VBRI всегда размещается со смещением +32 байта от начала первого mp3-фрейма.

Первые четыре байта в обоих заголовках содержат маркер ‘Xing’ или ‘Info’ для Xing. И ‘VBRI’ для VBRI.

Эти VBR заголовки имеют переменную длину и содержат различную информацию о кодировании файла. Подробнее о структуре заголовков VBR (и не только) можно почитать, например, тут.

Я же расскажу только о том, что нас интересует в данный момент. А именно – количество фреймов (Number of Frames). Это число длиной 4 байта.
В заголовке Xing оно содержится по смещению +8 байт от начала заголовка. В VBRI +14 байт от начала заголовка.

Используя таблицу Сэмплов на фрейм (Sampler Per Frame) мы можем получить длительность mp3-файла, закодированного с переменным битрейтом.

Длительность = Количество фреймов * Сэмплов на фрейм / Частоту дискретизации

Например: из заголовка VBRI получили количество фреймов 1118, сэмплов на фрейм = 1152. Частота дискретизации = 44100.
Длительность = 1118 * 1152 / 44100 = 29.204 = 29 секунд.


На этом на сегодня всё. Если был кому-то полезен — спасибо.

Для тех, кто захочет немедленно поковырять внутренности mp3 — Тут лежат скрипт на php, которые я писал для себя одновременно с данной статьей и четыре небольших mp3-файла для теста.

Ссылки

id3.org — Читаем о ID3
id3.org — и кое-что о mp3 frame
Довольно подробно о mp3 frame
getID3: Неплохая библиотека для получения информации о mp3. (PHP)

Структура MP3 файла — Audio Coding

В этой статье приводится спецификация заголовка MP3 формата. Перевод с английского.

Определенного заголовка у файла нет, вместо этого есть заголовок у каждого фрейма. Фрейм — часть аудио данных со своим заголовком. Т.е. в файле фреймов может присутствовать хоть тысяча, хоть миллион и у каждого из них будет свой заголовок. В файлах, закодированных уровнем I/II (MPEG Audio Layer I/II), фреймы абсолютно независимы и могут воспроизводиться отдельно друг от друга. После появления уровня III (MPEG Audio Layer III), фреймы стали зависимыми и теперь, чтобы воспроизвести один фрейм может потребоваться до 9 других фреймов (это произошло из-за использования «резервуара байтов» — некоего буфера).

Размер фрейма 32 бита (4 байта). Первые 12 бит (или первые 11 бит для MPEG 2.5 расширения) заголовка фрейма всегда установлены в 1 и называются «frame sync».

Далее — таблица, соотносящая биты с их значениями.

Длина в битахПозиция в битахОписание
11(31-21)Frame sync (все биты должны быть равны 1)
2(20,19)Идентификатор версии MPEG Audio 00 — MPEG Версии 2.
5 (более позднее расширение MPEG-2) 01 — зарезервировано 10 — MPEG Версии 2 (ISO/IEC 13818-3) 11 — MPEG Версии 1 (ISO/IEC 11172-3)
2(18,17)Идентификатор уровня 00 — зарезервировано 01 — Layer III 10 — Layer II 11 — Layer I
1(16)0 — Защита CRC (16 bit CRC follows header) 1 — Нет защиты
4(15-12)Индекс битрейта
битыV1, L1V1, L2V1, L3V2, L1V2, L2 & L3
0000свободныйсвободныйсвободныйсвободныйсвободный
0001323232328
00106448404816
00119656485624
010012864566432
010116080648040
011019296809648
01112241129611256
100025612811212864
100128816012814480
101032019216016096
1011352224192176112
1100384256224192128
1101416320256224144
1110448384320256160
1111неверныйневерныйневерныйневерныйневерный

Примечания: Все значения V1 — MPEG Версия 1 V2 — MPEG Версия 2 и Версия 2. 5 L1 — Layer I L2 — Layer II L3 — Layer III

«свободный» означает свободный формат. Свободный битрейт должен быть постоянным (CBR) и должен быть ниже максимально дозволенного. Со стороны декодера поддержка потока данных со свободным битрейтом не требуется. «неверный» означает, что значение за пределами дозволенного.

В MPEG файлах также может быть и переменный битрейт (VBR). В таком случае, каждый фрейм может быть создан с различным битрейтом. Это может быть использовано во всех уровнях. Декодеры Layer III должны поддерживать этот метод. Декодеры Layer I и Layer II могут поддерживать это.

Для Layer II могут быть некоторые недозволенные комбинации битрейта и режима. Вот список этих комбинаций:

битрейтодин каналстереоинтенсивное стереодва канала
свободныйдададада
32данетнетнет
48данетнетнет
56данетнетнет
64дададада
80данетнетнет
96дададада
112дададада
128дададада
160дададада
192дададада
224нетдадада
256нетдадада
320нетдадада
384нетдадада
2(11,10)Индекс частоты дискретизации
битыMPEG1MPEG2MPEG2. 5
0044100 Hz22050 Hz11025 Hz
0148000 Hz24000 Hz12000 Hz
1032000 Hz16000 Hz8000 Hz
11зарезервированозарезервированозарезервировано
1(9)Бит заполненности 0 — фрейм заполнен 1 — фрейм заполнен с одним лишним слотом

Заполненность нужна чтобы точно уложиться во фрейм. Как пример: 128kbps 44.1kHz уровень II использует фреймы в большинстве своем из 418 байтов и некоторые из 417 байтов длиной, чтобы получить точный битрейт 128k. Для уровня I слот 32 бита длиной, для уровня II и уровня III слот длиной в 8 бит.

1(8)Персональный бит. Всего лишь для информации.
2(7,6)Каналы 00 — Stereo (стерео) 01 — Joint stereo (совместное стерео) 10 — Dual channel (2 моно канала) 11 — Single channel (моно)

Примечание: Dual channel режим является двумя абсолютно независимыми моно каналами. Каждый использует точно половину битрейта самого файла. Многие декодеры выводят его как стерео, но на самом деле дела могут обстоять не совсем так. Одним из примеров использования может быть речь на двух разных языках, несущаяся в этом битовом потоке, и затем, предполагается, подходящим декодером будет декодирован только выбранный язык.

2(5,4)Расширение режима (Используется только вместе с Joint stereo)

Расширение режима используется для соединения информации, которая не используется для стерео эффекта, таким образом уменьшается количество требуемых битов. Эти биты динамически определяются кодером в режиме Joint Stereo, и Joint Stereo может меняться в разных фреймах и даже включаться или выключаться.

Полный диапазон частоты звучания в MPEG файле разделена на подмножества. Всего 32 таких подмножества. Для уровня I и II эти два бита определяют подмножества, где применено Intensity stereo. Для уровня III эти два бита определяют, что за тип Joint Stereo используется (Intensity stereo или m/s stereo). Диапазон частоты определен внутри декодирующего алгоритма.

Уровень I и IIУровень III
значениеУровень I & II
00подмножеств от 4 до 31
01подмножеств от 8 до 31
10подмножеств от 12 до 31
11подмножеств от 16 до 31
Intensity stereoMS stereo
выключеновыключено
включеновыключено
выключеновключено
включеновключено
1(3)Авторское право 0 — Не защищено авторскими правами 1 — Защищено авторскими правами
1(2)Оригинал 0 — Копия оригинальной композиции 1 — Оригинальная композиция
2(1,0)Выразительность 00 — отсутствует 01 — 50/15 ms 10 — зарезервировано 11 — CCIT J. 17

Выразительность здесь используется, чтобы сообщить декодеру, что файл должен быть переделан обратно, то есть, декодер должен провести обработку амплитудно-частотного соотношения в звуке после схемы шумоподавления, подобной Dolby. Это редко используется.

c++ — Чтение файлов MP3

спросил

Изменено 11 лет, 3 месяца назад

Просмотрено 49 тысяч раз

Я хочу читать файлы MP3 на C++ и предпочитаю писать для этого собственный код. В основном, чтобы узнать, как работает тип файла. Я хочу прочитать все биты шестнадцатеричных данных файла MP3 и воспроизвести их на моих динамиках. 🙂 Я понятия не имею, с чего начать, так как я еще не знаю, как данные на самом деле сохраняются в файле MP3.

Спасибо за помощь

  • c++
  • mp3

1

Начните с изучения структуры mp3-файла. Затем, если вам все еще интересно, найдите хороший учебник о том, как декодировать аудиоданные в каждом кадре. Это довольно сложно, поэтому вам понадобится немало времени, чтобы сделать это с нуля.

2

Вы можете купить спецификацию для формата MP3 здесь. Это около 160 евро.

Да, и кстати, это не «шестнадцатеричные данные». Если вы все еще находитесь в точке, где вы называете любые данные, не предназначенные для чтения человеком, «шестнадцатеричной» (которая является системой счисления), погружение с головой в двоичный формат данных, который включает сложные алгоритмы декодирования/кодирования, может быть немного слишком много для вас на данный момент.

Как насчет того, чтобы начать с написания проигрывателя, который может воспроизводить файлы . wav? (Заметьте, любой подходящий файл .wav, принимая во внимание формат файла и различные аудиоформаты)

5

Я провел небольшое исследование, может оно вам поможет.

Структура файла

Файл MP3 состоит из нескольких кадров MP3, состоящих из заголовка и блока данных. Эта последовательность кадров называется элементарным потоком. Кадры не являются независимыми элементами («хранилищем байтов») и поэтому не могут быть извлечены на произвольных границах фреймов. Блоки данных MP3 содержат (сжатую) аудиоинформацию с точки зрения частот и амплитуд. На диаграмме показано, что заголовок MP3 состоит из слова синхронизации, которое используется для идентификации начала допустимого кадра. За ним следует бит, указывающий, что это стандарт MPEG, и два бита, указывающие на то, что используется уровень 3; следовательно, MPEG-1 Audio Layer 3 или MP3. После этого значения будут различаться в зависимости от файла MP3. ISO/IEC 11172-3 определяет диапазон значений для каждого раздела заголовка вместе со спецификацией заголовка. Большинство файлов MP3 сегодня содержат метаданные ID3, которые предшествуют кадрам MP3 или следуют за ними; как отмечено на схеме.

Исходный код LAME

LAME — это библиотека MP3, но она также имеет открытый исходный код, что означает, что вы можете загрузить исходный код и изучить его. http://sourceforge.net/projects/lame/files/lame/3.98.4/lame-3.98.4.tar.gz/download Я сам посмотрел на него, и он, кажется, написан на C или C++, так что вам повезло. Если вы изучите исходный код LAME и поймете, как он работает, возможно, вам удастся создать собственную библиотеку MP3. Просто обратите внимание, что LAME — это библиотека не для воспроизведения файлов MP3, а для их кодирования. Но поскольку он создает MP3, а не читает их, я думаю, что структура должна быть немного более ясной, чем с любой другой библиотекой MP3-плеера.

Объяснение формата файла MP3

Это также, кажется, объясняет, как работает MP3 довольно хорошо, но это чистая теория, так что вам понадобится много терпения. http://www.mp3-converter.com/mp3codec/

0

Ну, это было бы жестко 🙂

В любом случае, ваше приложение должно состоять из двух частей — декомпрессионная библиотека/подпрограммы и ваш основной бэкенд , который бы занял некоторый распакованный блок данных и собственно сыграй.

Я бы порекомендовал «Сжатие данных» книгу Дэвида Соломона чтобы понять, как ваш декодер должен делать это на самом деле . Варианты для ваших вторых частей, к сожалению, слишком широки, чтобы охватить их одним предложением.

Вы также можете попробовать исследовать некоторые mp3 декодеры / декодирующие библиотеки с открытым исходным кодом, подобные этой.

1

Если вы настаиваете на том, чтобы сделать это самостоятельно, вам придется начать со спецификации:

http://mpgedit. org/mpgedit/mpeg_format/MP3Format.html

задача, что-то вроде http://sourceforge.net/projects/mpg123net/

Также есть декодер MAD… http://www.underbit.com/products/mad/

Чтобы правильно прочитать mp3 файл есть много математики, и я думаю, что вы действительно не хотите вдаваться в это…

заголовок — Определить, является ли файл файлом MP3?

Задавать вопрос

спросил

Изменено 3 года, 1 месяц назад

Просмотрено 26 тысяч раз

Я пишу библиотеку C++ для декодирования и кодирования аудио между различными форматами/кодеками. У меня есть процедура для быстрого определения формата перед загрузкой необходимой библиотеки кодеков.

Для файлов WAV можно просто найти значения ASCII «RIFF» и «WAVE» в начале файла. То же самое относится и к FLAC, мы можем просто прочитать первые 4 байта, которые будут «fLaC».

Но как быстро определить, является ли файл MP3? Я не могу полагаться на расширение файла. Я также не могу попытаться декодировать первый кадр MP3, так как в начале файла могут быть дополнительные данные (например, ID3, обложка и т. д.).

  • заголовок
  • mp3
  • обнаружение
  • decoding
  • flac

Определить, является ли файл MP3, сложнее, чем найти фиксированный шаблон в файле.

Некоторые концепции

(подробности см. на http://www.codeproject.com/Articles/8295/MPEG-Audio-Frame-Header)