Книга: DirectX 8 Programming Tutorial
A new class — CSound
A new class — CSound
Now that we have created and initialised DirectX Audio, we can load and play sounds and music. To help us with this, I have created a new class called CSound which is shown below. Take a quick look at the methods, and I'll explain how it works.
CSound::CSound() {
m_pDirectAudioPerformance = NULL;
m_pDirectAudioLoader = NULL;
m_pSegment = NULL;
m_pGraph = NULL;
m_pMediaControl = NULL;
m_pMediaPosition = NULL;
m_enumFormat = Unknown;
LogInfo("<li>Sound created OK");
}
void CSound::InitialiseForWavMidi(IDirectMusicPerformance8* pDirectAudioPerformance, IDirectMusicLoader8* pDirectAudioLoader) {
m_pDirectAudioPerformance = pDirectAudioPerformance;
m_pDirectAudioLoader = pDirectAudioLoader;
m_enumFormat = WavMidi;
}
void CSound::InitialiseForMP3() {
CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC, IID_IGraphBuilder, (void**)&m_pGraph);
m_pGraph->QueryInterface(IID_IMediaControl, (void**)&m_pMediaControl);
m_pGraph->QueryInterface(IID_IMediaPosition, (void**)&m_pMediaPosition);
m_enumFormat = MP3;
}
CSound::~CSound() {
Stop();
SafeRelease(m_pSegment);
SafeRelease(m_pGraph);
SafeRelease(m_pMediaControl);
SafeRelease(m_pMediaPosition);
LogInfo("<li>Sound destroyed OK");
}
bool CSound::LoadSound(const char* szSoundFileName) {
WCHAR wstrSoundPath[MAX_PATH];
CHAR strSoundPath[MAX_PATH];
switch(m_enumFormat) {
case MP3:
//Get the our applications "sounds" directory.
GetCurrentDirectory(MAX_PATH, strSoundPath);
strcat(strSoundPath, "Sounds");
strcat(strSoundPath, szSoundFileName);
//Convert the path to unicode.
MultiByteToWideChar(CP_ACP, 0, strSoundPath, –1, wstrSoundPath, MAX_PATH);
m_pGraph->RenderFile(wstrSoundPath, NULL);
break;
case WavMidi:
//Convert the filename to unicode.
MultiByteToWideChar(CP_ACP, 0, szSoundFileName, –1, wstrSoundPath, MAX_PATH);
//Load a sound
m_pDirectAudioLoader->LoadObjectFromFile(CLSID_DirectMusicSegment, IID_IDirectMusicSegment8, wstrSoundPath, (void**) &m_pSegment);
m_pSegment->Download(m_pDirectAudioPerformance);
break;
default:
return false;
}
return true;
}
bool CSound::Play(DWORD dwNumOfRepeats) {
switch(m_enumFormat) {
case MP3:
//Make sure that we are at the start of the stream
m_pMediaPosition->put_CurrentPosition(0);
//Play mp3
m_pMediaControl->Run();
break;
case WavMidi:
//Set the number of times the sound repeats
m_pSegment->SetRepeats(dwNumOfRepeats); //To loop the sound forever, pass in DMUS_SEG_REPEAT_INFINITE
//Play the loaded sound
m_pDirectAudioPerformance->PlaySegmentEx(m_pSegment, NULL, NULL, 0, 0, NULL, NULL, NULL);
break;
default:
return false;
}
return true;
}
bool CSound::Stop() {
switch(m_enumFormat) {
case MP3:
m_pMediaControl->Stop();
break;
case WavMidi:
//Stop the loaded sound
m_pDirectAudioPerformance->StopEx(m_pSegment, 0, 0);
break;
default:
return false;
}
return true;
}
bool CSound::IsPlaying() {
switch(m_enumFormat) {
case MP3:
REFTIME refPosition;
REFTIME refDuration;
m_pMediaPosition->get_CurrentPosition(&refPosition);
m_pMediaPosition->get_Duration(&refDuration);
if (refPosition < refDuration) {
return true;
} else {
return false;
}
break;
case WavMidi:
if (m_pDirectAudioPerformance->IsPlaying(m_pSegment, NULL) == S_OK) {
return true;
} else {
return false;
}
break;
default:
return false;
}
}
So, how can I play a sound with CSound? Simple really, first create a new CSound object, then call either InitialiseForWavMidi or InitialiseForMP3 depending on what type of sound you want to play. Next, call LoadSound which is where you specify which file to play. Finally, call Play to play the sound that you have loaded. That's it! There are also two other methods: Stop which will stop the sound from playing and IsPlaying which tells you if a sound is playing or not. Below is a brief explanation of how each function works.
InitialiseForWavMidi
InitialiseForWavMidi initialises the CSound object for playing wav or midi files. The two parameters are the performance and loader pointers that we created earlier in CGame. These pointers are then saved as member variables for later use. We also set the format of this CSound object to WavMidi.
InitialiseForMP3
InitialiseForMP3 initialises the CSound object for playing mp3 files. There are no parameters. InitialiseForMP3 uses CoCreateInstance to create a DirectShow filter graph manager object. We can use CoCreateInstance here because CoInitialize has already been called from our CGame constructor. From the filter graph manager object we use the QueryInterface method to create two other objects: a media control object and a media position object. These three pointers are saved as member variables for later use. We also set the format of this CSound object to MP3.
LoadSound
Once we have initialised the CSound object, we can use LoadSound to load a given file. The single parameter of LoadSound is the filename of the sound to load. This is not a path because all sounds will be loaded from the Sounds folder which is inside our project folder.
If the format of this CSound object is MP3, we first build up the full path of the file and convert it to a unicode string. Next, all we need to do is call the RenderFile method of the filter graph manager to construct a filter graph that will play the specified file.
If the format of this CSound object is WavMidi, we first convert the filename passed into a unicode string. Next we call LoadObjectFromFile which loads the file and returns a segment pointer. Lastly, we call the Download method of our segment which downloads the band data to the performance.
We are now ready to start playing sounds.
Play
Once a file has been loaded, we can play it. This single parameter of the Play method is optional (default is 0) and is the number of times you would like the sound to repeat. This parameter is only used if you are playing wav or midi files.
If the format of this CSound object is MP3, we first make sure that we are at the start of the stream by calling the put_CurrentPosition method of the media position object that we created earlier. Once this is done, we play the mp3 by calling the Run method of the media control object.
If the format of this CSound object is WavMidi, we first set the number of times that the sound should repeat. Then we play the loaded segment by calling the PlaySegmentEx method. If you would like the sound to repeat forever, pass in the constant DMUS_SEG_REPEAT_INFINITE.
Stop
This very simply stops the sound from playing. We use the Stop method of the media control object to stop the sound if it's an mp3 file. If it's a wav or midi file we simply call the StopEx method of the perfomance object passing in the segment to stop.
IsPlaying
Finally, the IsPlaying method will return true if the sound is playing and false if it is not. If the file is an mp3, we get the current position that playback has reached and the total duration of the track. If the current position is not at the end, then we must still be playing the sound. If the file is a wav or midi, we simply use the IsPlaying method of the performance object passing in the segment to check.
- State NEW packets but no SYN bit set
- 2. How to Apply These Terms to Your New Programs
- Операция new
- Usenet Network Newsgroups
- The Pan News Client Newsreader
- Adding New Users
- Installing the New Drive
- Mounting the New Partition and Populating It with the Relocated Files
- Usenet Newsgroups
- Linux News and Developments
- 5.3.2 Creating and Compiling a New File
- 5.3.1. New Hardware