Из Википедии, бесплатной энциклопедии
Перейти к навигации Перейти к поиску

ADX является потери собственного аудио хранение и форматом сжатия , разработанный CRI Middleware специально для использования в видеоиграх ; он получен из ADPCM . Его наиболее примечательной особенностью является функция зацикливания, которая оказалась полезной для фоновых звуков в различных играх, которые приняли этот формат, включая многие игры для Sega Dreamcast, а также некоторые игры для PlayStation 2 , GameCube и Wii . Одной из первых игр, в которых использовался ADX, была игра Burning Rangers на Sega Saturn . Примечательно, что серия Sonic the Hedgehogот поколения Dreamcast до по крайней мере Shadow the Hedgehog использовали этот формат для звукозаписи и голосовых записей.

Помимо основного кодирования ADPCM, набор инструментов ADX также включает родственный формат AHX, в котором используется вариант аудио MPEG-2, специально предназначенный для голосовых записей, и архивный архив AFS для объединения нескольких дорожек ADX и AHX в одну. файл-контейнер.

Версия 2 формата (ADX2) использует расширения HCA и HCA-MX, которые обычно объединены в файл-контейнер с расширениями ACB и AWB. Расширение AWB не следует путать с аудиоформатом с таким же расширением и в основном содержит двоичные данные для файлов HCA.

Общий обзор [ править ]

ADX - это сжатый аудиоформат, но в отличие от MP3 и аналогичных форматов, он не применяет психоакустическую модель к звуку, чтобы уменьшить его сложность. Вместо этого модель ADPCM сохраняет образцы, записывая ошибку, относящуюся к функции прогнозирования, что означает, что большая часть исходного сигнала выживает в процессе кодирования; как таковое сжатие ADPCM вместо этого торгует точностью представления для размера за счет использования относительно небольших размеров выборки, обычно 4 бита. Устойчивость слуховой системы человека к вызываемому шуму делает потерю точности едва заметной.

Как и другие форматы кодирования, ADX поддерживает несколько частот дискретизации, например 22050 Гц., 44100 Гц, 48000 Гц и т. Д., Однако глубина выходной выборки зафиксирована на уровне 16 бит, как правило, из-за уже упомянутой недостаточной точности. Он поддерживает несколько каналов, но, похоже, существует неявное ограничение стереозвука (2 канала), хотя сам формат файла может представлять до 255 каналов. Единственная особенно отличительная особенность, которая отличает ADX от альтернатив, таких как IMA ADPCM (кроме наличия другой функции прогнозирования), - это встроенная функция зацикливания, которая позволяет аудиоплееру опционально переходить назад после достижения одной указанной точки на дорожке для создания связная петля; гипотетически, эту функцию можно было бы использовать и для перехода вперед, но это было бы избыточным, поскольку вместо этого звук можно было бы просто обрезать с помощью программы редактирования.

Для воспроизведения есть несколько плагинов для WinAmp и инструмент преобразования в волну (см. Раздел ссылок). В программе / библиотеке с открытым исходным кодом FFmpeg также реализована поддержка ADX, однако ее декодер жестко запрограммирован, поэтому может правильно декодировать только ADX с частотой 44100 Гц.

Техническое описание [ править ]

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

В качестве примечания, АСПО архивировать файлы , которые ADXs иногда упакованы в это простой вариант тарболла , который использует числовые индексы для идентификации содержимого , а не имена. Исходный код экстрактора можно найти в архиве ADX по адресу. [1]

Заголовок файла [ править ]

Формат диска ADX определяется с прямым порядком байтов . Выявленные разделы основного заголовка приведены ниже:

Поля с пометкой «Неизвестно» содержат либо неизвестные данные, либо явно зарезервированы (т.е. заполнены нулевыми байтами). Поля, помеченные как «v3» или «v4», но не оба, считаются «Неизвестными» в той версии, которой они не отмечены. Этот заголовок может быть всего 20 байтов (0x14), как определено смещением авторских прав, что неявно исключает поддержку цикла, поскольку эти поля отсутствуют.

