解码ima4音频格式

MrD*_*ase 9 iphone file-format ima4

为了减少iPhone应用程序的下载大小,我正在压缩一些音频文件.具体来说,我在命令行上使用afconvert将.wav格式更改为.caf格式w/ima4压缩.

我已经阅读了这个(wooji-juice.com)关于这个确切主题的精彩帖子.我遇到了"解码ima4数据包"的麻烦.我看了他们的示例代码,我被卡住了.请帮助w /一些伪代码或示例代码,可以指导我正确的方向.

谢谢!

附加信息:这是我已经完成的以及我遇到麻烦的地方......我可以在模拟器和手机上播放.wav文件.我可以使用命令行上的afconvert将.wav文件压缩为.caf w/ima4压缩.我正在使用带CrashLanding的SoundEngine(我修复了一个内存泄漏).我修改了SoundEngine代码以查找mFormatID'ima4'.

我不明白上面链接的博客帖子开头w /"计算解压缩数据的大小".为什么我需要这样做?此外,"数据包"一词是指什么?我对任何类型的音频编程都很陌生.

Lau*_*ble 11

收集了Wooji-Juice,Multimedia WikiApple的所有数据后,这是我的建议(可能需要一些实验):

文件结构

  • Apple IMA4文件由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;
}
Run Code Online (Sandbox Code Playgroud)