c-input.wav将复制到output.wav,但不会将输入文件乘以因子

  • 本文关键字:wav 文件 复制 output c-input c cs50
  • 更新时间 :
  • 英文 :


这个程序应该获取输入文件并将其复制到输出文件,然后通过2位采样,更改输入文件的体积,并将更新后的版本保存在输出文件中。输入文件复制到output.wav中,但不会改变它的音量。我知道我已经步入正轨,但不明白为什么它不能正常工作。这也以某种方式通过了check50,但当我自己编译和运行它时,它并没有完成它应该做的事情

// 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;
int main(int argc, char *argv[])
{
// Check command-line arguments
if (argc != 4)
{
printf("Usage: ./volume input.wav output.wav factorn");
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]);
// TODO: Copy header from input file to output file
uint8_t header[HEADER_SIZE];
fread(header, HEADER_SIZE, 1, input);
fwrite(header, HEADER_SIZE, 1, output);
// TODO: Read samples from input file and write updated data to output file
int16_t buffer;
while(fread(&buffer, sizeof(int16_t), 1, input))
{
buffer = buffer * factor;
fwrite(&buffer, sizeof(int16_t), 1, output);
}
// Close files
fclose(input);
fclose(output);
}

http://www-mmsp.ece.mcgill.ca/Documents/AudioFormats/WAVE/WAVE.html告诉你一个波形文件是一个区块序列。每个块以一个4字节的块id(chkid(开头,后跟一个4个字节(小端序(的块大小(cksize(。有不同类型的块,所以我建议你阅读chkid和cksize,然后弄清楚你是否想要处理这个块。对于缩放,您只需要处理ckkid=";数据";并且它假定您的文件是wFormatTag=WAVE_FORMAT_PCM,即PCM编码的。

你没有告诉我们太多关于你的输入文件的信息,所以我从https://samplelib.com/sample-wav.html.它由3个块组成;RIFF"fmt";以及";数据";。该文件中的数据样本从字节44开始。此文件的wBitsPerSample=16或每个样本2个字节。你说";2比特采样";但我想你指的是字节。当我在因子为2的文件上运行程序时,第一个样本是0xf872,即-1934,相应的输出文件样本是0xf4=-3868。当我在波形编辑器(在我的例子中是mhwaveedit(中直观地比较输入和输出文件时,它看起来是按比例缩放的。

正如我所提到的,buffer * factor可能不足或溢出,在音频中,您通常会对其进行剪辑而不是换行。以下是实现这一目标的方法:

printf("buffer = %d", buffer);
if(factor * buffer > INT16_MAX)
buffer = INT16_MAX;
else if(factor * buffer < INT16_MIN)
buffer = INT16_MIN;
else
buffer *= factor;
printf(" => %dn", buffer);

当我现在运行你的程序时,它会剪辑:

$ ./clipping input.wav output.wav 2|egrep -- '-32768|32767' | head -1
buffer = 16661 => 32767

之前该样本会溢出的位置:

$ ./scaling input.wav output.wav 2|grep 16661 | head -1
buffer = 16661 => -32214

最新更新