Поле «Тип кодировки» должно содержать одно из:

  • 0x02 для ADX с предустановленными коэффициентами прогнозирования
  • 0x03 для стандартного ADX
  • 0x04 для ADX с экспоненциальным масштабом
  • 0x10 или 0x11 для AHX

Поле «Версия» должно содержать одно из:

  • 0x03 для ADX версии 3
  • 0x04 для ADX версии 4
  • 0x05 для варианта ADX 4 без поддержки цикла

При декодировании аудио AHX поле версии не имеет никакого значения и может быть проигнорировано.

Файлы с типом кодирования 2 используют 4 возможных набора коэффициентов предсказания, как указано ниже:

Пример формата [ править ]

Аудиоданные, закодированные в ADX, разбиваются на серию «блоков», каждый из которых содержит данные только для одного канала. Затем блоки размещаются в «кадрах», которые состоят из одного блока от каждого канала в порядке возрастания. Например, в стереофоническом (2-канальном) потоке это будет состоять из кадра 1: блока левого канала, блока правого канала; Кадр 2: слева, справа; Блоки обычно имеют размер 18 байт и содержат 4-битные выборки, хотя технически возможны другие размеры, пример такого блока выглядит следующим образом:

Первые 3 бита целого числа «Predictor / Scale» содержат индекс предиктора. Масштаб содержится в оставшихся 13 битах.

Индекс предсказателя - это 3-битное целое число, которое указывает, какой набор коэффициентов предсказания должен использоваться для декодирования этого блока. Используется только в файлах с типом кодировки «2».

Масштаб представляет собой 13-битное целое число без знака ( с прямым порядком байтов, как в заголовке), которое, по сути, является усилением всех выборок в этом блоке. Каждая выборка в блоке должна быть декодирована в порядке потока битов, то есть сначала старший бит. Например, если размер выборки составляет 4 бита:

Сами образцы не перевернуты, поэтому нет необходимости возиться с ними после их извлечения. Каждый сэмпл подписан, поэтому в этом примере значение может находиться в диапазоне от -8 до +7 (которое будет умножено на масштаб во время декодирования). В стороне, хотя любая битовая глубина от 1 до 255 возможна благодаря заголовку. Маловероятно, что когда-либо возникнут однобитовые выборки, поскольку они могут представлять только значения {0, 1}, {-1, 0} или {-1, 1}, все из которых не особенно полезны для кодирования песен - если они тогда неясно, какая из трех возможностей является правильной интерпретацией.

Декодирование ADX [ править ]

В этом разделе рассматривается декодирование ADX версии 3 или версии 4, когда «Тип кодирования» - «Стандартный ADX» ( 0x03 ). Кодировщик также можно построить, просто перевернув код в обратном порядке. Все примеры кода в этом разделе написаны с использованием C99 .

Перед тем как «стандартный» ADX можно будет либо закодировать, либо декодировать, необходимо вычислить набор коэффициентов предсказания. Обычно это лучше всего делать на этапе инициализации:

 #define M_PI acos (-1.0)  double  a ,  b ,  c ;  = SQRT ( 2.0 ) - сов ( 2.0 * M_PI * (( дважды ) adx_header -> highpass_frequency / adx_header -> sample_rate )); b = sqrt ( 2.0 ) - 1.0 ; c = ( a - sqrt (( a + b ) *                        ( а  -  б )))  /  б ;  // (a + b) * (ab) = a * ab * b, однако более простая формула теряет точность с плавающей запятой  // двойной коэффициент [2];  коэффициент [ 0 ]  =  c  *  2,0 ;  коэффициент [ 1 ]  =  - ( c  *  c );

Этот код вычисляет коэффициенты предсказания для предсказания текущей выборки из 2 предыдущих выборок. Эти коэффициенты также образуют фильтр верхних частот с конечной импульсной характеристикой первого порядка . [ требуется разъяснение ]

