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

C语言WAV文件反转程序异常:输出文件损坏无法播放

WAV文件反转程序输出损坏问题排查

我使用C语言编写了一个WAV文件反转程序,已完成编写并多次检查逻辑错误,程序可编译生成可执行文件并输出WAV文件,但输出文件存在损坏/错误,无法播放音频。请帮忙排查代码问题,感谢。

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "wav.h"

int check_format(WAVHEADER header);
int get_block_size(WAVHEADER header);

int main(int argc, char *argv[])
{
    // Ensure proper usage
    if (argc != 3)
    {
        printf("usage: ./reverse input.wav output.wav\n");
        return 1;
    }

    // Open input file for reading
    char *input_name = argv[1];
    char *output_name = argv[2];
    FILE *inptr = fopen(input_name, "r");

    if (inptr == NULL)
    {
        printf("File could not be opened\n");
        return 1;
    }

    // Read header
    WAVHEADER in_wav_header;
    fread(&in_wav_header, sizeof(WAVHEADER), 1, inptr);

    // check if input file is WAV file
    if (check_format(in_wav_header) != 0)
    {
        fclose(inptr);
        printf("unsupported file format\n");
        return 1;
    }

    // Open output file for writing
    FILE *outptr;
    outptr = fopen(output_name, "w");

    if (outptr == NULL)
    {
        printf("error creating output file\n");
        return 1;
    }

    // Write header to file
    fwrite(&in_wav_header, sizeof(WAVHEADER), 1, inptr);

    // Use get_block_size to calculate size of block
    int block_size = get_block_size(in_wav_header);
    printf("%i\n", block_size);

    // declare buffer array
    BYTE *buffer = malloc(sizeof(block_size));

    // set cursor to start of last block of input audio file
    fseek(inptr, -block_size, SEEK_END);

    // iterate through input file blocks, checking for header, and writing blocks
    // to the output file
    while (ftell(inptr) >= sizeof(WAVHEADER))
    {
        fread(buffer, block_size, 1, inptr);
        fwrite(buffer, block_size, 1, outptr);
        if (fseek(inptr, 2 * -block_size, SEEK_CUR))
        {
            return 1;
        }
    }

    // close files & free malloc space
    free(buffer);
    fclose(inptr);
    fclose(outptr);
}

int check_format(WAVHEADER header)
{
    char check[] = {'W', 'A', 'V', 'E'};
    for (int i = 0; i < 4; i++)
    {
        if (header.format[i] != check[i])
        {
            return 1;
        }
    }
    return 0;
}

int get_block_size(WAVHEADER header)
{
    if (header.numChannels == 1 || header.numChannels == 2)
    {
        int block_size = (header.bitsPerSample / 8) * header.numChannels;
        return block_size;
    }
    else
    {
        printf("error: too many audio channels\n");
        return 1;
    }
}

代码中的关键错误及修复方案

  • 头文件写入目标错误:代码中fwrite(&in_wav_header, sizeof(WAVHEADER), 1, inptr);将WAV头写入了输入文件inptr,而非输出文件outptr。这会破坏原输入文件,同时输出文件缺少必要的WAV头,直接导致文件无法被音频播放器识别。
    修复:将inptr改为outptr:

    fwrite(&in_wav_header, sizeof(WAVHEADER), 1, outptr);
    
  • 二进制文件打开模式错误:WAV是二进制文件,使用"r"和"w"模式打开会触发系统自动转换换行符(Windows系统下),破坏二进制数据的完整性。
    修复:打开文件时使用二进制模式:

    FILE *inptr = fopen(input_name, "rb");
    FILE *outptr = fopen(output_name, "wb");
    
  • 内存分配大小错误:malloc(sizeof(block_size))实际分配的是int类型的字节数(通常为4字节),而非block_size指定的音频块大小。若block_size大于4,会导致缓冲区溢出,写入错误数据。
    修复:直接使用block_size作为内存分配的大小:

    BYTE *buffer = malloc(block_size);
    
  • 错误返回值混淆:get_block_size函数在通道数非法时返回1,但1是有效的音频块大小(比如单声道8位音频),会导致后续逻辑误以为块大小有效,继续执行错误操作。
    修复:返回负数作为错误标识:

    else
    {
        printf("error: too many audio channels\n");
        return -1;
    }
    

    同时在主函数中增加错误判断:

    int block_size = get_block_size(in_wav_header);
    if (block_size <= 0)
    {
        fclose(inptr);
        fclose(outptr);
        return 1;
    }
    
  • 循环边界潜在问题:当音频数据长度刚好是块大小的整数倍时,最后一次fseek可能会让文件指针跳到WAV头之前,导致多读无关数据。可以调整循环逻辑,确保只处理音频数据部分:

    // 计算音频数据起始位置和总长度
    long data_start = sizeof(WAVHEADER);
    long current_pos = ftell(inptr);
    
    while (current_pos >= data_start)
    {
        fread(buffer, block_size, 1, inptr);
        fwrite(buffer, block_size, 1, outptr);
        current_pos -= 2 * block_size;
        if (fseek(inptr, current_pos, SEEK_SET) != 0)
        {
            break;
        }
    }
    

内容的提问来源于stack exchange,提问作者Charlie Webster

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 01:56:11