将 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,在这种情况下,您必须反转 right
和 left
。
由于int
可以被视为两个连续的short
s,因此您只需获取它的地址,然后就好像它确实是两个short
s 一样。
【讨论】:
【参考方案2】:iPhone 是小端 :-)
【讨论】:
以上是关于将 UInt32(音频帧)拆分为两个 SInt16(左右)?的主要内容,如果未能解决你的问题,请参考以下文章
SInt32 AudioUnitSampleType 实际上保存了整个音频数据吗?
将一个 32 位浮点数转换为两个 16 位 uint 数,然后再次转换回该 32 位浮点数