Как только мы узнаем коэффициенты декодирования, мы можем начать декодирование потока:

 статический  int32_t *  past_samples ;  // Ранее декодированные выборки из каждого канала, обнуленные в начале (size = 2 *  channel_count ) static  uint_fast32_t  sample_index  =  0 ;  // sample_index - это индекс набора выборок, который необходимо декодировать следующим  статическим  ADX_header *  adx_header ;  // буфер - это то место, куда будут помещены декодированные образцы  // samples_needed указывает, сколько наборов образцов (один образец из каждого канала) необходимо декодировать для заполнения буфера  // looping_enabled - это логический флаг для управления использованием встроенного in loop  // Возвращает количество «наборов» выборок в буфере, который не может быть заполнен (EOS)  unsigned  decode_adx_standard (  int16_t *  buffer ,  unsigned  samples_needed ,  bool  looping_enabled  )  {  unsigned  const  samples_per_block  =  ( adx_header -> block_size  -  2 )  * 8  /  adx_header -> sample_bitdepth ;  int16_t  шкала [  adx_header -> channel_count  ];  if  ( looping_enabled  &&  ! adx_header -> loop_enabled )  looping_enabled  =  false ;  // Цикл до тех пор, пока не будет декодировано запрошенное количество сэмплов или пока не будет достигнут конец файла  while  ( samples_needed  >  0  &&  sample_index  <  adx_header -> total_samples )  {  // Рассчитываем количество сэмплов, которые остались для декодирования в текущем блоке  неподписанный  sample_offset  =  sample_index  %  samples_per_block ;  беззнаковый  samples_can_get  =  samples_per_block  -  sample_offset ; // Ограничить выборки, которые мы можем получить во время этого прогона, если они не помещаются в буфер  if  ( samples_can_get  >  samples_needed )  samples_can_get  =  samples_needed ;  // Ограничить количество выборок, которые нужно получить, если поток недостаточно длинный или триггер цикла находится поблизости  if  ( looping_enabled  &&  sample_index  +  samples_can_get  >  adx_header -> loop_end_index )  samples_can_get  =  adx_header -> loop_end_index  -  sample_index ;  иначе,  если  ( sample_index  +  samples_can_get  >  adx_header -> total_samples )  samples_can_get  =  adx_header -> total_samples  - sample_index ;  // Вычислить битный адрес начала кадра , который находится в sample_index и запись этого места  без знака  длиной  started_at  =  ( adx_header -> copyright_offset  +  4  + \ sample_index  /  samples_per_block  *  adx_header -> BLOCK_SIZE  *  adx_header -> channel_count )  *  8 ;  // Чтение значения шкалы от начала каждого блока в этом кадре  для  ( без знака  I  =  0  ;  я  <  adx_header -> channel_count  ;  ++ я )  {  bitstream_seek (  started_at  +  adx_header -> block_size  *  я  *  8  );  scale [ i ]  =  ntohs (  bitstream_read (  16  )  );  }  // Предварительное вычисление стоп-значения для sample_offset  unsigned  sample_endoffset  =  sample_offset  +  samples_can_get ;  // Сохраняем адрес битового потока первой выборки сразу после шкалы в первом блоке кадра  start_at  + =  16 ; в  то время как  (  sample_offset  <  sample_endoffset  )  {  для  ( без знака  я  =  0  ;  я  <  adx_header -> channel_count  ;  ++ я )  {  // предсказать следующий пример  двойной  sample_prediction  =  коэффициент [ 0 ]  *  past_samples [ я * 2 +  0 ]  +  коэффициент [ 1 ]  *  past_samples [ i * 2  +  1 ];  // Ищем смещение образца, считываем и подписываем, расширяем его до 32-битного целого числа  // Реализация расширения знака оставлена ​​в качестве упражнения для читателя  // Расширение знака также должно включать поправку на порядок байтов, если имеется более 8 бит  bitstream_seek (  start_at  +  adx_header -> sample_bitdepth  *  sample_offset  + \ adx_header -> block_size  *  8  *  i  );  int_fast32_t  sample_error  =  bitstream_read (  adx_header -> sample_bitdepth  );  sample_error =  sign_extend (  sample_error ,  adx_header -> sample_bitdepth  );  // Масштабируем значение коррекции ошибок  sample_error  * =  scale [ i ];  // Рассчитываем выборку, комбинируя прогноз с исправлением ошибок  int_fast32_t  sample  =  sample_error  +  ( int_fast32_t ) sample_prediction ;  // Обновить прошлые образцы с помощью более нового образца  past_samples [ i * 2  +  1 ]  =  past_samples [ i * 2  +  0 ];  past_samples [ я * 2  +  0 ]  =  образец ;  // Ограничить декодированный образец до допустимого диапазона для 16-битного целого числа  if  ( sample  >  32767 )  sample  =  32767 ;  иначе,  если  ( образец  <  -32768 )  образец  =  -32768 ;  // Сохраняем семпл в буфер и продвигаемся на одно место  * buffer ++  =  sample ;  }  ++ sample_offset ;  // Мы декодировали по одной выборке из каждого блока, смещение блока  увеличено на 1 ++ sample_index ;  // Это также означает, что мы на один образец дальше в потоке  - samples_needed ;  // Итак, осталось на один набор выборок, которые нужно декодировать, меньше  }  // Проверяем, попали ли мы в маркер конца цикла, если нам нужно перейти к началу цикла  if  ( looping_enabled  &&  sample_index  ==  adx_header -> loop_end_index )  sample_index  =  adx_header -> loop_start_index ;  }  вернуть  samples_needed ;  }

