使用 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 系统,您还可以使用 fread
或 fwrite
一次读取整个数字。其实录音程序大概就是这样写文件的,这也是他们使用这种格式的原因。
// 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)的主要内容,如果未能解决你的问题,请参考以下文章
NAudio 拆分 wav 文件问题。其他所有音频文件声音失真,而其他音频文件清晰