将 32 位有符号整数转换为 24 位有符号音频数据
Posted
技术标签:
【中文标题】将 32 位有符号整数转换为 24 位有符号音频数据【英文标题】:Convert 32 bit signed int to 24 bit signed for audio data 【发布时间】:2018-03-20 23:19:19 【问题描述】:我正在尝试将我的 32 位有符号 int 音频数据转换为 24 位有符号。 目标是编写一个 Wave 文件。我已经设法编写了 8、16 和 32 位深度的正确 Wave 文件,但由于某种原因,我在 24 位时遇到了困难。声音输出听起来像 8 位(很多噪音),这似乎意味着只有 MSB 被正确解释,24 位值的第二个和第三个字节似乎不起作用。
代码:
int buffer_32[1024];
unsigned char buffer_24[1024*3];
for (unsigned i = 0; i < 1024; i++)
buffer_24[i*3] = (unsigned char)((buffer_32[i] & 0xff0000) >> 16);
buffer_24[i*3+1] = (unsigned char)((buffer_32[i] & 0xff00) >> 8);
buffer_24[i*3+2] = (unsigned char)(buffer_32[i] & 0xff);
基本上,我操纵字节来创建一个 24 位流(“24 位打包”)。
我不知道我的转换算法出了什么问题:你能帮帮我吗?
编辑:我忘了说,在进入此转换循环之前,我的 int 值已经正确缩放到 -8388608,8388607(24 位有符号整数)范围。
【问题讨论】:
你使用的是 32 的低 24 位。你需要使用高位。 您是否已完成打印以检查:printf("0x%.6X . = %.2X %.2X %.2X\n", buffer_32[i] & 0xFFFFFF, buffer_24[i*3+0], buffer_24[i*3+1], buffer_24[i*3+2]);
作为循环的最后一条语句?打印出来的值是否一致?
您确定您的输出字节顺序与您使用的任何播放器的预期字节顺序相匹配吗?我有兴趣查看此代码的 16 位版本,看看它们是否匹配。
【参考方案1】:
听起来像噪音的原因是您正在从数据中剥离 MSB。
试试这个:
buffer_24[i*3] = (unsigned char)((buffer_32[i] & 0xff000000) >> 24);
buffer_24[i*3+1] = (unsigned char)((buffer_32[i] & 0xff0000) >> 16);
buffer_24[i*3+2] = (unsigned char)((buffer_32[i] & 0xff00) >> 8);
【讨论】:
我忘了补充一点,我的 int 数组包含的值已经被缩放以适应 24 位范围,所以 MSB 为空 这是一个 hacky 解决方案,可用于测试错误是否不在这部分代码中。将 buffer_32[i] 乘以 0x100,然后使用此答案中给出的代码。【参考方案2】:我做这种事情已经 30 多年了,所以请耐心等待:
-
如果您的音频是多路复用立体声,那么我怀疑您所做的工作是否有效。
如果有符号位是左右的,那么您应该对它进行 (AND) 符号处理并处理结果,然后重新附加 (OR) 符号。
如果您只是想删除顶部字节,那么您应该使用 0x00ffffffff(四个字节)AND 输出顶部字节。
如果是纯模拟采样,我会根据我想要的质量类型降低分辨率(软件重新采样),降低音量等。
相信这会有所帮助。
【讨论】:
以上是关于将 32 位有符号整数转换为 24 位有符号音频数据的主要内容,如果未能解决你的问题,请参考以下文章
C#Winform基础 十进制整数转换为32位有符号二进制数
汇编 IA-32:如何将 64 位有符号数除以奇数(存储在 2 个寄存器中)
2021-09-12:请你来实现一个 myAtoi(string s) 函数,使其能将字符串转换成一个 32 位有符号整数(类似 C/C++ 中的 atoi 函数)。函数 myAtoi(string(