我的问题与这个问题有关,但反过来了。
Split UInt32 (audio frame) into two SInt16s (left and right)?
在上面的链接中,op希望将32位帧分成2个16位样本(左和右)。
我有2个16位样本,我想将它们表示为单个32位交错帧。
到目前为止,我的尝试看起来像这样。
UInt32* ar = malloc(totalFramesInFile * sizeof (ar));
for (int b=0; b < totalFramesInFile; b++)
{
UInt32 l = soundStructArray[audioFile].audioDataLeft[b];
UInt32 r = soundStructArray[audioFile].audioDataRight[b];
UInt32 t = (UInt32) l + r;
ar[b] = t;
}
soundStructArray[audioFile].audioData = ar;
这是合法和正确的吗?由于我的经验不足,我不确定。我的音频输出听起来有点奇怪,我正在尝试通过消除过程来确定哪些是错误的。
如果有人能够确认我正在做的是将2个16位采样表示为32位帧或建议正确的方法,那将会很有帮助。
我有一种感觉,我所做的是错的。我认为这是因为32位帧的前16位应该是左边,后面的16位应该是右边的。整个事情不应该是两者的总和......我想。
答案 0 :(得分:4)
您需要更改::
UInt32 t = (UInt32) l + r;
为:
UInt32 t = (l << 16) | (r & 0xffff);
这会将l
置于t
的最重要的16位和最低16位的r
中。
详细说明
如果您有两个16位样本,l
和r
,它们在二进制文件中如下所示:
l: LLLLLLLLLLLLLLLL
r: RRRRRRRRRRRRRRRR
让我们首先将它们扩展到32位:
l: 0000000000000000LLLLLLLLLLLLLLLL
r: 0000000000000000RRRRRRRRRRRRRRRR
现在让我们将l
向左移动16位(l << 16
)
l: LLLLLLLLLLLLLLLL0000000000000000
r: 0000000000000000RRRRRRRRRRRRRRRR
现在让我们将OR(|
)放在一起:
t: LLLLLLLLLLLLLLLLRRRRRRRRRRRRRRRR
Voilà!现在您将l
和r
组合成一个32位值,以后可以轻松地再次提取它们。
答案 1 :(得分:2)
我会接受这一点作为Paul R答案的补充,但是发表评论的时间太长了。
可能更“明显”的替代解决方案是在32位值中明确设置顶部或底部16位值。您可以使用联合执行此操作,即
typedef union {
struct {
SInt16 high;
SInt16 low;
} parts;
UInt32 word;
} IntConverter;
用法:
IntConverter * ar = malloc(totalFramesInFile * sizeof (IntConverter));
for (int b=0; b < totalFramesInFile; b++)
{
ar[b].parts.high = soundStructArray[audioFile].audioDataLeft[b];
ar[b].parts.low = soundStructArray[audioFile].audioDataRight[b];
}
soundStructArray[audioFile].audioData = (UInt32 *) ar;
但是,这种方法要求您更多地了解底层平台,因为它依赖于数据实际存储在内存中的方式。但是,根据目标平台和编译器,它可能更有效。