Search code examples
c++fopenfwritewav

C++ - Creating a Wave (.Wav) file from another Wave file but with a custom header


I am really new to programming so any help from you guys would be so helpful and I would be very grateful for it. This is C++ by the way. I have a wave file that I successfully read the header of. I want to create another wave file that has every other data value of the first wave file as the output. Each value will be the average of two from the first file.

This will decrease the number of samples by half. In order for it to play back at the right speed I need to change the header information of the second wave file so that the sampling frequency is halved. However, I cannot seem to do arithmetic operations when I am trying to use fwrite. I have successfully written a second wave file with an identical header as the first, but I need to change some of the values.

I really think it is just a simple data type being wrong or something, but I am a novice programmer so I can't figure it out.

FILE* fptr2;                        // File pointer for WAV output
fptr2 = fopen("KingdomOut.wav","w");    // Open wav file for reading


int ChunkSizeOut = (HeaderInfo.ChunkSize)/2 + 18;

cout << ChunkSizeOut << endl;

// RIFF chunk descriptor
fwrite(HeaderInfo.ChunkID, sizeof(char), 4, fptr2);             // "RIFF"
fwrite(&HeaderInfo.ChunkSize, sizeof(int), 1, fptr2);           // 4 + (8 + SubChunk1Size) + (8 + SubChunk2Size)
fwrite(HeaderInfo.Format, sizeof(char), 4, fptr2);              // "WAVE"
// fmt sub-chunk
fwrite(HeaderInfo.Subchunk1ID, sizeof(char), 4, fptr2);         // "fmt "
fwrite(&HeaderInfo.Subchunk1Size, sizeof(int), 1, fptr2);       // bytes remaining in subchunk, 16 if uncompressed
fwrite(&HeaderInfo.AudioFormat, sizeof(short), 1, fptr2);       // 1 = uncompressed
fwrite(&HeaderInfo.NumChannels, sizeof(short), 1, fptr2);       // mono or stereo
fwrite(&HeaderInfo.SampleRate, sizeof(int), 1, fptr2);
fwrite(&HeaderInfo.ByteRate, sizeof(int), 1, fptr2);            // == SampleRate * NumChannels * BitsPerSample/8
fwrite(&HeaderInfo.BlockAlign, sizeof(short), 1, fptr2);        // == NumChannels * BitsPerSample/8
fwrite(&HeaderInfo.BitsPerSample, sizeof(short), 1, fptr2);         
// data sub-chunk
fwrite(HeaderInfo.Subchunk2ID, sizeof(char), 4, fptr2);         // "data"
fwrite(&HeaderInfo.Subchunk2Size, sizeof(int), 1, fptr2);       // == NumSamples * NumChannels * BitsPerSample/8

fclose(fptr2);

This is the writing of the second wave file using the data from the first. (The header of the first wav file is in a struct called HeaderInfo). This code works perfectly, however I would like to change &HeaderInfo.Chunksize to the value I have near the top, ChunkSizeOut. I cannot simply input the value because it says variable of type int is incompatible. I have tried so much more but nothing seems to work. I also tried performing the arithmetic on &HeaderInfo.Chunksize but you cannot do that. I will change more variables than just this one, but the format will be the same for all.

Please help me, I will be so thankful.


Solution

  • Read about the fopen call. When writing binary files you need to add a 'b' to the open mode, like

    fptr2 = fopen("KingdomOut.wav","wb");    // Open wav file for reading
    

    The default, without the 'b' is to open the file in text mode, and that might cause some bytes to be written differently (more specifically, the value 0x0a might be written as the sequence 0x0d and 0x0a, that is newline '\n' may be converted to newline-carriage return "\r\n").