Iphone 解码ima4音频格式

Iphone 解码ima4音频格式,iphone,file-format,ima4,Iphone,File Format,Ima4,为了减少iPhone应用程序的下载量,我压缩了一些音频文件。具体来说,我在命令行上使用afconvert将.wav格式更改为.caf格式,并使用ima4压缩 我读过(woojijuice.com)关于这个主题的精彩文章。我在“解码ima4数据包”步骤中遇到问题。我已经看过了他们的示例代码,我被卡住了。请提供一些伪代码或示例代码,以指导我正确的方向 谢谢 其他信息: 这是我完成的和我遇到的问题。。。 我可以在模拟器和手机上播放.wav文件。 我可以在命令行上使用afconvert将.wav文件压缩

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

我读过(woojijuice.com)关于这个主题的精彩文章。我在“解码ima4数据包”步骤中遇到问题。我已经看过了他们的示例代码,我被卡住了。请提供一些伪代码或示例代码,以指导我正确的方向

谢谢

其他信息: 这是我完成的和我遇到的问题。。。 我可以在模拟器和手机上播放.wav文件。 我可以在命令行上使用afconvert将.wav文件压缩为.caf w/ima4压缩。我正在使用带有崩溃的声音引擎(我修复了一个内存泄漏)。 我修改了SoundEngine代码以查找mFormatID“ima4”

我不明白上面链接的博客文章是从“计算未打包数据的大小”开始的。我为什么要这样做?此外,术语“包”指的是什么?我对任何类型的音频编程都很陌生。

术语“数据包”指的是一组带有标题的压缩音频样本。您需要标题来解码紧接着的数据。如果你认为你的IMA4文件是一本书,那么每个数据包都是一个页面。顶部是解码该页面所需的值,后面是压缩音频

这就是为什么需要计算解压数据的大小(然后为其留出空间)——因为它是压缩的,所以需要将数据从压缩音频转换为未压缩音频,然后才能输出。为了分配输出缓冲区,您需要知道它必须有多大(注意:您可能需要一次以大于单个数据包的块输出)

根据前面的“概述”部分,其典型结构是64个样本集,每个16位(128字节)被转换为2字节的头和32字节的压缩样本集(总共34字节)。因此,在典型情况下,您可以通过获取输入数据大小,除以34得到数据包的数量,然后乘以128字节得到每个数据包的未压缩音频,从而生成预期的输出数据大小

不过,你不应该那样做。看起来您应该改为查询kAudioFilePropertyDataFormat以获取mBytesPerPacket——这是上面的“34”值,而mFramesPerPacket——这是上面的64,它被乘以2(对于16字节的样本)以生成128字节的输出

然后,对于每个数据包,您将需要运行post中描述的解码。在稍长的伪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!
}
packet=GetPacket();
Header=(数据包[0]>4;//高位半字节
按照博客帖子的说法,处理这一点——在符号扩展上要小心!
}

上面的符号扩展是指post涉及以无符号和有符号方式处理每个半字节如果是1,则为负;此外,位移位可能会进行符号扩展。这在上述伪码中没有处理。

从中收集所有数据后,这是我的建议(可能需要一些实验):

文件结构

  • Apple IMA4文件由34字节的数据包组成。这是用于构建文件的数据包单元
  • 每个34字节数据包有两个部分:
    • 前2个字节包含前导:一个初始预测器和一个阶跃索引
    • 剩下的32字节包含声音半字节(4位半字节用于检索16位样本)
  • 每个数据包有32字节的压缩数据,代表16位的64个样本
  • 如果声音文件是立体声文件,则数据包是交错的(一个用于左侧,一个用于右侧);必须有偶数个数据包
解码

每个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;
}
int[]ima\u index\u table=…//来自[Multimedia Wiki][2]的索引表
int[]步骤表=…//来自[Multimedia Wiki][2]的步骤表
byte[]packet=…//一个压缩了34字节的数据包
short[]output=…//128字节的输出缓冲区
int前导=(数据包[0]>4;
//解码下半字节
步骤索引+=ima索引表[下半字节];
差=((有符号)半字节+0.5f)*步/4;
预测器+=diff;
步骤=ima_步骤表[步骤索引];
//钳制预测值以保持在范围内
如果(预测值>65535)
输出[j++]=65535;
否则如果(预测值<-65536)
输出[j++]=-65536;
其他的
输出[j++]=(短)预测器;
//解码UPPER半字节
步骤索引+=ima索引表[上半字节];
差=((有符号)半字节+0.5f)*步/4;
预测器+=diff;
步骤=ima_步骤表[步骤索引];
//钳制预测值以保持在范围内
如果(预测值>65535)
输出[j++]=65535;
否则如果(预测值<-65536)
输出[j++]=-65536;
其他的
输出[j++]=(短)预测器;
}

也告诉人们你遇到了什么困难。你完成了哪些步骤,在哪里遇到了问题?你必须使用OpenAL吗?如果你使用OpenAL,你只需要自己解码,否则你可以让CoreAudio来处理。