0

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.

Cash_Lion
  • 61
  • 1
  • 8
  • If you're programming in C++, you should learn to use the [C++ input/output library](http://en.cppreference.com/w/cpp/io). – Some programmer dude Oct 21 '13 at 06:15
  • You are absolutely right, my code is more like C I suppose but I was recommended to use fwrite for this so that is what I happened to use. – Cash_Lion Oct 21 '13 at 06:36

2 Answers2

1

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").

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • Thank you, I added the b and it changed some values, but it was still incorrect. I am still working on this. – Cash_Lion Oct 21 '13 at 06:27
  • Yup, that was primarily it. After quite a few changes it is working now. Adding the b after the reading files was what made it happen. Thank you – Cash_Lion Oct 21 '13 at 16:13
0

HeaderInfo seems like a struct and what is the type of ChunkSize field? Try to find declaration in header file (*.h maybe riff.h or wave.h i don't now what kind of library you are using) where this struct was declared. Any way according your code HeaderInfo.ChunkSize should be an int value. So you can try something like that:

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

instead of:

int ChunkSizeOut = (HeaderInfo.ChunkSize)/2 + 18;
Sergey Kolesov
  • 480
  • 4
  • 16
  • ChunkSize is an int. I am using stdafx.h and Windows.h (Visual Studio 2010). I tried your suggestion but it did not change the result. Thank you for your response. I created the struct HeaderInfo and read the values in from the first wave file. – Cash_Lion Oct 21 '13 at 06:30
  • And if you change your `fwrite(&HeaderInfo.ChunkSize, sizeof(int), 1, fptr2);` on `fwrite(&ChunkSizeOut, sizeof(int), 1, fptr2)`; does it write in the new wave files value of `ChunkSizeOut` (the same value you write in console) – Sergey Kolesov Oct 21 '13 at 10:33
  • I swear I have been refreshing this page really often but it says your comment was 4 hours ago, sorry. Anyways, no, I try to do that but all of the values mess up. It doesn't even output what I wrote. It changes every time the program is run. – Cash_Lion Oct 21 '13 at 14:42
  • Yes what you said actually does work haha, my second reading file was not "rb" just "r" so all the numbers were wrong. – Cash_Lion Oct 21 '13 at 16:14