Search code examples
c++caudiowavbinaryfiles

loop through WAV file in c(or c++)


I am trying to copy a WAV sound in C. the original file is a 2 seconds file, but I want to replicate the data in the destination file several times, so that it plays longer. For example, if I copy it 3 times, it should play for 6 seconds... right?

But for some reason, even though the destination file is bigger than the original file, it still plays for 2 seconds... Can anyone help please?

Here is my code:

#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;
}

Solution

  • When you change size of your data you'll need to update output header as well.

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

    Also, to make sure you are reading correct file check that meta->chunk_size == file size of man1_nb.wav - 8