使用 C 绕过声音/音频文件 (WAV)

Posted

技术标签:

【中文标题】使用 C 绕过声音/音频文件 (WAV)【英文标题】:Bypassing Sound/Audio Files (WAV) using C 【发布时间】:2020-11-26 15:13:08 【问题描述】:

作为我为声音设计创建 VST 的长期项目想法的一部分,我现在开始了解声音文件以及它们如何存储在计算机中。

我面临的问题与更改声音文件的字节有关。我正在使用 C 加载一个基本的 WAV 声音文件,使用 putchar 函数,因为它可以直接访问 ascii 代码中的每个字节。我找到了一个很好的地方来研究 WAV 文件here 并进入它。在处理完头文件的内容后,我想弄脏自己的手,所以使用一些信号处理,我想制作一个小脚本,以一半的速度输出输入的 WAV 文件。

为了在不改变 WAV 文件主体(数据)的值的情况下做到这一点,我必须将采样率减半,但每秒字节数也要减半,以便(采样率 x 块对齐 = 字节数第二)真实

我为处理采样率的字节而编写的一些演示代码(在位置 25 和 28 之间,我得到了采样率的字节)

#include <stdio.h>

int main() 
    int character_of_byte, position = 0;
    while ((character_of_byte = getchar() ) != EOF) 
         position++;
         if (position >= 25 && position <= 28)  
             putchar(character_of_byte / 2);
          else 
             putchar(character_of_byte);
         
    

例如如果采样率为 44100khz,则作为十进制输入给出:68、172、0、0 字节以小端形式存储,当减半时,十进制输出必须为:22050 , 如果我们将上述所有内容减半并按顺序存储 : 34, 86, 0, 0 则成立,例如176400khz,我把所有小数都减半后,这个数字后来被解释为88072。

Putchar 在这种情况下 (176400khz) 得到: 16 , 177 , 2 , 0 (按顺序),用于输入,但是: 如果我运行相同的脚本,它将输出:8、88、1 和 0,这会产生数字 88072。

这是错误的,因为在 8 的情况下位移跳过了 1,因为 177 是奇数,所以它的最后 1 位应该被转移到 8 上(而是保存为 00001000),创建 10001000。如果我必须更改作为输入输入的字节,我该如何解决这个问题? 请记住,32 位数字的最后一个字节首先给出,小端形式

【问题讨论】:

想象一个数字除以所有数字并四舍五入,例如12345678 除以 2 是 01122334。这就是你在这里所做的。 通常,这将通过读取 4 个字节,创建一个 32 位数字,将 32 位数字除以,然后将 32 位数字再次拆分为字节并写入它们来完成。跨度> 你说得对,我就是这么做的。我试图模仿向右移位。我也会这样做,但遗憾的是我没有这样做的能力。 【参考方案1】:

通常,这将通过读取 4 个字节,创建一个 32 位数字,将 32 位数字除以,然后将 32 位数字再次拆分为字节并写入它们来完成。

// assumes no EOF
int byte_1 = (unsigned char)getchar(f);
int byte_2 = (unsigned char)getchar(f);
int byte_3 = (unsigned char)getchar(f);
int byte_4 = (unsigned char)getchar(f);
int32_t number = (byte_1 | (byte_2 << 8) | (byte_3 << 16) || (byte_4 << 24));
number /= 2;
byte_1 = number & 255;
byte_2 = (number >> 8) & 255;
byte_3 = (number >> 16) & 255;
byte_4 = (number >> 24) & 255;
putchar(byte_1);
putchar(byte_2);
putchar(byte_3);
putchar(byte_4);

(当然这可以写得更短;我这样写是为了清楚地表达这个想法)。

如果您不介意您的代码仅适用于 little-endian 系统,您还可以使用 freadfwrite 一次读取整个数字。其实录音程序大概就是这样写文件的,这也是他们使用这种格式的原因。

// still no EOF checks
int32_t sample_rate;
fread(&sample_rate, sizeof(sample_rate), 1, f);
sample_rate /= 2;
fwrite(&sample_rate, sizeof(sample_rate), 1, stdout);

【讨论】:

以上是关于使用 C 绕过声音/音频文件 (WAV)的主要内容,如果未能解决你的问题,请参考以下文章

目标c中的音频文件格式问题

NAudio 拆分 wav 文件问题。其他所有音频文件声音失真,而其他音频文件清晰

如何使用 NAudio 将两个 wav 音频文件与 30 秒的白色声音连接起来

如何将wav格式声音文件转换为文本文件

C语言播放音频文件的问题....

C++如何播放wav声音文件.Linux系统