Microsoft DirectX 8.1 (C++) |
This topic explains how to load data from wave files into DirectSound buffers without the help of the DirectMusic loader and performance. Most applications do not need to work directly with wave data and buffers. For the preferred method of loading and playing waves, see Loading Audio Data and Playing Sounds.
Wave files are in the Resource Interchange File Format (RIFF), which consists of a variable number of chunks containing either header information (for example, the wave format of sound samples) or data (the samples themselves). The Win32 API supplies functions for opening and closing RIFF files, seeking chunks, and so on. The names of these functions all start with "mmio".
The DirectSound API does not include methods for handling wave files. However, the Dsutil.cpp file used by many of the SDK sample applications implements a CWaveFile class that has the following public methods:
The first step in reading a wave file is to call the CWaveFile::Open method. This verifies that the file is in RIFF format and gets information about the wave format. The parameters are the filename, NULL for the format, and the WAVEFILE_READ flag. The method returns an HRESULT.
The following code opens a wave file:
CWaveFile waveFile;
if (FAILED(waveFile.Open("mywave.wav", NULL, WAVEFILE_READ)))
{
waveFile.Close();
}
The application can now begin copying data from the file to a secondary sound buffer. Normally you don't create the sound buffer until you have obtained the format of the wave. The following code creates a
LPDIRECTSOUNDBUFFER lpdsbStatic;
DSBUFFERDESC dsbdesc;
memset(&dsbdesc, 0, sizeof(DSBUFFERDESC));
dsbdesc.dwSize = sizeof(DSBUFFERDESC);
dsbdesc.dwFlags = 0;
/* The wave format and size of the data chunk are stored in
// CWaveFile after CWaveFile::Open has been called.
dsbdesc.dwBufferBytes = waveFile.GetSize();
dsbdesc.lpwfxFormat = waveFile.m_pwfx;
// lpds is a valid IDirectSound8 pointer.
if FAILED(lpds->CreateSoundBuffer(&dsbdesc, &lpdsbStatic, NULL))
{
// Error handling.
.
.
.
}
Now the buffer can be filled with data. Because in this case the application is not streaming the data, the entire buffer is locked from the beginning. There is no wraparound, so only a single pointer and byte count are required.
LPVOID lpvAudio1;
DWORD dwBytes1;
if FAILED(lpdsbStatic->Lock(
0, // Offset of lock start.
0, // Size of lock; ignored in this case.
&lpvAudio1, // Address of lock start.
&dwBytes1, // Number of bytes locked.
NULL, // Wraparound start; not used.
NULL, // Wraparound size; not used.
DSBLOCK_ENTIREBUFFER))
{
// Error handling.
.
.
.
}
The CWaveFile::Read method can then be used to fill the buffer, as follows:
DWORD dwBytesRead;
waveFile.Read((BYTE*)lpvAudio1, dwBytes1, &dwBytesRead);
Finally, the application unlocks the buffer and closes the wave file:
lpdsbStatic->Unlock(lpvAudio1, dwBytes1, NULL, 0);
waveFile.Close();
For a
For more information on streaming, see Using Streaming Buffers and Play Buffer Notification.
See the sample applications in the DirectX SDK installation for more examples of using the CWaveFile class.