在 pcm 音频中交换字节序

Posted

技术标签:

【中文标题】在 pcm 音频中交换字节序【英文标题】:Swap endian in pcm audio 【发布时间】:2011-08-23 14:53:30 【问题描述】:

我已经编写了简单的程序来交换 PCM 音频中的字节序(2 个通道,48kHz,24 位),但只有一个通道正确交换,第二个仍然是小字节序(我在 CoolEdit 2000 中检查了生成的输出) .谁能给我一些指导,我的代码有什么问题?

inline int endian_swap(unsigned int x)

unsigned char c1, c2, c3, c4;

    c1 = x & 255;
    c2 = (x >> 8) & 255;
    c3 = (x >> 16) & 255;
    c4 = (x >> 24) & 255;

    return ((int)c1 << 24) + ((int)c2 << 16) + ((int)c3 << 8) + c4;


int main()


FILE *fpIn, *fpOut;
short x;

fpIn = fopen("audio.pcm", "rb");
fpOut = fopen("out.pcm", "wb");
int test = sizeof(short);

int count = 0;
int swaped = 0;

while( fread(&x, sizeof(int), 1, fpIn) == 1 )
    
    swaped = endian_swap(x);

    fwrite(&swaped, sizeof(int), 1, fpOut);
    

system("pause");
return 0;

最好的问候!

【问题讨论】:

endian_swap()是如何实现的? 对不起,我之前没有添加endian_swap() 结合了这两个错误(由 Oli Charlesworth 和 mtrw 提到),我很惊讶这两个频道看起来都不错。 【参考方案1】:

您一次读取一个int 文件。但是int 可能是 16 位或 32 位。你说你有 24 位音频。

您应该修改代码以一次将三个char 读取到char [3] 数组中。然后,您将修改您的 swap_endian 函数以对 char [3] 进行操作(这很简单;只需交换数组的第一个和最后一个元素的内容!)

【讨论】:

不要忘记,如果您将这些值传递给交换 32 位整数的函数,则交换 24 位值的字节序将不起作用。【参考方案2】:

您声明了short x。尝试声明unsigned int x

【讨论】:

这确实是个问题。但它不会解决主要问题(见我的回答)。 @Oli - 我假设该文件实际上包含ints,而不是char[3]s,因为我从未见过它这样做。大多数接口最终会给出完整的 32 位结果,其中 24 个数据位移到一端或另一端。我想这就是为什么在 OP 的第一个实验中一个频道看起来不错的原因。如果文件真的保存了char[3]s,那么两个通道看起来都会被破坏。 @mrtw:我并不是说该文件会真正包含char [3]s,它会包含int24s,但它们在C 中不作为本机类型存在!跨度> @Oli - 我从未见过包含int24s 的文件,尽管一切都是第一次。我同意如果存在这样的文件,char[3] 将是处理它的正确方法。如果 ADC 提供打包的 int24s,我会感到非常惊讶,因为 MCU 或任何处理数据的东西无论如何都需要解包。更容易让 SPORT/SPI/whatever 及其相关的 DMA 引擎将数据放入字对齐内存中。 @mrtw:我也没有,但我从未使用过 24 位 PCM。您似乎是在暗示您希望该文件具有 25% 的填充。

以上是关于在 pcm 音频中交换字节序的主要内容,如果未能解决你的问题,请参考以下文章

实现两个字节序的交换

PCM音频实时播放:音频字节数组(16/8位)转为PCM ArrayBuffer流

wchar_t 数据是不是需要字节序转换?

使用 gstreamer 将 PCM 数据发送到 VLC 播放器

网络字节序

网络字节序