2010-01-25 3 views
9

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

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

Спасибо!

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

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

+0

сказать также людей на то, что вы застряли. Какие шаги вы завершили, и где вы столкнулись с вашими проблемами? – Younes

+0

Вам нужно использовать OpenAL? Вам нужно сделать только декодирование, если вы используете OpenAL, иначе вы можете просто обработать CoreAudio. –

ответ

11

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

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

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

Термин «пакет» относится к группе сжатых аудиозаписей с заголовком. Вам нужен заголовок для декодирования данных, следующих за ним. Если вы считаете, что ваш файл 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, то он отрицательный; кроме того, бит-сдвиг может выполнять расширение знака. Это не обрабатывается в вышеуказанном псевдокоде.