1

我的问题与这个问题有关,但它是相反的。

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

在上面的链接中,操作想要将 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 位应该在右边。整个事情不应该是两者的总和……我想。

4

2 回答 2

4

你需要改变::

UInt32 t = (UInt32) l + r;

到:

UInt32 t = (l << 16) | (r & 0xffff);

这放入l了最高有效 16 位tr最低有效 16 位。

详细解释

如果您有两个 16 位样本lr,在二进制中看起来像这样:

l: LLLLLLLLLLLLLLLL
r: RRRRRRRRRRRRRRRR

让我们首先将它们扩展到 32 位:

l: 0000000000000000LLLLLLLLLLLLLLLL
r: 0000000000000000RRRRRRRRRRRRRRRR

现在让我们l左移 16 位 ( l << 16)

l: LLLLLLLLLLLLLLLL0000000000000000
r: 0000000000000000RRRRRRRRRRRRRRRR

现在让我们对它们进行 OR ( |) 运算:

t: LLLLLLLLLLLLLLLLRRRRRRRRRRRRRRRR

瞧!现在您已经将它们组合成一个 32 位值lr以后可以轻松地再次从中提取它们。

于 2010-11-26T08:55:58.753 回答
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;

但是,这种方法需要您对底层平台有更多了解,因为它依赖于数据在内存中的实际存储方式。但是,根据目标平台和编译器,它可能会更有效。

于 2010-11-26T11:06:39.980 回答