Поиск в файле MP3 - PullRequest
       14

Поиск в файле MP3

0 голосов
/ 16 февраля 2020

Я работаю над разработкой программного обеспечения для аппаратной реализации этими людьми . В целом, декодер работает нормально, но я изо всех сил стараюсь, чтобы он начал воспроизводить звук посередине. Я подозреваю, что это общая черта MP3-декодеров, так как они должны иметь некоторую историю данных для правильного построения текущего звука (я не настолько квалифицирован в MPEG, однако имею представление о некоторых основах). Проблема в том, что этот декодер является черным ящиком, и любое углубление в его коде требует огромных усилий и времени. Опытным путем я обнаружил, что звуковой мусор при запуске где-то посередине происходит не более, чем через 1 (одну) секунду после запуска с файлом с частотой дискретизации 320 кбит / с и частотой дискретизации 44100. На самом деле я могу отключить декодер на секунду (пока он собирает / декодирует необходимые данные для дальнейшего воспроизведения), а затем включить его для продолжения воспроизведения.

Я выполнил поиск по inte rnet , не нашел ничего полезного. Попытка сделать недействительными первые кадры, повредив заголовки кадров (самое простое, что можно сделать, не вдаваясь в заголовки / данные MP3), еще больше ухудшило ситуацию.

Вопросы:

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

Обновление: только что попробовал другой файл @ 128 кбит / с / 48k и максимальное время мусора составляет около 2 секунд ... Я не могу поверить, что декодер с такими ограниченными ресурсами - используемый входной буфер составляет 2 КБ с некоторыми промежуточными рабочими буферами, всего должно быть не более 36 КБ - может сохранять историю в течение 2 секунд, или у декодера возникают проблемы с поиском syn c слово в потоке ... и, таким образом, моему драйверу необходимо выяснить начало кадра (путем определения слова syn c, чтения заголовка кадра, вычисления размера кадра и поиска кадра, чтобы он содержал другой синтаксис c слово).

1 Ответ

0 голосов
/ 17 февраля 2020

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

  1. У декодера возникли проблемы с получением первого син c слова потока, и работает очень хорошо, когда первые байты, предоставленные ему, являются FF FB или FF FA. Все остальные байты - в середине кадра - с очень высокой вероятностью вызывают серьезное искажение звука, пока декодер не отловит правильную синхронизацию c. Таким образом, я разработал код, ищущий начало следующего кадра после точки поиска, проверив, что это фактическое начало кадра, рассчитав размер кадра и посмотрев, что следующий кадр содержит FFFB / FA.
  2. Исправив проблема 1 У меня незначительное повреждение осталось от декодера, начиная декодировать кадр без исторических данных. Я решил это, отключив декодер для первых 4 транзакций буферизации.

Серьезное повреждение все еще происходит, но редко, и кажется, что природа повреждения зависит от того, что было в буферах декодера (не только входной буфер Хаффмана, но другие промежуточные буферы) перед тем, как декодер получает команду на запуск. Мое оборудование выполняет очистку входных буферов до 0, когда декодер находится в состоянии сброса, но этого, кажется, недостаточно (или просто неправильно) ...

Сам декодер является своего рода Po C ( доказательство концепции) работы, студенческий семестр с целью доказать, что они смогли это сделать; пакет содержит код тестового стенда, но не содержит документации / комментариев низкого уровня в коде и не готов к полевой реализации и производству. В целом тот факт, что он работал для меня вообще (почти) из коробки, делает честь разработчикам и является признаком высокого качества их работы. Я рассмотрел и опробовал несколько опубликованных проектов для MP3-декодеров для кремниевой реализации (FPGA) и пришел к выводу, что этот является лучшим из доступных. Кроме того, лицензия, на которую они предоставляют свою работу, достаточно велика.

Обновление: Мои исследования показали, что основная проблема заключается не во входном буфере (однако можно улучшить ситуация путем загрузки 528 байт исторических данных в буфер декодера, чтобы он мог получить основные данные из предыдущего кадра), но во внутреннем состоянии декодера. Его документация гласит:

Чтобы уменьшить использование ресурсов, часть ОЗУ для буферизации промежуточных данных также используется для декодирования Хаффмана как битовый резервуар ...

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

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

