A Wave file, like many graphic and sound files, has a header file at the beginning that describes the sound data contained in the file. This header was created by Microsoft and contains everything we need to know about the sound file and then some. The first 4 bytes in a wave file header in determining if the file we opened is really a wave file. The first four bytes should contain the text "RIFF", RIFF means that it's a microsoft media file of some sort, if we have RIFF it may not necessarily mean we have a wave sound file, RIFF is also at the start of MIDI and other various multimedia files. The next 4 bytes is a 32 bit value describing how big the rest of the file is going to be (not including those first four "RIFF" bytes). Let's write some code to open up a file and read these in:
FILE *fp;
fp = fopen("sound.wav","rb);
if (fp)
{
BYTE id[4]; //four bytes to hold 'RIFF'
DWORD size; //32 bit value to hold file size
fread(id,sizeof(BYTE),4,fp); //read in first four bytes
if (!strcmp(id,"RIFF"))
{ //we had 'RIFF' let's continue
fread(size,sizeof(DWORD),1,fp);
//read in 32bit size value
}
}
FILE *fp;
fp = fopen("sound.wav","rb);
if (fp)
{
BYTE id[4]; //four bytes to hold 'RIFF'
DWORD size; //32 bit value to hold file size
fread(id,sizeof(BYTE),4,fp); //read in first four bytes
if (!strcmp(id,"RIFF"))
{ //we had 'RIFF' let's continue
fread(size,sizeof(DWORD),1,fp);
//read in 32bit size value
fread(id,sizeof(BYTE),4,fp);
//read in 4 byte string now
if (!strcmp(id,"WAVE"))
{ //this is probably a wave file since it contained "WAVE"
fread(id,sizeof(BYTE),4,fp); //read in 4 bytes "fmt ";
}
}
}
After "fmt " we have a 32 bit value that says how big our following format chunk is going to be, for a typical wave file this will be "16", meaning that we're going to use the next 16 bytes in the file to describe the sound data's format. Be careful though, this value may not always be a 16 - wave files that are compressed (like ADPCM or such) use different format chunk sizes and you may need to adjust, if you don't have a 16 here you may want to abort the load unless you know about the way the compressed file stores it's format info. Let's see what those next 16 bytes are going to be in a typical wave file:32 bit value saying how big the format chunk is (in bytes)
16 bit value identifying the format tag (identifies way data is stored, 1 here means no compression (PCM), if otherwise it's some other type of format)
16 bit value describing # of channels (1 means mono, 2 means stereo)
32 bit value describing sample rate or number of samples per second (like 44100, 22050, or 11025)
32 bit value describing average # of bytes per second (found by: samplerate*channels*(bitspersample/8)) you probably won't need or use this value
16 bit value describing block alignment (found by: (bitspersample/8)*channels) you probably won't need or use this value either
16 bit value describing bits per sample (8bit or 16bit sound)
Ok now that we know what those next 16 bytes describing the format are, let's add some source code to reflect this:
FILE *fp;
fp = fopen("sound.wav","rb);
if (fp)
{
BYTE id[4]; //four bytes to hold 'RIFF'
DWORD size; //32 bit value to hold file size
//our 16 bit format info values
short format_tag, channels, block_align, bits_per_sample;
DWORD format_length, sample_rate, avg_bytes_sec; //our 32 bit format info values
fread(id, sizeof(BYTE), 4, fp); //read in first four bytes
if (!strcmp(id, "RIFF"))
{ //we had 'RIFF' let's continue
fread(size, sizeof(DWORD), 1, fp); //read in 32bit size value
fread(id, sizeof(BYTE), 4, fp); //read in 4 byte string now
if (!strcmp(id,"WAVE"))
{ //this is probably a wave file since it contained "WAVE"
fread(id, sizeof(BYTE), 4, fp); //read in 4 bytes "fmt ";
fread(format_length, sizeof(DWORD),1,fp);
fread(format_tag, sizeof(short), 1, fp);
fread(channels, sizeof(short),1,fp);
fread(sample_rate, sizeof(DWORD), 1, fp);
fread(avg_bytes_sec, sizeof(short), 1, fp);
fread(block_align, sizeof(short), 1, fp);
fread(bits_per_sample, sizeof(short), 1, fp);
}
else
printf("Error: RIFF file but not a wave file\n");
}
else
printf("Error: not a RIFF file\n");
}
void Load_Wave_File(char *fname)
{
FILE *fp;
fp = fopen(fname,"rb);
if (fp)
{
BYTE id[4], *sound_buffer; //four bytes to hold 'RIFF'
DWORD size; //32 bit value to hold file size
short format_tag, channels, block_align, bits_per_sample; //our 16 values
DWORD format_length, sample_rate, avg_bytes_sec, data_size, i; //our 32 bit values
fread(id, sizeof(BYTE), 4, fp); //read in first four bytes
if (!strcmp(id, "RIFF"))
{ //we had 'RIFF' let's continue
fread(size, sizeof(DWORD), 1, fp); //read in 32bit size value
fread(id, sizeof(BYTE), 4, fp); //read in 4 byte string now
if (!strcmp(id,"WAVE"))
{ //this is probably a wave file since it contained "WAVE"
fread(id, sizeof(BYTE), 4, fp); //read in 4 bytes "fmt ";
fread(&format_length, sizeof(DWORD),1,fp);
fread(&format_tag, sizeof(short), 1, fp); //check mmreg.h (i think?) for other
// possible format tags like ADPCM
fread(&channels, sizeof(short),1,fp); //1 mono, 2 stereo
fread(&sample_rate, sizeof(DWORD), 1, fp); //like 44100, 22050, etc...
fread(&avg_bytes_sec, sizeof(short), 1, fp); //probably won't need this
fread(█_align, sizeof(short), 1, fp); //probably won't need this
fread(&bits_per_sample, sizeof(short), 1, fp); //8 bit or 16 bit file?
fread(id, sizeof(BYTE), 4, fp); //read in 'data'
fread(&data_size, sizeof(DWORD), 1, fp); //how many bytes of sound data we have
sound_buffer = (BYTE *) malloc (sizeof(BYTE) * data_size); //set aside sound buffer space
fread(sound_buffer, sizeof(BYTE), data_size, fp); //read in our whole sound data chunk
}
else
printf("Error: RIFF file but not a wave file\n");
}
else
printf("Error: not a RIFF file\n");
}
}
Disclaimer and Distribution Info
[hr] This file is Copyright 1998, Nathan Davidson
You may NOT distribute this tutorial or put it up on your website without getting my permission first.
All information is provided "as is" and the author assumes no responsibility for any damage caused by use of information in this tutorial. Use at your own risk.
[hr]
If you want to see some other sound tutorials then head over to my web site, currently located at:
http://www.aros.net/~npawn/
Reprinted with permission
Hi,
Small typos in code (both in last and second to last code listing):
should be:
And
should be:
(the same error exists in all nonpointer values in the second to last listing).