Большая часть приведенного выше кода должно быть достаточно простым для тех , кто разбирается в C . ADX_headerУказатель ' ' относится к данным, извлеченным из заголовка, как описано ранее, предполагается, что они уже были преобразованы в порядок байтов узла. Эта реализация не является оптимальной, и внешние проблемы были проигнорированы, такие как конкретный метод расширения знака и метод получения битового потока из файла или сетевого источника. После его завершения в выходном буфере появятся наборы семплов (если стерео, будут пары, например) семплов . Декодированные образцы будут в стандартном PCM с чередованием с порядком байтов от хоста.формат, т.е. левый 16 бит, правый 16 бит, левый, правый и т. д. Наконец, если цикл не включен или не поддерживается, функция вернет количество пробелов выборки, которые не использовались в буфере. Вызывающий может проверить, не равно ли это значение нулю, чтобы определить конец потока и при необходимости сбросить или записать тишину в неиспользуемые пробелы.

Шифрование [ править ]

ADX поддерживает простую схему шифрования, в которой значения XOR из генератора линейных конгруэнтных псевдослучайных чисел сравниваются со значениями шкалы блоков. Этот метод дешифровки с вычислительной точки зрения не требует больших затрат (в соответствии с декодированием в реальном времени ADX), но делает зашифрованные файлы непригодными для использования. Шифрование активно, когда значение «Флаги» в заголовке равно 0x08 . Поскольку XOR является симметричным, для дешифрования используется тот же метод, что и для шифрования. Ключ шифрования - это набор из трех 16-битных значений: множитель, приращение и начальные значения для линейного конгруэнтного генератора (модуль равен 0x8000, чтобы сохранить значения в 15-битном диапазоне допустимых масштабов блока). Обычно все файлы ADX из одной игры используют один и тот же ключ.

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

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

Декодирование AHX [ править ]

Как отмечалось ранее, AHX - это просто реализация аудио MPEG2, а метод декодирования в основном такой же, как и стандартный, можно просто демультиплексировать поток из контейнера ADX и передать его через стандартный аудиодекодер MPEG, например mpg123 . «Частота дискретизации» и «общее количество отсчетов» заголовка ADX обычно верны, если они нужны декодеру (поэтому они должны быть установлены реализациями кодировщика / мультиплексора), но большинство других полей, таких как «размер блока» и «битовая глубина образца», будут обычно равняется нулю - как отмечалось выше, функция цикла также недоступна.

Ссылки [ править ]

  1. ^ "Название неизвестно" . Архивировано из оригинала на 2009-03-18.
  • Страница продукта ADX на сайте CRI Middleware
  • Кодек vgmstream WinAMP с исходным кодом (поддерживает ADX)
  • Утилиты Dreamcast, включая преобразователи ADX с исходным кодом ((2009-10-24)
  • CRI ADX Описание из multimedia.cx Wiki
  • Техническое описание ADX на vgmstream Wiki