为了减少iPhone应用程序的下载大小,我正在压缩一些音频文件。具体来说,我在命令行上使用afconvert将.wav格式更改为.caf格式w/ ima4压缩。
我读过这 (wooji-juice.com)关于这个确切主题的精彩文章。我在“解码ima4数据包”的步骤中遇到了问题。我看过他们的代码我被困住了。请帮助w/一些伪代码或示例代码,可以指导我朝着正确的方向。
谢谢!
附加信息:这是我完成的,我遇到麻烦的地方.我可以在模拟器和电话中播放.wav文件。我可以在命令行上使用af红外将.wav文件压缩为.caf w/ ima4压缩。我使用的是w/ CrashLanding (我修复了一个内存泄漏)的CrashLanding。我修改了SoundEngine代码以查找mFormatID‘ima4 4’。
我不明白上面的博客文章是从w/“计算未打包数据的大小”开始的。我为什么要这么做?另外,“包”一词指的是什么?我对任何类型的音频编程都很陌生。
发布于 2010-02-03 17:09:12
在收集了乌济果汁、多媒体Wiki和苹果的所有数据之后,下面是我的建议(可能需要一些实验):
文件结构
译码
每包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;
}发布于 2010-02-02 17:35:57
“数据包”一词是指一组带有标头的压缩音频样本。您需要头来解码紧接在后面的数据。如果您认为您的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,那么它是负的;此外,位移位可能做符号扩展。这在上面的伪代码中不被处理。
https://stackoverflow.com/questions/2130831
复制相似问题