loading sound
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]
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:
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");}
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.
- 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.
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.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement