c - 将数据写入 wav 文件

Posted

技术标签:

【中文标题】c - 将数据写入 wav 文件【英文标题】:c - writing data to wav file 【发布时间】:2017-01-09 22:24:24 【问题描述】:

我正在开发一个从 wav 文件中读取数据的小工具。该工具首先提取标题,然后将音频数据分成左右声道。音频文件就是采样频率为44100Hz、16Bit PCM、双通道的文件。

处理数据后,我想将数据写回输出文件并在每个通道上附加 100 个零。这里出现了问题:每个通道上仅附加了一半的所需样本。其次,附加“零”的前半部分是随机数据。

在下面查看我的代码

#include <stdlib.h>
#include <stdio.h>

#define BUFFSIZE 1024
#define NUM_ZEROS 100

#include <stdio.h>
#include <stdlib.h>

typedef struct header_file

    char chunk_id[4];
    int chunk_size;
    char format[4];
    char subchunk1_id[4];
    int subchunk1_size;
    short int audio_format;
    short int num_channels;
    int sample_rate;
    int byte_rate;
    short int block_align;
    short int bits_per_sample;
    char subchunk2_id[4];
    int subchunk2_size;
 header;

typedef struct header_file* header_p;


int main(int argc, char** argv)

    if( argc != 3 )
        printf("Wrong number of input arguments. Aborting.\n");
        return -1;
    

    char *inputFile = argv[1];
    char *outputFile = argv[2];

    FILE * infile = fopen(inputFile, "r+");
    FILE * outfile = fopen(outputFile, "w+");

    int count = 0;                                      // For counting number of frames in wave file.
    short int buff16[2*BUFFSIZE];                       // short int used for 16 bit as input data format is 16 bit PCM audio
    short int buffLeft[BUFFSIZE], buffRight[BUFFSIZE];
    header_p meta = (header_p)malloc(sizeof(header));   // header_p points to a header struct that contains the wave file metadata fields
    int nb, cnt;                                        // variable storing number of bytes returned

    printf("Buffers initialized.\n");

    if (infile)
    
        fread(meta, 1, sizeof(header), infile);
        meta->subchunk2_size = meta->subchunk2_size + 2 * NUM_ZEROS;
        fwrite(meta,1, sizeof(*meta), outfile);


        while (!feof(infile))
        
            nb = fread(buff16,1,BUFFSIZE,infile);       // Reading data in chunks of BUFSIZE
            count++;                                    // Incrementing Number of frames

            for(cnt = 0; cnt < nb/2; cnt++)
                buffLeft[cnt] = buff16[2*cnt];
                buffRight[cnt] = buff16[2*cnt+1];
            

            /*
             * TODO: INSERT SIGNAL PROCESSING PART
             */

            for(cnt = 0; cnt < nb/2; cnt++)
                buff16[2*cnt] = buffLeft[cnt];
                buff16[2*cnt+1] = buffRight[cnt];
            

            fwrite(buff16,1,nb,outfile);
        

        for(cnt = 0; cnt < 2*NUM_ZEROS; cnt++)
            buff16[cnt] = 0;
        
        fwrite(buff16,1, 2*NUM_ZEROS,outfile);

        printf("Number of frames in the input wave file are %d.\n", count);
    

    fclose(infile);
    fclose(outfile);

    return 0;

有人知道我做错了什么吗?

【问题讨论】:

【参考方案1】:

你确定只有一部分添加的零是垃圾吗?

您弄乱了freadfwrite 的数据大小

你的缓冲区是short int:

short int buff16[2*BUFFSIZE]; // BUFFSIZE*2*sizeof(short) bytes

你只阅读了那个大小的 1/4:

nb = fread(buff16,1,BUFFSIZE,infile);  // BUFFSIZE bytes

这读取 BUFSIZE bytes 因为您只指定每个元素的大小为 1。 而不是BUFFSIZE*2 短裤,您只能读取BUFFSIZE 字节。 返回值是读取元素的数量,即字节数。 在您的缓冲区中,该数据量仅足以用于 nb/2 元素,但您访问 buff16[0] .. buff16[nb-1] 后半部分未从文件中读取。 幸运的是,您也没有将后半部分写回新文件中,因为 那里也存在与长度相同的错误。 最后,当您将零值附加到文件时,也会出现同样的问题。

tl;dr

freadfwrite 的大小参数更改为sizeof(short int)

【讨论】:

【参考方案2】:

你有

#define NUM_ZEROS 100

fwrite(buff16,1, 2*NUM_ZEROS,outfile);

目标:

我想将数据写回输出文件并附加 100 个零 在每个频道上。

我认为每个频道应该有 100 个样本。 由于您有 16 位 PCM,因此每个样本为 2 个字节。 因此,一个通道需要写入 200 个字节(零)。立体声意味着 400 字节。

您的 fwrite 仅保存 2*NUM_ZEROS 即 200 个字节 - 这是关于丢失样本的部分答案。

另外你声明

short int buff16[2*BUFFSIZE];

只读取一半并使用一半 (nb/2) 进行处理。比写满缓冲区(实际上是声明的一半),上半部分充满内存中的随机垃圾。

【讨论】:

以上是关于c - 将数据写入 wav 文件的主要内容,如果未能解决你的问题,请参考以下文章

如何更改 aurioTouch 项目以将录音写入 .caff 或 .wav 文件

写入 WAV 文件 C++

使用 ExtAudioFileWrite ios 将流式 mp3 数据包的缓冲区写入 wav 文件

Python:将 wav 文件写入 numpy 浮点数组

来自另一个 wav 文件的 WAV 文件写入问题

写入 PCM 数据时的文件 (.wav) 持续时间 @16KBps