术语“数据包”是指一组带有标头的压缩音频样本。您需要标头来解码紧随其后的数据。如果您认为您的 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,则为负;此外,位移可能会进行符号扩展。这在上面的伪代码中没有处理。