DirectSound: Loadng a WAV file to a buffer.

Started by
8 comments, last by datadawgx 19 years, 6 months ago
hey guys. what are the key functions ill need to load a WAV file from a path into a static buffer? i cant find in the directx 9 sdk docs what to do. VB has CreateSoundBufferFromFile, am i looking for something similar? any help you guys can provide would help. im not using DirectMusic, and id appreciate a tutorial that is comprehensive to getting a wav file loaded and playing with DirectSound. im using dx8.
Advertisement
just to clarify, i have created a WAVEFORMATEX and DSBUFFERDESC structures already. and i have a buffer pointer, and i have a path. thx
ive spent all day reviewing the few examples of direct sound initialization, loading, and playback i can find on gd.net and through google searchs. everyone uses their own object oriented systems that bury the detail im looking for. every single tutorial is like "the code for doing this is really long and hard to undetstand, so we/I did it for you! cut and paste this..."

does ANYONE have a straight forward way to load a WAV file into a buffer? static, streaming, anything.

is directmusic this much trouble?
i guess this isnt a very popular subject. i understand.

im going to stop trying to reinvent the wheel and im going to use the sound system used in dsutil.h and dsutil.cpp. they do what im trying to do.
The problem of loading a wave file into a static buffer is that you have to know about the wavefile. When you use Disrect Sound in low level (like I do) with no classes to bury all the dirty work, you have to set all the features of your buffer. For example, stereo, mono, 8 bit, 16 bit, sample rate, etc. There is a bunch of junk.

So at the header of every WAV file is all that junk. So you have to read in the wave file, examine the header, format your DirectSound buffers accordingly, and then from the header find where the actual data starts. Once you have your buffers formatted properly, you can read in the data and start the old 'Play()' function.

That's a lot of annoying work. I do not know the details of the WAV file header. But all classes which read in a wave file and play them in a Direct Sound buffer have to go through all those stages.

The only addition when considering streaming data is that you have to set up some kind of notification (be careful...put in the write flags when you create your buffer) that will signal your write thread to load more data into the DS buffer. You have to do this far enough ahead of time so that you don't disrupt the flow. That also means keeping track of where you are in the file so you can read the next bunch of data.

Hope this makes sense.

Brian

PS I have not looked at this site for a couple of months. So I just saw your message today.
Brian Reinhold
Opps! A confusing typo:

I meant "put in the CORRECT flags" not "put in the write flags" in that latter paragraph. That typo could really lead to confusion!

Brian
Brian Reinhold
this is what i use, anyway..

Sound::Sound(String filename, DWORD flags){	m_pDSB=NULL;	m_BufferSize=0;	m_CreationFlags=0;	m_looping=0;	if(flags & DSBCAPS_CTRL3D) RuntimeError("DSBCAPS_CTRL3D is not a valid flag for 2D sounds!");	filename=AbsolutePath(filename);	File* f=ReadFile(filename);	if(!f) { RuntimeError("Could not open WAV file!"); }	String sig=ReadCharacters(f,4);	if(sig!="RIFF") { CloseFile(f); RuntimeError("File is not a valid WAV file"); }	SeekFile(f,8);	sig=ReadCharacters(f,4);	if(sig!="WAVE") { CloseFile(f); RuntimeError("File is not a valid WAV file"); }	sig=ReadCharacters(f,4);	if(sig!="fmt ") { CloseFile(f); RuntimeError("File is not a valid WAV file"); }	SeekFile(f,20);	int type=ReadShort(f);	if(type!=0x0001) { CloseFile(f); RuntimeError("File is some stupid compressed WAV that\nI don't feel like bothering with."); }		WORD channels=ReadShort(f);	if(channels>2) { CloseFile(f); RuntimeError("File is a WAV with more than 2 channels.\nGo make it stereo."); }	WAVEFORMATEX wave;	ZeroMemory(&wave,sizeof(wave));	wave.wFormatTag=WAVE_FORMAT_PCM;	wave.nChannels=channels;	wave.nSamplesPerSec=ReadInt(f); ReadInt(f); ReadShort(f);	wave.wBitsPerSample=ReadShort(f);	if(!(wave.wBitsPerSample==8 || wave.wBitsPerSample==16))	{		CloseFile(f);		RuntimeError("WAV file is not a valid bitrate (8 or 16)");	}	wave.nBlockAlign=(wave.nChannels*wave.wBitsPerSample)/8;	wave.nAvgBytesPerSec=wave.nSamplesPerSec*wave.nBlockAlign;	sig=ReadCharacters(f,4);	if(sig!="data") { CloseFile(f); RuntimeError("File is not a valid WAV file"); }	DSBUFFERDESC desc;	ZeroMemory(&desc,sizeof(desc));	desc.dwSize=sizeof(desc);	desc.dwFlags=m_CreationFlags=flags|DSBCAPS_GETCURRENTPOSITION2|DSBCAPS_LOCDEFER;	desc.dwBufferBytes=m_BufferSize=ReadInt(f);	desc.lpwfxFormat=&wave;	HRESULT hr;	if(FAILED(hr=gpDSound->CreateSoundBuffer(&desc,&m_pDSB,NULL)))		{ CloseFile(f); DXRuntimeError("Could not create sound buffer!",hr); }	unsigned char* data;	DWORD size;	if(FAILED(hr=m_pDSB->Lock(0,0,(void**)&data,&size,NULL,0,DSBLOCK_ENTIREBUFFER)))		{ CloseFile(f); DXRuntimeError("Could not lock sound buffer",hr); }	ReadPtr(f,data,size);	CloseFile(f);	if(FAILED(hr=m_pDSB->Unlock(data,size,NULL,0)))		DXRuntimeError("Could not unlock sound buffer",hr);	SoundVec.push_back(this);}


there are some proprietary functions in there (namely, my File functions and my RuntimeError() function) but you get the idea. most of my file functions are just very thin wrappers over the slightly lower-level fopen/fread functions. WAV files are not really that complicated.. it's just the sheer number of different types that you have to deal with that makes it annoying.

this particular function will only load 8- or 16-bit, mono or stereo WAVs, which are proabably 99.999% of the WAVs you'll come across. it also only handles WAVs that store their data in one big chunk - no DATA and SLNT chunks. and no compression either.
_______________________________________________________________________Hoo-rah.
Hey, how did you get your code post to show up in that nifty scrollable highlighted text box..?

Just wondering. Its a great way to post code so people don't have to scroll to heck and back to get to the next reply, and to separate msg from code...

-- ******** The source of all my problems is in the source ******** --
{source} and {/source}, but use square brackets [ ] instead of the curly ones { }. :)
_______________________________________________________________________Hoo-rah.
ill give these ideas a try soon. it doesnt look as hard as i thought it would be

This topic is closed to new replies.

Advertisement