I wrote a class for loading wav files (currently only PCM ones).
It works for some files (testing with the ones for the August08 sdk in samples/media/wav), but for others it seems to corrupt something and the resulting sound data just produces a continous noise (I know my playback works fine since if i use the dx SDK's CWaveFile class it works fine...).
One of the files doesnt even load. I know for this one its because theres a "PAD " section between "fmt " and "data", but having looked over the files in a hex editor none of the other files do. This file also has a "fmt " size of 40 bytes with the first 2 (the ones that define the format I thought?) being 65534, however the CWaveFile class loads it fine, so it must be PCM??
They all work fine with the CWaveFile class...
class SoundData
{
public:
WAVEFORMATEX * GetFormat(){return &format;}
unsigned char* GetData() {return data;}//PCM, ADPCM or xWMA supported
unsigned GetSize() {return size;}
virtual ~SoundData(){}
protected:
unsigned char *data;
unsigned size;
WAVEFORMATEX format;
};
class Wav : public SoundData
{
public:
Wav(const std::string &file);
virtual ~Wav();
private:
void LoadPCM(std::ifstream &file);
};
Wav::Wav(const std::string &fileName)
{
std::ifstream file(fileName.c_str(), std::ios::in | std::ios::binary);
//check this is really a wave
char id[4];
file.read(id, 4);
if(strcmp(id,"RIFF")==0)
throw std::string("Not a media file");
//skip over the next 4 bytes
file.seekg(4,std::ios::cur);
//make sure its wave
file.read(id, 4);
if(strcmp(id,"WAVE")==0)
throw std::string("Not a wave file");
//skip over "fmt "
file.seekg(4,std::ios::cur);
//get format chunk size and format tag
file.read((char*)&format.cbSize, sizeof(unsigned));
file.read((char*)&format.wFormatTag, sizeof(unsigned short));
//decide what format we have
switch(format.wFormatTag)
{
case 1:
LoadPCM(file);
break;
default:
{
std::stringstream ss;
ss << "Unknown wave format: " << format.wFormatTag;
std::string str = ss.str();
throw str;
}
}
file.close();
//done
std::cout << "Loaded file:\n";
std::cout << "\tChannels: " << format.nChannels << "\n";
std::cout << "\tSample Rate: " << format.nSamplesPerSec << "\n";
std::cout << "\tBits per Sample: " << format.wBitsPerSample << "\n";
std::cout << "\tBlock Align: " << format.nBlockAlign << "\n";
std::cout << "\tBytes per second: " << format.nAvgBytesPerSec << "\n";
std::cout << "\tData Size: " << size << "\n";
std::cout << std::endl;
};
void Wav::LoadPCM(std::ifstream &file)
{
if(format.cbSize < 16)
{
std::stringstream ss;
ss << "Unknown format size... less than 16: " << format.cbSize;
throw std::string(ss.str());
}
//----FORMAT CHUNK----///
//we already have format tag + size
//channels
file.read((char*)&format.nChannels, sizeof(unsigned short));
file.read((char*)&format.nSamplesPerSec, sizeof(unsigned));
file.read((char*)&format.nAvgBytesPerSec, sizeof(unsigned));
file.read((char*)&format.nBlockAlign, sizeof(unsigned short));
file.read((char*)&format.wBitsPerSample, sizeof(unsigned short));
//skip to end of format section
file.seekg(format.cbSize-16,std::ios::cur);//we only know how to read the first 16 bytes, so ignore the rest
//----DATA----//
char str[4];
//file.seekg(4,std::ios::cur);//skip over "data" string
file.read(str,4);
//data size
file.read((char*)&size, sizeof(unsigned));
data = new unsigned char[size*2];
//read in the entire data section
file.read((char*)data, size);
//done
}
Wav::~Wav()
{
delete[] data;
}