Jump to content

ADX (формат файла)

ЦРИ ADX
Разработчик(и) Промежуточное ПО CRI
Первоначальный выпуск 1996
Платформа Кросс-платформенный
Тип Кодек / формат файла
Лицензия Собственный
Веб-сайт Промежуточное ПО CRI

CRI ADX — это собственный аудиоконтейнер и формат сжатия, разработанный CRI Middleware специально для использования в видеоиграх ; он получен из ADPCM, но со сжатием с потерями . Его наиболее примечательной особенностью является функция зацикливания, которая оказалась полезной для фоновых звуков в различных играх, использующих этот формат, включая многие игры для Sega Dreamcast , а также некоторые для PlayStation 2 , GameCube и Wii игры . Одной из первых игр, использовавших ADX, была Burning Rangers для Sega Saturn . Примечательно, что Sonic the Hedgehog серия , начиная с поколения Dreamcast, и большинство игр Sega для домашних видеоконсолей и ПК, начиная с Dreamcast, продолжают использовать этот формат для записи звука и голоса. Jet Set Radio Future для оригинальной Xbox также использовал этот формат. [1]

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

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

Общий обзор

[ редактировать ]

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

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

Для воспроизведения, помимо собственного программного обеспечения CRI Middleware, существует несколько плагинов для WinAmp, а также инструменты преобразования WAV. В FFmpeg также реализована поддержка CRI ADX, но его декодер жестко запрограммирован, поэтому может правильно декодировать только ADX с частотой 44100 Гц.

Техническое описание

[ редактировать ]

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

Формат диска ADX определяется в формате big-endian . Идентифицированные разделы основного заголовка приведены ниже:

0 1 2 3 4 5 6 7 8 9 А Б С Д И Ф
0x0 0x80 0x00 Смещение авторских прав Тип кодировки Размер блока Образец битовой глубины Количество каналов Частота дискретизации Всего образцов
0x10 Частота верхних частот Версия Флаги Примеры выравнивания контура (v3) Цикл включен (v3) Цикл включен (v3) Индекс начала цикла (v3)
0x20 Индекс байта начала цикла (v3) Цикл включен (v4)

Индекс конца цикла (v3)

Индекс начала цикла (v4)

Индекс байта конца цикла (v3)

Индекс байта начала цикла (v4)
0x30 Индекс конца цикла (v4) Индекс байта конца цикла (v4) Ноль или более байт пустого пространства
??? [CopyrightOffset - 2] Строка ASCII (незавершенная): «(c)CRI»
... [CopyrightOffset + 4] Здесь начинаются аудиоданные

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

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

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

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

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

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

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

Коэффициент 0 Коэффициент 1
Установить 0 0x0000 0x0000
Набор 1 0x0F00 0x0000
Набор 2 0x1CC0 0xF300
Набор 3 0x1880 0xF240

Образец формата

[ редактировать ]

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

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
Предиктор/Шкала 32 4-битных семпла

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

7 6 5 4 3 2 1 0
Первый образец Второй образец

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

Декодирование CRI ADX

[ редактировать ]

