【问题标题】:loop through WAV file in c(or c++)在c(或c ++)中循环遍历WAV文件
【发布时间】:2017-10-02 08:59:28
【问题描述】:

我正在尝试在 C 中复制 WAV 声音。原始文件是一个 2 秒的文件,但我想多次复制目标文件中的数据,以使其播放时间更长。比如我复制3次,应该播放6秒……对吧?

但由于某种原因,即使目标文件比原始文件大,它仍然会播放 2 秒... 有人可以帮忙吗?

这是我的代码:

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

using namespace std;

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()

{
    FILE * infile = fopen("../files/man1_nb.wav","rb");     // Open wave file in read mode
    FILE * outfile = fopen("../files/Output.wav","wb");     // Create output ( wave format) file in write mode

    int BUFSIZE   = 2;                  // BUFSIZE can be changed according to the frame size required (eg: 512)
    int count     = 0;                      // For counting number of frames in wave file.
    short int buff16[BUFSIZE];              // short int used for 16 bit as input data format is 16 bit PCM audio
    header_p meta = (header_p)malloc(sizeof(header));   // header_p points to a header struct that contains the wave file metadata fields
    int nb;                         // variable storing number of byes returned
    if (infile)
    {
        fread(meta, 1, sizeof(header), infile); // Read only the header
        fwrite(meta,1, sizeof(*meta), outfile); // copy header to destination file
        int looper = 0;                         // number of times sound data is copied
        for(looper=0; looper <2; looper++){

        while (!feof(infile))
        {
            nb = fread(buff16,1,BUFSIZE,infile);        // Reading data in chunks of BUFSIZE
            count++;                                    // Incrementing Number of frames
            fwrite(buff16,1,nb,outfile);                // Writing read data into output file
        }
        fseek(infile, 44, SEEK_SET);                    // Go back to end of header
        }
    }
fclose(infile); fclose(outfile);
return 0;
}

【问题讨论】:

  • 您不对输出文件的标题进行任何更改。查看here 以获取格式说明。您可能应该关注Subchunk2Size 字段。
  • 我没有对标题进行任何更改。虽然我考虑过,但即使我确实更改了样本数量并复制了一次音频,它仍然会播放。当然,有些字段必须保持不变(例如采样率、通道数等...)
  • 我不知道细节,但很明显,标题必须以某种方式适应新的长度。
  • 检查this Stack Overflow Entry about the WAVE Format。它表示有一个 filesize 和一个 data section size 与您的小文件相同。
  • @makadev 该帖子实际上也不正确,因为它假定 wav 文件具有相同的固定大小标头。

标签: c++ c audio wav binaryfiles


【解决方案1】:

你的读写代码部分都是错误的。

wav 文件有 RIFF format 并由 tlv 块组成。每个块由标头和数据组成。通常 wav 文件由 3 个块组成:带有FOURCC 代码的格式块、带有PCMWAVEFORMAT 结构的格式块和带有声音数据的数据块。此外,由于每个块的大小受 32 位长度保持字段的限制,因此通过将 wav 文件连接在一起来构造大文件。

您需要逐块解析文件,并逐块写入目标文件,相应地更新标头。

【讨论】:

  • 谢谢,正在调查
【解决方案2】:

当您更改数据大小时,您还需要更新输出标头。

long total_bytes_written_to_outfile = ftell(outfile);

// correct chunk_size and subchunk2_size just before closing outfile:
fseek(outfile, 0, SEEK_SET);
int size = total_bytes_written_to_outfile - sizeof(*meta);
meta->chunk_size = sizeof(header) - sizeof(meta->chunk_id) - sizeof(meta->chunk_size) + size;
meta->subchunk2_size = size;
fwrite(meta, 1, sizeof(*meta), outfile);
fclose(outfile);

此外,为确保您读取的文件正确,请检查 meta-&gt;chunk_size == man1_nb.wav - 8 的文件大小

【讨论】:

  • @PhoenixBlue 它是经过 chunk_size 字段的字节数。 36 是sizeof(header) - sizeof(meta-&gt;chunk_id) - sizeof(meta-&gt;chunk_size)
猜你喜欢
  • 2019-05-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-03
  • 1970-01-01
  • 2011-01-25
  • 2014-12-04
  • 1970-01-01
相关资源
最近更新 更多