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

C语言WAV音频反转程序无法创建/写入output.wav问题排查

WAV音频反转程序无法生成output.wav文件问题排查

我编写了一个用于反转.wav音频文件的C程序,但无论如何都无法生成output.wav文件。推测问题出在文件写入信息的环节,可能是内存操作或逻辑错误导致。尝试过用errno调试但无帮助,也未出现预期的"Couldn't create file"提示,因此聚焦于文件写入相关的代码逻辑排查。

问题代码

WavHeader.h

#include <stdint.h>
typedef uint8_t   BYTE;
typedef uint16_t  WORD;
typedef uint32_t  DWORD;
typedef struct
{
    BYTE   chunkID[4];
    DWORD  chunkSize;
    BYTE   format[4];
    BYTE   subchunk1ID[4];
    DWORD  subchunk1Size;
    WORD   audioFormat;
    WORD   numChannels;
    DWORD  sampleRate;
    DWORD  byteRate;
    WORD   blockAlign;
    WORD   bitsPerSample;
    BYTE   subchunk2ID[4];
    DWORD  subchunk2Size;
} __attribute__((__packed__))
WAVHEADER;

reverse.c

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

#include "wav.h"

// Number of bytes in .wav header
const int HEADER_SIZE = 44;

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
    FILE *input = fopen(argv[1], "rb");
    if (input == NULL)
    {
        printf("Could not open file.\n");
        return 1;
    }

    // Read header
    WAVHEADER header;
    fread(&header, 1, HEADER_SIZE, input);

    // Use check_format to ensure WAV format
    int result = check_format(header);
    if (result == 0)
    {
        return 0; // format is okay
    }
    if (result != 0)
    {
        printf("File is unsupported format, ensure it extension is a .WAV\n");
        return 1;
    }

    // Open output file for writing
    FILE *output = fopen(argv[2], "w");
    if (output == NULL)
    {
        fclose(input);
        printf("Could not create file.\n");
        return 1;
    }

    // Write header to file
    fwrite(&header, 1, HEADER_SIZE, output);

    // Use get_block_size to calculate size of block
    int block =  get_block_size(header);


    // Write reversed audio to file

    int16_t *buffer = malloc(block); // Allocate memory for the audio buffer
    if (buffer == NULL)
    {
        printf("Memory allocation error.\n");
        fclose(input);
        fclose(output);
        return 1;
    }

    fseek(input, HEADER_SIZE, SEEK_SET);

    // Calculate the number of audio blocks in the file
    long numBlocks = (header.subchunk2Size) / block;

    // Read audio blocks from input, reverse, and write to output
    for (long i = 0; i < numBlocks; i++)
    {
        fseek(input, -(i + 1) * block, SEEK_END);
        fread(buffer, block, 1, input);
        fwrite(buffer, block, 1, output);
    }

    // clean up
    free(buffer);
    fclose(input);
    fclose(output);
    return 0;
}

int check_format(WAVHEADER header)
{
    if (header.format[0] == 'W' && header.format[1] == 'A' && header.format[2] == 'V' && header.format[3] == 'E')
    {
        return 0; // if format is correct
    }
    else
    return 1; // if format is not .WAV
}

int get_block_size(WAVHEADER header)
{
    int blockSize = header.numChannels * (header.bitsPerSample / 8);
    return blockSize;
}

核心问题与修复方案

1. 头文件引用错误

reverse.c中#include "wav.h",但实际头文件名为WavHeader.h,编译时会找不到头文件,导致WAVHEADER类型未定义,程序无法编译通过。
修复:将引用改为#include "WavHeader.h"(确保文件名大小写与实际一致)。

2. 格式检查逻辑完全颠倒

check_format函数返回0表示格式正确,但main函数中判断result == 0时直接return 0退出程序,导致格式正确的情况下根本不会执行后续的文件写入操作,这是生成不了输出文件的关键原因。
修复:调整逻辑:

int result = check_format(header);
if (result != 0)
{
    printf("File is unsupported format, ensure it extension is a .WAV\n");
    fclose(input);
    return 1;
}
// 格式正确,继续执行后续逻辑

3. 输出文件打开模式错误

用"w"模式打开二进制文件会导致系统自动转换换行符(比如Windows下将\n转为\r\n),破坏WAV文件的二进制结构,甚至导致写入失败。
修复:用二进制写入模式"wb"打开输出文件:

FILE *output = fopen(argv[2], "wb");

4. 内存分配类型不匹配

int16_t* buffer仅适用于16位采样的WAV文件,如果是8位或24位采样,类型会不匹配,可能导致内存访问错误。
修复:改用通用的uint8_t*:

uint8_t *buffer = malloc(block);

5. 音频读取逻辑优化

原循环中频繁从文件末尾反向偏移fseek,效率较低且存在边界风险。可以先将所有音频数据读入内存,再反转写入:

// 读取所有音频数据到内存
uint8_t *audio_data = malloc(header.subchunk2Size);
if (audio_data == NULL) { /* 错误处理 */ }
fread(audio_data, 1, header.subchunk2Size, input);

// 反转写入:从最后一个block开始往前写
for (long i = numBlocks - 1; i >= 0; i--) {
    fwrite(audio_data + i * block, block, 1, output);
}

free(audio_data);

修复后的完整reverse.c示例

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

#include "WavHeader.h"

// Number of bytes in .wav header
const int HEADER_SIZE = 44;

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
    FILE *input = fopen(argv[1], "rb");
    if (input == NULL)
    {
        printf("Could not open file.\n");
        return 1;
    }

    // Read header
    WAVHEADER header;
    fread(&header, 1, HEADER_SIZE, input);

    // Use check_format to ensure WAV format
    int result = check_format(header);
    if (result != 0)
    {
        printf("File is unsupported format, ensure it extension is a .WAV\n");
        fclose(input);
        return 1;
    }

    // Open output file for writing
    FILE *output = fopen(argv[2], "wb");
    if (output == NULL)
    {
        fclose(input);
        printf("Could not create file.\n");
        return 1;
    }

    // Write header to file
    fwrite(&header, 1, HEADER_SIZE, output);

    // Use get_block_size to calculate size of block
    int block = get_block_size(header);

    // Allocate memory for audio data
    uint8_t *audio_data = malloc(header.subchunk2Size);
    if (audio_data == NULL)
    {
        printf("Memory allocation error.\n");
        fclose(input);
        fclose(output);
        return 1;
    }

    // Read all audio data
    fread(audio_data, 1, header.subchunk2Size, input);

    // Calculate the number of audio blocks in the file
    long numBlocks = (header.subchunk2Size) / block;

    // Write reversed audio blocks to output
    for (long i = numBlocks - 1; i >= 0; i--)
    {
        fwrite(audio_data + i * block, block, 1, output);
    }

    // Clean up
    free(audio_data);
    fclose(input);
    fclose(output);
    return 0;
}

int check_format(WAVHEADER header)
{
    return (header.format[0] == 'W' && header.format[1] == 'A' && header.format[2] == 'V' && header.format[3] == 'E') ? 0 : 1;
}

int get_block_size(WAVHEADER header)
{
    return header.numChannels * (header.bitsPerSample / 8);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 04:45:54