将 UInt32(音频帧)拆分为两个 SInt16(左右)?

Posted

技术标签:

【中文标题】将 UInt32(音频帧)拆分为两个 SInt16(左右)?【英文标题】:Split UInt32 (audio frame) into two SInt16s (left and right)? 【发布时间】:2010-03-08 22:28:46 【问题描述】:

对任何比 Java 更低级别的东西都一无所知,深入研究 iPhone 音频,并从所有强制转换/指针/原始内存访问中实现。

我正在使用some example code,它从光盘读取 WAV 文件并将立体声样本作为单个 UInt32 值返回。如果我理解正确,这只是返回创建两个 16 位样本所需的 32 位内存的便捷方式。最终,这些数据被写入缓冲区,然后一个音频单元将其拾取。即使数据是以 UInt32 大小的块写入的,它最终也会被解释为 16 位样本对。

我需要帮助的是将这些 UInt32 帧拆分为左右样本。我假设我想将每个 UInt32 转换为 SInt16,因为音频样本是有符号值。在我看来,为了效率,我应该能够简单地指向内存中的相同块,并避免任何复制。

所以,在伪代码中,它会是这样的:

UInt32 myStereoFrame = getFramefromFilePlayer;

SInt16* leftChannel = getFirst16Bits(myStereoFrame);
SInt16* rightChannel = getSecond16Bits(myStereoFrame);

谁能帮我把我的伪代码变成真正的代码?

编辑:

非常感谢 zneak 的回答,效果很好:

SInt16* left = (SInt16*)&myUInt32Chunk;
SInt16* right = left + 1;

现在,要将我的 SInt16 重新组装成 UInt32(假设我不想只使用我的原始变量 myStereoFrame),我需要或多或少地反向执行相同的操作:将我的两个 SInt16 连续排列内存插槽,然后将该内存转换为 UInt32。

所以我做了一个数组:

SInt16 newFrameInMemory[2] = *left, *right

然后将该数组的整个长度复制到 UInt32 中

UInt32 newFrame32 = newFrameInMemory

虽然这行不通,但如果我做这点丑陋的事情——将数组转换为指针,然后取消引用指针,它确实有效。

UInt32 newFrame32 = *((UInt32*)&newFrameInMemory)

有没有更漂亮的方法来做到这一点?

【问题讨论】:

【参考方案1】:

很简单:

SInt16* left = (SInt16*)&myUInt32Chunk;
SInt16* right = left + 1;

除非 iPhone 是 little-endian,在这种情况下,您必须反转 rightleft

由于int 可以被视为两个连续的shorts,因此您只需获取它的地址,然后就好像它确实是两个shorts 一样。

【讨论】:

【参考方案2】:

iPhone 是小端 :-)

【讨论】:

以上是关于将 UInt32(音频帧)拆分为两个 SInt16(左右)?的主要内容,如果未能解决你的问题,请参考以下文章

uint和int的区别

如何在 iOS 中读取音频文件并获取样本?

SInt32 AudioUnitSampleType 实际上保存了整个音频数据吗?

将一个 32 位浮点数转换为两个 16 位 uint 数,然后再次转换回该 32 位浮点数

如何在 Neon 中将 uint32x4_t 转换为 uint8x16_t?

有啥方法可以将大约 16GB 的 SAS 文件拆分为 Python 中的多个文件/数据帧?