将 2 个 sint16s 样本表示为单个 uint32 样本

发布于 2024-10-04 16:50:06 字数 856 浏览 6 评论 0原文

我的问题与这个问题相关,但方向相反。

将 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 位应该在右边。整个事情不应该是两者的总和……我想。

My question is related to this question but it is in reverse.

Split UInt32 (audio frame) into two SInt16s (left and right)?

In the link above the op wanted to split a 32 bit frame into 2 16 bit samples (left and right).

I have 2 16 bit samples and I would like to express them as a single 32 bit interleaved frame.

What I have attempted so far looks like this.

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;

Is this legitimate and correct? I'm not sure due to my inexperience. My audio output is sounding a little peculiar and I'm trying to by process of elimination determine whats going wrong.

It would be helpful if somebody could either confirm that what I'm doing is the correct way to express 2 16 bit samples as a 32 bit frame or suggest a correct way.

I have a feeling that what I have done is wrong. I think this because the first 16 bits of the 32bit frame should be the left and the second 16 bits should be the right. The whole thing shouldnt be the sum of the two...... I think.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

意犹 2024-10-11 16:50:06

您需要将:: 更改

UInt32 t = (UInt32) l + r;

为:

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

这会将 l 放入 t 的最高有效 16 位,将 r 放入最低有效 16 位。

详细说明

如果您有两个 16 位样本,lr,它们的二进制形式如下所示:

l: LLLLLLLLLLLLLLLL
r: RRRRRRRRRRRRRRRR

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

l: 0000000000000000LLLLLLLLLLLLLLLL
r: 0000000000000000RRRRRRRRRRRRRRRR

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

l: LLLLLLLLLLLLLLLL0000000000000000
r: 0000000000000000RRRRRRRRRRRRRRRR

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

t: LLLLLLLLLLLLLLLLRRRRRRRRRRRRRRRR

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

You need to change::

UInt32 t = (UInt32) l + r;

to:

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

This puts l in the most significant 16 bits of t and r in the least significant 16 bits.

Detailed explanation

If you have two 16 bit samples, l and r, which look like this in binary:

l: LLLLLLLLLLLLLLLL
r: RRRRRRRRRRRRRRRR

let's first extend them to to 32 bits:

l: 0000000000000000LLLLLLLLLLLLLLLL
r: 0000000000000000RRRRRRRRRRRRRRRR

Now let's shift l left by 16 bits (l << 16)

l: LLLLLLLLLLLLLLLL0000000000000000
r: 0000000000000000RRRRRRRRRRRRRRRR

Now let's OR (|) them together:

t: LLLLLLLLLLLLLLLLRRRRRRRRRRRRRRRR

Voilà ! Now you have l and r combined into a 32 bit value from which they can easily be extracted again later.

我是有多爱你 2024-10-11 16:50:06

我会将其作为对 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;

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

I'll take this up as a complement to Paul R's answer, but it was a bit too long to put in a comment.

An alternative solution that may be more "obvious" is explicitly setting the top or bottom 16-bit values in the 32-bit value. You can do this with a union, i.e.

typedef union {
    struct {
        SInt16 high;
        SInt16 low;
    } parts;
    UInt32 word;
} IntConverter;

Usage:

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;

However, this approach requires you to know a bit more about the underlying platform, since it relies on how data is actually stored in memory. Depending on the target platform and compiler, though, it could be more efficient.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文