且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

解码ima4音频格式

更新时间:2022-06-18 23:37:43

Wooji-Juice 多媒体Wiki Apple ,这是我的建议(可能需要一些实验):

After gathering all the data from Wooji-Juice, Multimedia Wiki and Apple, here is my proposal (may need some experiment):

文件结构


  • Apple IMA4文件由34个字节的数据包组成。这是用于构建文件的数据包单元。

  • 每个34字节的数据包有两部分:


    • 第一部分2个字节包含前导码:初始预测器和步骤索引

    • 剩下的32个字节包含声音半字节(4位的半字节用于检索16位样本)

    解码

    每个34字节的数据包将导致64位16位样本的解压缩。因此,未压缩数据的大小为每个数据包128个字节。

    Each packet of 34 bytes will lead to the decompression of 64 samples of 16 bits. So the size of the uncompressed data is 128 bytes per packet.

    解码伪代码如下所示:

    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;
    }