2010-01-25 94 views
9

爲了減少iPhone應用程序的下載大小,我正在壓縮一些音頻文件。具體來說,我在命令行上使用afconvert將.wav格式更改爲.caf格式,並使用ima4壓縮。解碼ima4音頻格式

我讀過this(wooji-juice.com)關於這個確切的話題的真棒帖子。我在解碼ima4數據包的時候遇到了麻煩。我看了他們的示例代碼,我被卡住了。請幫助一些僞代碼或示例代碼,可以指導我朝着正確的方向發展。

謝謝!

附加信息: 這裏是我已經完成了什麼,在哪裏我有麻煩...... 我可以在這兩個模擬器和手機上播放.wav文件。 我可以使用命令行上的afconvert將.wav文件壓縮爲.caf w/ima4壓縮。我使用的是帶有CrashLanding的SoundEngine(我修復了一個內存泄漏)。 我修改了SoundEngine代碼以查找mFormatID'ima4'。

我不明白上面鏈接的博客文章開始w /「計算解壓縮數據的大小」。爲什麼我需要這樣做?此外,術語「數據包」是指什麼?我對任何類型的音頻編程都很陌生。

+0

還告訴人們在你被卡住的東西。你最後確定了哪些步驟?你遇到過哪些問題? – Younes 2010-01-25 08:08:55

+0

你必須使用OpenAL嗎?如果你使用的是OpenAL,你只需要自己解碼,否則你可以讓CoreAudio處理它。 – 2010-02-05 13:03:05

回答

11

Wooji-JuiceMultimedia WikiApple收集所有數據後,這裏是我的建議(可能需要一些實驗):

文件結構

  • 蘋果IMA4文件中提出的34包字節。這是用於構建文件的數據包單元。
  • 每34個字節的數據包有兩個部分:
    • 第一2個字節包含前同步碼:初始預測器和一個階躍折射率
    • 離開32個字節包含聲音半字節(4位的半字節用於檢索16位樣本)
  • 每個數據包都有32個字節的壓縮數據,它們代表64個16位樣本。
  • 如果聲音文件是立體聲,則數據包交錯(一個用於左側,一個用於右側);必須有偶數個數據包。

解碼

的34個字節的每個分組將導致16位64個樣本的減壓。所以未壓縮數據的大小是每個數據包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,那麼它是負的;此外,移位可能會進行符號擴展。這不是在上面的僞代碼中處理的。