这段代码成功生成了输出文件,但实际上没有声音,我还不知道出了什么问题
#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 段并打印文件的标题,之后应该从输入文件的末尾开始打印从输入文件到输出文件的每个块,直到到达文件的标题文件(避免再次打印文件头),并且我计算了文件每个块的大小。
我们希望保持每个音频块的通道顺序。例如,在一个两通道WAV文件(立体声音频)中,我们要确保最后一个输入音频块的第一个通道成为第一个输出音频块的第一个通道。
我将此作为格式的答案发布,但我只想解释一些事情。当您打开文件时,该文件具有关联的位置。这就像数据中的索引。使用
fseek()
您可以更改此位置,但是当您简单地 fread()
时,位置也会增加。
在这里,您寻求结尾,因此几行之后,您就读到了“过去”结尾。那里没有数据。因此,在查找到末尾之后,您应该向后查找 4 个字节。这可确保您从读取最后 4 个字节开始。
fseek(input, 0, SEEK_END);
...
while (here > HEADER_SIZE)
{
...
fread(Buffer, 4, 1, input);
fseek(input, -4, SEEK_CUR);
现在,正如您所看到的,read 将位置向前移动了 4,然后 search 也将其向后移动了 4。所以你最终会循环相同的字节。相反,您应该回溯 8 个字节。
here
变量不受此影响,因此每步减少 4 是正确的。
BYTE *lChannel = malloc(sizeof(blockSize / 2));
BYTE *rChannel = malloc(sizeof(blockSize / 2));
// seek pointer to lasst blockSize of input file
fseek(input, -(blockSize) - 1, SEEK_END);
int i = 1;
long int initFtell = ftell(input);
while (fread(audioBlock, sizeof(BYTE), blockSize, input) == blockSize)
{
i += 1;
long int k = (blockSize * i);
memcpy(lChannel, audioBlock, blockSize / 2);
memcpy(rChannel, &audioBlock[blockSize / 2], blockSize / 2);
fwrite(rChannel, sizeof(BYTE), blockSize / 2, output);
fwrite(lChannel, sizeof(BYTE), blockSize / 2, output);
fseek(input, -(blockSize * i), SEEK_END);
// printf("ftell: %li, k: %li\n", ftell(input), -k);
if ((initFtell - k - HEADERSIZE) == 0) { break; } else { continue; }
}
// #9 close opened files
fclose(output);
fclose(input);
}