如何更改 .wav 文件的音量?

How to change the volume of a .wav file?

我的代码只是复制 header 但不会在第二个循环中更改音量。

// TODO: Copy header from the input file to the output file

uint8_t header[HEADER_SIZE];
uint8_t* header_p=malloc(HEADER_SIZE * sizeof(uint8_t));
while(fread(&header_p,sizeof(header[HEADER_SIZE]),1,input))
{
    fwrite(&header_p,sizeof(header[HEADER_SIZE]),1,output);
}

// TODO: Read samples from the input file and write updated data to the output file

int16_t buffer;

while(fread(&buffer,sizeof(buffer),1,input))
{
    buffer =(int16_t)(buffer*factor);
    fwrite(&buffer,sizeof(buffer),1,output);
}

如果一个特定的 WAV 文件仅包含 header 后跟代表声音数据的 16 位带符号值,则您的错误将出现在第一个 while 循环中。此循环继续从输入到输出复制 sizeof(header[HEADER_SIZE])(实际上是 header 中一个元素的大小为 1)个块,直到文件末尾为止,第二个 while 循环将不会已进入。

只需复制一次header,并使用更合适的缩放算法来修复其他一些问题。例如:

uint8_t header[HEADER_SIZE];
/* There is only one header, so parse it just once */
if (fread(&header[0], sizeof(header), 1, input)) {
    fwrite(&header[0], sizeof(header), 1, output);
}

/* Assuming 16-bit signed integer PCM payload */
int16_t sample;
while(fread(&sample, sizeof(sample), 1, input)) {
    /* Round value to nearest number */
    double scaledValue = floor((sample * factor) + 0.5);

    /* Clamp new value */
    if (scaledValue >= INT16_MAX) {
        sample = INT16_MAX;
    } else if (scaledValue <= INT16_MIN) {
        sample = INT16_MIN;
    } else {
        sample = (int16_t)scaledValue;
    }
    fwrite(&sample, sizeof(sample), 1, output);
}

然而 .wav 文件格式并没有那么简单并且有多种变体,16 位带符号 PCM 值只是其中之一。 header 中还给出了示例数据的大小和格式,您需要仔细解析 header 并采取相应的行动。有关 .wav 文件格式的更多信息,我想这些是一个很好的起点: