loading sound

Started by
5 comments, last by Buckeye 15 years, 10 months ago
im haveing a problem loading a wav file i can get it to load but there just seems to be a little bit of garbage data at the begining of the sound so i hacked the code a bit and it seems to work but i want to do it the right way will somebody help me. this code is all from How to Load a Wave File by Nathan "nPawn" Davidson i had to modifiy it a lot sorry i dont know how to post code fstream file; file.open(Path, ios::in | ios::binary); if(file) { char id[5], *sound_buffer; //four bytes to hold 'RIFF' DWORD size; //32 bit value to hold file size WORD 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 id[4] = '\0'; file.read(reinterpret_cast<char *>(&id[0]), sizeof(char) * 4); // --------------- UpperString(id); if (FindString(id, "RIFF")) { file.read(reinterpret_cast<char *>(&size), sizeof(DWORD)); // --------------- file.read(reinterpret_cast<char *>(&id[0]), sizeof(char) * 4); // --------------- UpperString(id); if (FindString(id, "WAVE")) { file.read(reinterpret_cast<char *>(&id[0]), sizeof(char) * 4); file.read(reinterpret_cast<char *>(&format_length), sizeof(DWORD)); file.read(reinterpret_cast<char *>(&format_tag), sizeof(WORD)); file.read(reinterpret_cast<char *>(&channels), sizeof(WORD)); file.read(reinterpret_cast<char *>(&sample_rate), sizeof(DWORD)); file.read(reinterpret_cast<char *>(&avg_bytes_sec), sizeof(DWORD)); file.read(reinterpret_cast<char *>(&block_align), sizeof(WORD)); file.read(reinterpret_cast<char *>(&bits_per_sample), sizeof(WORD)); file.read(reinterpret_cast<char *>(&id[0]), sizeof(char) * 4); // data corrupt file.read(reinterpret_cast<char *>(&data_size), sizeof(DWORD)); file.read(reinterpret_cast<char *>(&id[0]), sizeof(char) * 4); // this is hack file.read(reinterpret_cast<char *>(&id[0]), sizeof(char) * 4); // this is hack file.read(reinterpret_cast<char *>(&id[0]), sizeof(char) * 4); // this is hack file.read(reinterpret_cast<char *>(&id[0]), sizeof(char) * 4); // this is hack size -= 40 + 16; // have to use file size because data is corrupt (header + hack) sound_buffer = new char[size]; //set aside sound buffer space file.read(reinterpret_cast<char *>(&sound_buffer[0]), sizeof(char) * size); [Edited by - helpmenow on June 16, 2008 12:17:34 AM]
Advertisement
You can find the .wav format specifications on MSDN. There are several variants of the .wav header.

What you read in the "//data corrupt" line is the ExtraInformationSize field of the WAVEFORMATEX structure, indicating the number of additional bytes of data that follow the normal WAVEFORMATEX header fields. It is used for the WAVEFORMATEXTENSIBLE structure and houses 3 additional fields: number of valid bits per sample, a mask indicating which speakers the channels are mapped to and a GUID indicating the .wav's sub format.

That should do the trick:
file.read(reinterpret_cast<char *>(&id[0]), sizeof(char) * 4);file.read(reinterpret_cast<char *>(&format_length), sizeof(DWORD));file.read(reinterpret_cast<char *>(&format_tag), sizeof(WORD));file.read(reinterpret_cast<char *>(&channels), sizeof(WORD));file.read(reinterpret_cast<char *>(&sample_rate), sizeof(DWORD));file.read(reinterpret_cast<char *>(&avg_bytes_sec), sizeof(DWORD));file.read(reinterpret_cast<char *>(&block_align), sizeof(WORD)); file.read(reinterpret_cast<char *>(&bits_per_sample), sizeof(WORD));if(format_tag == WAVEFORMATPCM) {  // Skip format_length - 18 bytes  // These could have been used for whatever purpose} else if(format_tag == WAVEFORMATEXTENSIBLE) {  WORD validBitsPerSample;  DWORD chanelMaskFlags;  GUID subFormat;    file.read(reinterpret_cast<char *>(&validBitsPerSample), sizeof(WORD));  file.read(reinterpret_cast<char *>(&channelMaskFlagslength), sizeof(DWORD));  file.read(reinterpret_cast<char *>(&subFormat), sizeof(GUID));  // Skip format_length - 40 bytes  // These could have been used for whatever purpose  if(subFormat != KSDATAFORMAT_SUBTYPE_PCM) {    // Wave is compressed or doesn't contain PCM data    throw runtime_error("Unsupported .wav file format");  }} else {  // Wave is compressed or doesn't contain PCM data  throw runtime_error("Unsupported .wav file format");}
Professional C++ and .NET developer trying to break into indie game development.
Follow my progress: http://blog.nuclex-games.com/ or Twitter - Topics: Ogre3D, Blender, game architecture tips & code snippets.
Another example for PCM format.

struct WAVE_HEADER{	char           chHeaderChunkID[4];	long           lHeaderChunkSize;	char           chSubchunkID[4];	char           chFormatTag[4];	unsigned long  dwFormatChunkSize;	unsigned short wAudioFormat; //PCM için 1	unsigned short wChannels;	unsigned long  dwSamplesPerSec;	unsigned long  dwAvgBytesPerSec;	unsigned short wBlockAlign;	unsigned short wBitsPerSample;	char           chDataChunkID[4];	unsigned long  dwDataChunkSize;};char *buff;FILE * fp;fp=fopen("c:\\a.wav","rb"); fread(&WaveHeader,sizeof(WAVE_HEADER),1,fp);buff=new char[WaveHeader.dwDataChunkSize];fread(buff,WaveHeader.dwDataChunkSize,1,fp);


@3ddreams: That's very scary code. Some suggestions:

- Without #pragma pack, you're ignoring alignment issues which may cause the offsets of your struct members to no longer match the file format.

- There's no guarantee the 'fmt ' chunk comes directly after the file header. And no guarantee that the 'data' chunk comes directly after the 'fmt ' chunk. There are lots of variations of the .wav format with additional tags out there.

- You are assuming all .wav files use WAVEFORMATEX. Windows 2000 introduced an new format called WAVEFORMATEXTENSIBLE that doesn't match your structure and would result in your dwDataChunkSize containing garbage. This page has some wave files using the new format for testing: Wave File Examples.
Professional C++ and .NET developer trying to break into indie game development.
Follow my progress: http://blog.nuclex-games.com/ or Twitter - Topics: Ogre3D, Blender, game architecture tips & code snippets.
I show olny an example one of wave formats. This is not constant way for loading wave files. But if file format is constant this code works.
ok cygon ive checked your code out and i dont know where the WAVEFORMATPCM is defined i would like to try it out but since i cant guess what value it is i need to know a header file or something your code seems like it would work though
I believe it's actually WAVE_FORMAT_PCM, in mmreg.h or mmsystem.h.

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

This topic is closed to new replies.

Advertisement