Расшифровка аудио формата ima4 - PullRequest
9 голосов
/ 25 января 2010

Чтобы уменьшить размер загружаемого приложения для iPhone, я сжимаю некоторые аудиофайлы. В частности, я использую afconvert в командной строке для изменения формата .wav на формат .caf со сжатием ima4.

Я прочитал этот (wooji-juice.com) потрясающий пост на эту тему. У меня проблемы с шагом "декодирование пакетов ima4". Я посмотрел их пример кода и застрял. Пожалуйста, помогите с каким-нибудь псевдокодом или примером кода, который поможет мне в правильном направлении.

Спасибо!

Дополнительная информация : Вот что я закончил и где у меня проблемы ... Я могу воспроизводить файлы .wav как на симуляторе, так и на телефоне. Я могу сжать файлы .wav в .caf w / ima4, используя afconvert в командной строке. Я использую SoundEngine, который пришел с CrashLanding (я исправил одну утечку памяти). Я изменил код SoundEngine для поиска mFormatID 'ima4'.

Я не понимаю сообщение в блоге, связанное выше, начиная с "Расчет размера неупакованных данных". Зачем мне это делать? Кроме того, что означает термин «пакет»? Я очень новичок в любом виде звукового программирования.

Ответы [ 2 ]

11 голосов
/ 03 февраля 2010

После сбора всех данных из Wooji-Juice , Multimedia Wiki и Apple , вот мое предложение (может потребоваться некоторый эксперимент):

Файловая структура

  • Файл Apple IMA4 сделан из пакета по 34 байта. Это пакетная единица, используемая для создания файла.
  • Каждый 34-байтовый пакет состоит из двух частей:
    • первые 2 байта содержат преамбулу: начальный предиктор и индекс шага
    • оставшиеся 32 байта содержат звуковые фрагменты (для получения 16-битной выборки используется фрагмент размером 4 бита)
  • Каждый пакет имеет 32 байта сжатых данных, которые представляют 64 выборки по 16 битов.
  • Если звуковой файл стереофонический, пакеты чередуются (один для левого, другой для правого); должно быть четное количество пакетов.

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

Каждый пакет из 34 байтов приведет к распаковке 64 выборок по 16 бит. Таким образом, размер несжатых данных составляет 128 байт на пакет.

Псевдокод декодирования выглядит так:

int[] ima_index_table = ... // Index table from [Multimedia Wiki][2]
int[] step_table = ... // Step table from [Multimedia Wiki][2]
byte[] packet = ... // A packet of 34 bytes compressed
short[] output = ... // The output buffer of 128 bytes
int preamble = (packet[0] << 8) | packet[1];
int predictor = preamble && 0xFF80; // See [Multimedia Wiki][2]
int step_index = preamble && 0x007F; // See [Multimedia Wiki][2]
int i;
int j = 0;
for(i = 2; i < 34; i++) {
    byte data = packet[i];
    int lower_nibble = data && 0x0F;
    int upper_nibble = (data && 0xF0) >> 4;

    // Decode the lower nibble
    step_index += ima_index_table[lower_nibble];
    diff = ((signed)nibble + 0.5f) * step / 4;
    predictor += diff;
    step = ima_step_table[step index];

    // Clamp the predictor value to stay in range
    if (predictor > 65535)
        output[j++] = 65535;
    else if (predictor < -65536)
        output[j++] = -65536;
    else
        output[j++] = (short) predictor;

    // Decode the uppper nibble
    step_index += ima_index_table[upper_nibble];
    diff = ((signed)nibble + 0.5f) * step / 4;
    predictor += diff;
    step = ima_step_table[step index];

    // Clamp the predictor value to stay in range
    if (predictor > 65535)
        output[j++] = 65535;
    else if (predictor < -65536)
        output[j++] = -65536;
    else
        output[j++] = (short) predictor;
}
1 голос
/ 02 февраля 2010

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

Вот почему вам необходимо рассчитать размер распакованных данных (а затем освободить место для них) - поскольку они сжаты, вам необходимо преобразовать данные из сжатого звука в несжатый звук, прежде чем вы сможете его выводить. Чтобы выделить выходной буфер, вам нужно знать, насколько большим он должен быть (примечание: вам может потребоваться выводить порциями, которые больше, чем один пакет за раз).

Похоже, что типичная структура, согласно более раннему разделу «Обзор», состоит в том, что наборы из 64 выборок, каждый из 16 бит (т.е. 128 байтов) транслируются в 2-байтовый заголовок и 32-байтовый набор сжатых выборок. (Всего 34 байта). Таким образом, в типичном случае вы можете получить ожидаемый размер выходных данных, взяв размер входных данных, разделив его на 34, чтобы получить количество пакетов, затем умножив его на 128 байтов для несжатого звука на пакет.

Тебе не следует этого делать. Похоже, вы должны вместо этого запросить kAudioFilePropertyDataFormat, чтобы получить mBytesPerPacket - это значение «34» выше, а mFramesPerPacket - это 64 выше, которое умножается на 2 (для 16-байтовых выборок), чтобы получить 128 байтов выхода.

Затем для каждого пакета вам необходимо выполнить декодирование, описанное в посте. В несколько более длинном псевдо-C-коде, если вы получаете массивы байтов, для обработки заголовка:

packet = GetPacket();
Header = (packet[0] << 8) | packet[1]; //Big-endian 16-bit value
step_index = Header & 0x007f; //Lower seven bits
predictor = Header & 0xff80; //Upper nine bits
for (i = 2; i < mBytesPerPacket; i++)
{
    nibble = packet[i] & 0x0f; //Low Nibble
    process that nibble, per the blogpost -- be careful on sign-extension!
    nibble = (packet[i] & 0xf0) >> 4; //High Nibble
    process that nibble, per the blogpost -- be careful on sign-extension!
}

Расширение знака, приведенное выше, относится к тому факту, что сообщение включает в себя обработку каждого клева как без знака, так и со знаком. Если старший бит полубайта (бит 3) равен 1, то он отрицательный; Кроме того, битовое смещение может выполнять расширение знака. Это не обрабатывается в приведенном выше псевдокоде.

...