C语言实现WAV音频反转生成文件无声音问题求助
WAV音频反转程序生成无声音文件的排查与修复
我用C语言写了一个反转WAV音频片段并生成新WAV文件的程序,能成功生成输出文件,但文件没有声音。已经确认输入是WAV格式,计算了音频块大小,尝试从输入文件末尾开始逐块写入输出文件,要求保留每个音频块的声道顺序(比如双声道文件中,最后一个输入块的左声道要成为第一个输出块的左声道),但结果异常,需要排查问题原因。
原代码
#include <stdint.h> #include <stdio.h> #include <stdlib.h> #include "wav.h" #include <string.h> typedef uint8_t BYTE; 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 // TODO #1 if (argc != 3) { printf("usage: ./reverse input.wav output.wav\n"); return 1; } // Open input file for reading // TODO #2 FILE *input = fopen(argv[1], "r"); if (input == NULL) { printf("could not open file\n"); return 2; } // Read header into an array // TODO #3 WAVHEADER header; fread(&header, HEADER_SIZE, 1, input); // Use check_format to ensure WAV format // TODO #4 if (check_format(header) == 5) { printf("Incorrect file format\n"); return 3; } // Open output file for writing // TODO #5 FILE *output = fopen(argv[2], "w"); if (output == NULL) { printf("could not open file\n"); return 4; } // Write header to file // TODO #6 fwrite(&header, HEADER_SIZE, 1, output); // Use get_block_size to calculate size of block // TODO #7 int block_size = get_block_size(header); printf("block size is: %d\n", block_size); // Write reversed audio to file // TODO #8 fseek(input, 0, SEEK_END); long here = ftell(input); while (here > HEADER_SIZE) { int *Buffer[4]; fread(Buffer, 4, 1, input); fwrite(Buffer, 4, 1, output); fseek(input, -4, SEEK_CUR); here -= 4; } fclose(input); fclose(output); } int check_format(WAVHEADER header) { // TODO #4 BYTE *format = header.format; if (format[0] == 'W' && format[1] == 'A' && format[2] == 'V' && format[3] == 'E') { printf("is a wave file\n"); return 0; } else { printf("Bad\n"); return 5; } } int get_block_size(WAVHEADER header) { // TODO #7 int block_size = header.numChannels * (header.bitsPerSample / 8); return block_size; }
问题排查与修复要点
- 文件打开模式错误:WAV是二进制文件,必须用
"rb"(读二进制)和"wb"(写二进制)模式打开,原代码用"r"和"w"会导致系统处理换行符,破坏音频二进制数据。 - 缓冲区定义错误:原代码中
int *Buffer[4];是指针数组,不是存储音频数据的缓冲区,会导致非法内存读写,应改为与block_size匹配的字节数组或动态分配内存。 - 硬编码块大小:原代码硬编码读写4字节,没有使用计算出的
block_size,无法适配不同声道数、不同位深的WAV文件。 - 反转逻辑错误:原代码的文件指针移动逻辑错误,没有正确定位到上一个音频块的起始位置,导致读取的数据混乱。
修复后的代码
#include <stdint.h> #include <stdio.h> #include <stdlib.h> #include "wav.h" #include <string.h> typedef uint8_t BYTE; const int HEADER_SIZE = 44; int check_format(WAVHEADER header); int get_block_size(WAVHEADER header); int main(int argc, char *argv[]) { // 检查参数数量 if (argc != 3) { printf("usage: ./reverse input.wav output.wav\n"); return 1; } // 以二进制模式打开输入文件 FILE *input = fopen(argv[1], "rb"); if (input == NULL) { printf("could not open input file\n"); return 2; } // 读取WAV头部 WAVHEADER header; fread(&header, HEADER_SIZE, 1, input); // 验证WAV格式 if (!check_format(header)) { printf("Incorrect file format\n"); fclose(input); return 3; } // 以二进制模式打开输出文件 FILE *output = fopen(argv[2], "wb"); if (output == NULL) { printf("could not open output file\n"); fclose(input); return 4; } // 写入头部到输出文件 fwrite(&header, HEADER_SIZE, 1, output); // 计算音频块大小 int block_size = get_block_size(header); printf("block size is: %d\n", block_size); // 分配音频块缓冲区 BYTE *buffer = malloc(block_size); if (buffer == NULL) { printf("memory allocation failed\n"); fclose(input); fclose(output); return 5; } // 定位到输入文件末尾,开始反转读取 fseek(input, 0, SEEK_END); long current_pos = ftell(input); // 从最后一个音频块开始,向前遍历 while (current_pos > HEADER_SIZE) { // 回退一个块大小,定位到当前块的起始位置 fseek(input, -block_size, SEEK_CUR); // 读取一个音频块 fread(buffer, block_size, 1, input); // 写入到输出文件 fwrite(buffer, block_size, 1, output); // 回退两个块大小:读完后指针已移动block_size,需再退block_size到上一个块起始 fseek(input, -block_size * 2, SEEK_CUR); current_pos -= block_size; } // 释放资源 free(buffer); fclose(input); fclose(output); return 0; } int check_format(WAVHEADER header) { // 验证WAV格式标识 return (header.format[0] == 'W' && header.format[1] == 'A' && header.format[2] == 'V' && header.format[3] == 'E'); } int get_block_size(WAVHEADER header) { // 计算每个音频块的大小:声道数 × 每个样本的字节数 return header.numChannels * (header.bitsPerSample / 8); }
内容的提问来源于stack exchange,提问作者Diaplo
相关产品推荐
相关产品推荐