Кодировщик для ADX также можно создать, просто перевернув код для работы в обратном направлении. Примеры кода написаны с использованием C99 .

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

 #define M_PI acos(-1.0)
 double a, b, c;
 a = sqrt(2.0) - cos(2.0 * M_PI * ((double)adx_header->highpass_frequency / adx_header->sample_rate));
 b = sqrt(2.0) - 1.0;
 c = (a - sqrt((a + b) * (a - b))) / b; //(a+b)*(a-b) = a*a-b*b, however the simpler formula loses accuracy in floating point
 
 // double coefficient[2];
 coefficient[0] = c * 2.0;
 coefficient[1] = -(c * c);

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

 static int32_t*      past_samples; // Previously decoded samples from each channel, zeroed at start (size = 2*channel_count)
 static uint_fast32_t sample_index = 0; // sample_index is the index of sample set that needs to be decoded next
 static ADX_header*   adx_header;
 
 // buffer is where the decoded samples will be put
 // samples_needed states how many sample 'sets' (one sample from every channel) need to be decoded to fill the buffer
 // looping_enabled is a boolean flag to control use of the built-in loop
 // Returns the number of sample 'sets' in the buffer that could not be filled (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 scale[ adx_header->channel_count ];
 
  if (looping_enabled && !adx_header->loop_enabled)
     looping_enabled = false;
 
  // Loop until the requested number of samples are decoded, or the end of file is reached
  while (samples_needed > 0 && sample_index < adx_header->total_samples)
  {
     // Calculate the number of samples that are left to be decoded in the current block
     unsigned sample_offset = sample_index % samples_per_block;
     unsigned samples_can_get = samples_per_block - sample_offset;

     // Clamp the samples we can get during this run if they won't fit in the buffer
     if (samples_can_get > samples_needed)
        samples_can_get = samples_needed;
 
     // Clamp the number of samples to be acquired if the stream isn't long enough or the loop trigger is nearby
     if (looping_enabled && sample_index + samples_can_get > adx_header->loop_end_index)
        samples_can_get = adx_header->loop_end_index - sample_index;
     else if (sample_index + samples_can_get > adx_header->total_samples)
        samples_can_get = adx_header->total_samples - sample_index;
 
     // Calculate the bit address of the start of the frame that sample_index resides in and record that location
     unsigned long started_at = (adx_header->copyright_offset + 4 + \
                     sample_index / samples_per_block * adx_header->block_size * adx_header->channel_count) * 8;
 
     // Read the scale values from the start of each block in this frame
     for (unsigned i = 0 ; i < adx_header->channel_count ; ++i)
     {
        bitstream_seek( started_at + adx_header->block_size * i * 8 );
        scale[i] = ntohs( bitstream_read( 16 ) );
     }
 
     // Pre-calculate the stop value for sample_offset
     unsigned sample_endoffset = sample_offset + samples_can_get;
 
     // Save the bitstream address of the first sample immediately after the scale in the first block of the frame
     started_at += 16;
     while ( sample_offset < sample_endoffset )
     {
        for (unsigned i = 0 ; i < adx_header->channel_count ; ++i)
        {
           // Predict the next sample
           double sample_prediction = coefficient[0] * past_samples[i*2 + 0] + coefficient[1] * past_samples[i*2 + 1];
 
           // Seek to the sample offset, read and sign extend it to a 32bit integer
           // Implementing sign extension is left as an exercise for the reader
           // The sign extension will also need to include a endian adjustment if there are more than 8 bits
           bitstream_seek( started_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 );
 
           // Scale the error correction value
           sample_error *= scale[i];
 
           // Calculate the sample by combining the prediction with the error correction
           int_fast32_t sample = sample_error + (int_fast32_t)sample_prediction;
 
           // Update the past samples with the newer sample
           past_samples[i*2 + 1] = past_samples[i*2 + 0];
           past_samples[i*2 + 0] = sample;
 
           // Clamp the decoded sample to the valid range for a 16bit integer
           if (sample > 32767)
              sample = 32767;
           else if (sample < -32768)
              sample = -32768;
 
           // Save the sample to the buffer then advance one place
           *buffer++ = sample;
        }
        ++sample_offset;  // We've decoded one sample from every block, advance block offset by 1
        ++sample_index;   // This also means we're one sample further into the stream
        --samples_needed; // And so there is one less set of samples that need to be decoded
    }
 
    // Check if we hit the loop end marker, if we did we need to jump to the loop start
    if (looping_enabled && sample_index == adx_header->loop_end_index)
       sample_index = adx_header->loop_start_index;
  }
 
  return samples_needed;
 }

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

Шифрование

[ редактировать ]

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

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

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

AHX-декодирование

[ редактировать ]

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

  1. ^ «imgur.com» . Имгур . Проверено 10 мая 2023 г.
[ редактировать ]
Arc.Ask3.Ru: конец переведенного документа.
Arc.Ask3.Ru
Номер скриншота №: 5c554a0e0c87fa860c702c7a91a7afb6__1708082880
URL1:https://arc.ask3.ru/arc/aa/5c/b6/5c554a0e0c87fa860c702c7a91a7afb6.html
Заголовок, (Title) документа по адресу, URL1:
ADX (file format) - Wikipedia
Данный printscreen веб страницы (снимок веб страницы, скриншот веб страницы), визуально-программная копия документа расположенного по адресу URL1 и сохраненная в файл, имеет: квалифицированную, усовершенствованную (подтверждены: метки времени, валидность сертификата), открепленную ЭЦП (приложена к данному файлу), что может быть использовано для подтверждения содержания и факта существования документа в этот момент времени. Права на данный скриншот принадлежат администрации Ask3.ru, использование в качестве доказательства только с письменного разрешения правообладателя скриншота. Администрация Ask3.ru не несет ответственности за информацию размещенную на данном скриншоте. Права на прочие зарегистрированные элементы любого права, изображенные на снимках принадлежат их владельцам. Качество перевода предоставляется как есть. Любые претензии, иски не могут быть предъявлены. Если вы не согласны с любым пунктом перечисленным выше, вы не можете использовать данный сайт и информация размещенную на нем (сайте/странице), немедленно покиньте данный сайт. В случае нарушения любого пункта перечисленного выше, штраф 55! (Пятьдесят пять факториал, Денежную единицу (имеющую самостоятельную стоимость) можете выбрать самостоятельно, выплаичвается товарами в течение 7 дней с момента нарушения.)