Я буду сохранять свои «лучшие» «проверенная» реализация, с примечаниями по качеству.

Обновление 2: Я ошибся, можно искать тихо, но для смягчения искажения звука (да, я все еще не уверен если я исправил это полностью) мне пришлось найти еще один недостаток в декодере: это связано с синхронизацией, декодер предполагает, что дополнительные данные всегда доступны в буфере, хотя их еще не может быть. (Это на самом деле ясно из кода тестового стенда, предоставленного в IP - способ пополнения данных во время QA и тестирования). В случаях, когда я обнаружил повреждение, первые кадры в первой части ОЗУ входного буфера не были должным образом декодированы, пропущены, и декодер быстро пропускает во вторую часть ОЗУ, предполагая, что есть новые данные, однако приводное оборудование еще не готово выборка требуемых данных и помещение этих данных во вторую часть буферной оперативной памяти декодера, таким образом, повреждение сохранялось в течение достаточно долгого времени с циклом декодера, пропускающим «недействительные» кадры, пока он не отловил правильное изображение кадра и не нормализовал его темп через буфер. *

Теперь решение:

  1. воспроизвести (почти) 5 кадров тишины через декодер, прежде чем включить его. Это обеспечит очистку всех внутренних буферов декодера. Это не займет много времени, однако требует некоторого кодирования;
  2. предоставляет возможность установить начальный указатель декодера Хаффмана readptrhuffctl.v ) после сброса в значение, отличное от 0 Это даст гибкость для загрузки некоторых исторических данных в буфер декодера и запуска декодера Хаффмана из середины буфера, а не с самого его начала;
  3. вычисляет позицию, к которой нужно стремиться, она вычисляется относительно легко для MPEG-1 Layer-3: duration = (filesize-ID3size) / (битрейт / 8 * 1000), newPosition = ID3size + seekTime * (битрейт / 8 * 1000). Длительность необходима для проверки этой позиции, чтобы она соответствовала времени воспроизведения, или же можно использовать newPosition для проверки размера файла. Эти форумы не учитывают более старые версии тегов, появляющиеся в конце файла, но они обычно не превышают 128 байт, что является своего рода незначительным для расчета времени относительно среднего размера звукового файла MP3; он также предполагает CBR (VBR потребует совершенно другого способа, требующего большей мощности и ввода / вывода данных для точного поиска). Как ни странно, я нашел веб-страницы с неправильной формулой расчета продолжительности, поэтому остерегайтесь постов невежественных людей с крутыми названиями должностей;
  4. Ищите на рассчитанную позицию, найдите следующий кадр с этой позиции, рассчитайте размер кадра и убедитесь, что на этом расстоянии находится следующий действительный кадр. Новый указатель будет указывать на этот следующий кадр, найденный на расстоянии;
  5. найти указатель обратного просмотра main_data_begin для фрейма, на который теперь указывает указатель на шаге 4. Уменьшите новый указатель на это значение, чтобы указатель указывал на предыдущий кадр до начала основных данных для текущего кадра - это будет указатель для начала данных декодера. Обратите внимание, что произойдет сбой, если основные данные начинаются более чем в одном кадре назад (для правильной работы потребуется удаление заголовков предыдущего кадра (ов);
  6. заполнить указатель начала буфера декодера, определенный на шаге 5, и установите указатель начала декодирования на тот, который был идентифицирован на шаге 4. Хотя реализация предполагает, что вы заполняете буфер пополам, делайте это иначе, чем в начале: заполняйте весь буфер, а не только первую половину. Для этого после сброса установите бит бездействия, проверьте запрос данных, сбросьте бит бездействия, выполните две 1024-байтовые передачи в буфер декодера (эффективно заполняя его полностью), затем установите бит бездействия, затем сбросьте его, а затем снова установите его ;
  7. после выполнения шага 7 продолжайте нормально пополнять 1024 байта на запрос декодера.

При использовании этого плана у меня не было случаев искажения звука. Как вы видите, это требует некоторых изменений в Verilog, но это должно быть легко, если вы знаете основы или аппаратное обеспечение, знайте, что Verilog amd может выполнять обратный инжиниринг.

...