首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >解码ima4音频格式

解码ima4音频格式
EN

Stack Overflow用户
提问于 2010-01-25 07:34:45
回答 2查看 4.6K关注 0票数 10

为了减少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/“计算未打包数据的大小”开始的。我为什么要这么做?另外,“包”一词指的是什么?我对任何类型的音频编程都很陌生。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2010-02-03 17:09:12

在收集了乌济果汁多媒体Wiki苹果的所有数据之后,下面是我的建议(可能需要一些实验):

文件结构

  • 苹果IMA4文件由34个字节的数据包组成。这是用于构建文件的数据包单元。
  • 每个34个字节包有两个部分:
    • 前两个字节包含序言:一个初始预测器和一个步骤索引。
    • 剩下的32个字节包含声音小块(一个4位的小块用来检索一个16位的样本)

  • 每个数据包有32个字节的压缩数据,它们代表64个16位的样本。
  • 如果声音文件是立体声的,则数据包被交错(左一个,右边一个);必须有偶数的数据包。

译码

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

解码伪码如下所示:

代码语言:javascript
复制
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;
}
票数 12
EN

Stack Overflow用户

发布于 2010-02-02 17:35:57

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

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

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

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

然后,对于每个数据包,您将需要运行在文章中描述的解码过程中。在稍微长一些的伪C代码中,假设您得到的是字节数组,以处理标题:

代码语言:javascript
复制
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,那么它是负的;此外,位移位可能做符号扩展。这在上面的伪代码中不被处理。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2130831

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档