You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

用C语言对.wav文件做低通滤波并保存输出的问题求助

问题解答

现有代码先修正几个明显错误

  • 你已经通过fread(&wav, 1, sizeof(wav), fp);读取了全部44字节的WAV头,此时文件指针已经偏移到音频数据起始位置,不需要再从缓冲区复制前44字节头,直接把已读取的wav结构体写入输出文件即可。
  • 你定义的buffIn是int类型数组,单个元素占4字节,循环条件用sizeof(buffIn)会遍历4*1024=4096次,直接超出数组边界,会触发内存访问错误。
  • 你使用的单字节滤波逻辑不符合WAV采样存储规则:WAV的音频采样是按位宽打包的,比如常见的16位PCM是2字节存一个采样值,按单字节叠加会直接破坏采样结构,导致输出音频无法正常播放。
  • 代码里printf("0x%02x",buffOut[x]);的变量x未定义,属于语法错误。

正确写入输出文件的实现步骤

第一步:先写入WAV头

直接把你已经读取解析好的WAV头写入输出文件,不需要额外复制缓冲区内容:

// 写入WAV头到输出文件
fwrite(&wav, sizeof(Wav), 1, outfile);

第二步:按采样位宽处理音频数据并写入

这里以最常见的16位PCM格式为例,修正缓冲区和滤波逻辑,处理后直接写入输出文件:

// 按16位采样定义缓冲区,每次处理1024个采样
int16_t buffIn[1024];
int16_t buffOut[1024];
size_t readCnt;
// 循环读取直到文件读完
while((readCnt = fread(buffIn, sizeof(int16_t), 1024, fp)) > 0) {
    // 一阶低通滤波 y[n] = α*x[n] + (1-α)*y[n-1] 比相邻叠加效果更好,也不会溢出
    // 这里α取0.5,等效于相邻采样平滑,和你预期的最简低通效果一致
    static int16_t prevOut = 0;
    for(int i=0; i<readCnt; i++) {
        buffOut[i] = 0.5 * buffIn[i] + 0.5 * prevOut;
        prevOut = buffOut[i];
    }
    // 把处理完的缓冲区数据写入输出文件
    fwrite(buffOut, sizeof(int16_t), readCnt, outfile);
}

第三步:关闭文件释放资源

所有读写完成后一定要关闭文件,避免数据没刷入磁盘:

fclose(fp);
fclose(outfile);

额外注意事项

  • 如果你的WAV是立体声,采样是按左、右声道交替存储的,上述滤波逻辑会自动对两个声道都生效,不需要额外调整。
  • 如果需要实现高通滤波,把滤波公式换成y[n] = 0.5*(y[n-1] + x[n] - x[n-1])即可。
  • 如果你一定要保留你原来的相邻采样叠加逻辑,记得叠加后除以2,避免采样值溢出16位的取值范围,导致爆音。

内容的提问来源于stack exchange,提问作者Robert Gutu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 21:36:03