   Loading WAVs For OpenAL
  I am trying to load WAV files into memory to use with OpenAL. I have done some research on the internet, and it looks like alut is used to load wavs, however, this is not an option I can use. I was able to load the WAV's riff header and both sub chunks with not problem. The only problem is getting the data read, and the proper format. I feed my data to OpenAL via alBufferData(), but I do not think the format I am feeding in (value is 1 for PCM in the WAV file) is correct because no data is played. Here is my loading code:bool LoadWAV(const char *filename, int *format, void *data, int *size, int *freq){FILE *fp = NULL;RIFFHeader riff;WAVSubChunk1 chunk1;WAVSubChunk2 chunk2;fp = fopen(filename, "rb");if(!fp){printf("LoadWAV(%s): invalid file\n", filename);return false;}// read the sub chunk datafread(&riff, sizeof(RIFFHeader), 1, fp);fread(&chunk1, sizeof(WAVSubChunk1), 1, fp);fread(&chunk2, sizeof(WAVSubChunk2), 1, fp);riff.Print();chunk1.Print();chunk2.Print();data = malloc(chunk2.subChunkSize);fread(data, sizeof(chunk1.bitsPerSample / 8), chunk2.subChunkSize / (chunk1.bitsPerSample / 8), fp);//set the data*format = chunk1.format;*size = chunk2.subChunkSize;*freq = chunk1.sampleRate;return true;}alBufferData(buffer[0],format,data,size,freq); // parameters are globalsBtw, aren't there code tags I can use for this? I could not find them.   
  Alright, after a nap, I was able to figure out two things:1) I did not have OpenAL initialized...2) Allocating and writing data to void*-typed pointers caused errors when uploading to OpenAL, so I just used unsigned char arrays instead. Here is working code in case anyone needs to manually load a WAV:struct RIFFHeader{char riff[4];long size;char wave[4];void Print(){printf("RIFFHeader::Print()\n");printf("riff: %c%c%c%c\n", riff[0], riff[1], riff[2], riff[3]);printf("size: %i\n", size);printf("wave: %c%c%c%c\n", wave[0], wave[1], wave[2], wave[3]);printf("\n");}};struct WAVSubChunk1{char subChunkId[4];long subChunkSize;short format;short numChannels;long sampleRate;long byteRate;short blockAlign;short bitsPerSample;void Print(){printf("WAVSubChunk1::Print()\n");printf("subChunkId: %c%c%c%c\n", subChunkId[0], subChunkId[1], subChunkId[2], subChunkId[3]);printf("subChunkSize: %i\n", subChunkSize);printf("format: %i\n", format);printf("numChannels: %i\n", numChannels);printf("sampleRate: %i\n", sampleRate);printf("byteRate: %i\n", byteRate);printf("blockAlgin: %i\n", blockAlign);printf("bitsPerSample: %i\n", bitsPerSample);printf("\n");}};struct WAVSubChunk2{char subChunkId[4];long subChunkSize;void Print(){printf("WAVSubChunk2::Print()\n");printf("subChunkId: %c%c%c%c\n", subChunkId[0], subChunkId[1], subChunkId[2], subChunkId[3]);printf("subChunkSize: %i\n", subChunkSize);printf("\n");}};unsigned char *LoadWAV(const char *filename, int *format, int *size, int *freq){FILE *fp = NULL;unsigned char *data = NULL;RIFFHeader riff;WAVSubChunk1 chunk1;WAVSubChunk2 chunk2;fp = fopen(filename, "rb");if(!fp){printf("LoadWAV(%s): invalid file\n", filename);return NULL;}// read the sub chunk datafread(&riff, sizeof(RIFFHeader), 1, fp);fread(&chunk1, sizeof(WAVSubChunk1), 1, fp);fread(&chunk2, sizeof(WAVSubChunk2), 1, fp);// print the sound datariff.Print();chunk1.Print();chunk2.Print();// check chunk identifiersif(riff.riff[0] != 'R' || riff.riff[1] != 'I' || riff.riff[2] != 'F' || riff.riff[3] != 'F'){printf("LoadWAV(%s): invalid 'RIFF' header\n", filename);return NULL;}if(riff.wave[0] != 'W' || riff.wave[1] != 'A' || riff.wave[2] != 'V' || riff.wave[3] != 'E'){printf("LoadWAV(%s): invalid 'WAVE' header\n", filename);return NULL;}if(chunk1.subChunkId[0] != 'f' || chunk1.subChunkId[1] != 'm' || chunk1.subChunkId[2] != 't' || chunk1.subChunkId[3] != ' '){printf("LoadWAV(%s): invalid 'fmt ' header\n", filename);return NULL;}if(chunk2.subChunkId[0] != 'd' || chunk2.subChunkId[1] != 'a' || chunk2.subChunkId[2] != 't' || chunk2.subChunkId[3] != 'a'){printf("LoadWAV(%s): invalid 'data' header\n", filename);return NULL;}data = new unsigned char[chunk2.subChunkSize];fread(data, 1, chunk2.subChunkSize, fp);//set the dataif(chunk1.numChannels == 1){if(chunk1.bitsPerSample == 8)*format = AL_FORMAT_MONO8;if(chunk1.bitsPerSample == 16)*format = AL_FORMAT_MONO16;}if(chunk1.numChannels == 2){if(chunk1.bitsPerSample == 8)*format = AL_FORMAT_STEREO8;if(chunk1.bitsPerSample == 16)*format = AL_FORMAT_STEREO16;}*size = chunk2.subChunkSize;*freq = chunk1.sampleRate;return data;}void FreeWAV(unsigned char *data){if(data){delete [] data;data = NULL;}}...// here is how to upload to an OpenAL buffer:unsigned char *byteArray = NULL;byteArray = LoadWAV("Sounds/reactor.wav", &format, &size, &freq);alBufferData(buffer[0],format,(void*)byteArray,size,freq);FreeWAV(byteArray);OpenAL also needs to be initialized, so make sure to do that, generate your buffers/sources, and setup your listener stats as well.   ;  While that code might suit most standard WAV files, you'll find that even simple programs like Microsoft's SndRec32 will actually fill those files with JUNK, INFO or FACT objects, which will cause issues when reading those files with your code.It's easy enough to fix though, the first thing you do is confirm it's a RIFF file format (check the RIFF header), then keep skipping the sub chunks that don't use the WAVE identifier, then read the wave header, then skip any more sub chunks that don't use the DATA identifier, and then read the data.You can also compare memory with memcmp() instead of using a giant if statement, like this: memcmp("RIFF",riff.riff,4).Also, when you're freeing the memory allocated, you're also just clearing the local pointer, rather than the pointer passed to the function (you'll need to use a pointer pointer).   ;  Good call on both accounts. I'm using memcmp now, and all the code above has been integrated into a constructor for my Sound class making that data pointer a local pointer to that constructor.I found some more information on subchunks. At the moment, I cannot test wavs with invalid sub chunk data because I do not the means to generate it. I did some more research, and it appears that there sub chunks can have an arbitrary amount of data associated with them. Is this correct? If so, I'll have to manually check the chunk header and size, then skip past the rest of the chunk. I'll look into it late when I'm back.   ;  RIFF files have a fairly simple format.You've got a header, which consists of a 4 byte identifier ("RIFF"), 32 bit integer value for the size, and then another 4 byte identifier that specifies the type of file it is ("WAVE" for WAV audio files, "AVI " for video files). The size should tell you how much memory you'd need to allocate to buffer the rest of the file - you'll find Microsoft's software will usually depend on this to be accurate, just like when specifying bitmap headers (it doesn't mean your code has to follow that requirement though).Then you've got all of the chunks, and each chunk has a header, which consists of another 4 byte identifier and 32 bit integer for the size. The size basically tells you how much data/text/etc. follows the chunk's header.All you need to do is check the initial header (to confirm it's a RIFF file format, and if so, what type). Then you need to find the next important header (the format header "fmt "), and then you've got the audio format. After that, the only other useful thing you'll need from the file is the data chunks (which obviously follow the headers with the "data" identifiers). You can usually read the chunk headers, and if they're of no use to you, just skip 'size' bytes further through the file and read the next one.   