以下是我对CS50 第 4 周:音量 的解决方案。我试图解决的问题是读取 .wav 文件并根据命令行参数“factor”更改其音量。
问题:
当我测试此代码时,我最初使用
fread(header, HEADER_SIZE, 1, input);
我的代码进行编译而不会出现错误,并且会生成以下内容的输出文件:
./volume input.wav output.wav 1.0
但是,如果我将音量因子更改为 1.0 以外的任何其他值,就会生成损坏的输出文件。
// Modifies the volume of an audio file
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
// Number of bytes in .wav header
const int HEADER_SIZE = 44;
void copy_header(FILE *input, FILE *output);
void copy_samples(FILE *input, FILE *output, float factor);
int main(int argc, char *argv[])
{
// Check command-line arguments
if (argc != 4)
{
printf("Usage: ./volume input.wav output.wav factor\n");
return 1;
}
// Open files and determine scaling factor
FILE *input = fopen(argv[1], "r");
if (input == NULL)
{
printf("Could not open file.\n");
return 1;
}
FILE *output = fopen(argv[2], "w");
if (output == NULL)
{
printf("Could not open file.\n");
return 1;
}
float factor = atof(argv[3]);
copy_header(input, output);
copy_samples(input, output, factor);
// Close files
fclose(input);
fclose(output);
}
void copy_header(FILE *input, FILE *output)
{
uint8_t header[HEADER_SIZE];
fread(header, sizeof(HEADER_SIZE), 1, input);
fwrite(header, sizeof(HEADER_SIZE), 1, output);
printf("header: %s; header_size: %lu; HEADER_s: %lu\n", header, sizeof(header), sizeof(HEADER_SIZE));
}
void copy_samples(FILE *input, FILE *output, float factor)
{
int16_t buffer;
while (fread(&buffer, sizeof(int16_t), 1, input) != 0)
{
buffer = buffer * factor;
fwrite(&buffer, sizeof(int16_t), 1, output);
}
}
经过大量挖掘后,我发现输出:
printf("header: %s; header_size: %lu; HEADER_s: %lu\n", header, sizeof(header), sizeof(HEADER_SIZE));
将是:
header: RIFFDb; header_size: 44; HEADER_s: 4
为什么 sizeof(HEADER_SIZE) 的值会变为 4?我是不是完全忽略了什么?我解决这个问题的方法正确吗?
我使用以下方法修复了代码中的错误:
fread(header, sizeof(header), 1, input);
但我想知道为什么以及如何破坏此代码。提前致谢!
当我们查看这些行时:
您似乎认为,在声明 之后
header
, 的大小HEADER_SIZE
现在与 的大小相关联header
。事实并非如此。运算
sizeof
符计算其操作数的大小(以字节为单位)。在 的情况下,sizeof(HEADER_SIZE)
操作数是 类型的变量HEADER_SIZE
(或更准确地说是带括号的变量)int
。计算结果为 4,因为int
在您的系统上占用 4 个字节。这导致您的代码出现问题,因为仅读取了 4 个字节而不是您想要的 44 个字节。
这有效:
因为
sizeof(header)
它给出的是数组的字节大小header
,即 44。这也行得通:
因为它将传入 44 作为要读取的字节数。