}
So now we have an Earth that you can control.
In this tutorial we've seen how to use the mouse and keyboard via DirectInput. We've used the data from these input devices to control elements in our scene. The next thing to do is add some sound and music to our application, we'll do this in the next tutorial.
DirectX Tutorial 13: Sounds and Music
In this tutorial we will learn how to play music and sounds with DirectX. We will use DirectX Audio to play wav and midi files, we will also use DirectShow to play mp3 files. In this tutorial we will have a simple application that plays a background track (in mp3 format) and we will allow the user to use the mouse to play some sound effects (in wav format) whenever they click on a coloured number. You can download the full source code by clicking the "Download Source" link above.
So far in our tutorials we have used Direct3D and DirectInput for graphics and user input. Now I'm going to introduce you to two more components of DirectX: DirectX Audio and DirectShow. We use DirectX Audio to play wav and midi audio files. We use DirectShow to play streaming media such as full motion video (avi) and high quality audio (mp3) files. In this tutorial we will only be looking at how to play mp3's with DirectShow.
So when should I use which type of file format? Well, that is largely a matter of personal preference. Before I tell you my preference, here is some information about each format.
Wav files
Wav files are pure, uncompressed digital audio. It is an actual, digital recording similar to that stored on a CD. Uncompressed digital audio is the only true "CD quality" audio. But wav files can be massive. Even a short track can take up 20 or 30 megabytes of space, often much more.
Midi files
Midi stands for "Musical Instrument Digital Interface". Midi files do not actually contain music recordings, instead they hold a set of instructions on how to play a tune. Midi files are very small which is good if you plan to have a downloadable version of your game on a website. The quality of playback dependents on the sound card of your user's machine. A Midi sequence that sounds great on a high-end card may sound terrible on a cheap one. Also, Midi is for instrumentals only, not vocals.
Mp3 files
As with wav files, mp3 files are actual digital recordings. But the major difference between mp3 and wav is that mp3 files are compressed, and are typically one-tenth the size of uncompressed files. Because mp3 files are compressed, they are a lossy format. This means that depending on how they are compressed, a certain degree of quality will be lost. However, you can still get "almost" CD quality audio from an mp3 file as long as the compression settings are right. Also, mp3 files are a "streaming media" that means that when they are played the whole track is not loaded at the start. Instead, only a part of the track is loaded from disk at a time as it is required.
My preference
I would say that you probably want to use mp3 or midi files for background music. Especially if you want your users to download you game from a website. Mp3 and midi files are both small and therefore good for long background tracks. I would then tend to use wav files for short sound effects like explosions and power-ups for that extra bit of quality. If file size is not a problem, then why not use wav files for all sounds and music?
Before we can start the actual coding, we need to add some new header and library files to our project. I've included the new header files in Game.h just below where I have included d3dx8.h. You can add the library files by going to Project > Settings… then on the Link tab, type the new library file names into the Object/Library Modules input box. The new files are listed below:
· dmusici.h
· dsound.h
· dshow.h
· dsound.lib
· strmiids.lib
To setup DirectX Audio we need to create two objects: the performance object and the loader object. The performance object is the top-level object in DirectX Audio, it handles the flow of data from the source to the synthesizer. The loader object loads the files (wav and midi) into sound segments that can be played later. We only need one of each of these objects for the whole application, so we will create them as member variables of our CGame class. Their definitions are shown below:
IDirectMusicPerformance8* m_pDirectAudioPerformance;
IDirectMusicLoader8* m_pDirectAudioLoader;
Before we can create our objects, we need to initialise the COM library. We need to do this because DirectX Audio is pure COM. Don't worry too much about what this means, all you need to do is call the CoInitialize function (shown below) before you can create the DirectX Audio objects. To keep it simple, this is done in the CGame constructor.
CoInitialize(NULL);
Now that we have initialised COM, we need to create and initialise our two DirectX Audio objects. To do this, we have a new method of CGame called InitialiseDirectAudio which is shown below. This method is called from our Initialise method, take a look at the code and I'll explain in a moment.
bool CGame::InitialiseDirectAudio(HWND hWnd) {
LogInfo("<br>Initialise DirectAudio:");
//Create the DirectAudio performance object
if (CoCreateInstance(CLSID_DirectMusicPerformance, NULL, CLSCTX_INPROC, IID_IDirectMusicPerformance8, (void**) &m_pDirectAudioPerformance) != S_OK) {
LogError("<li>Failed to create the DirectAudio perfomance object.");
return false;
} else {
LogInfo("<li>DirectAudio perfomance object created OK.");
}
//Create the DirectAudio loader object
if (CoCreateInstance(CLSID_DirectMusicLoader, NULL, CLSCTX_INPROC, IID_IDirectMusicLoader8, (void**) &m_pDirectAudioLoader) != S_OK) {
LogError("<li>Failed to create the DirectAudio loader object.");
return false;
} else {
LogInfo("<li>DirectAudio loader object created OK.");
}
//Initialise the performance object
if (FAILED(m_pDirectAudioPerformance->InitAudio(NULL, NULL, hWnd, DMUS_APATH_SHARED_STEREOPLUSREVERB, 64, DMUS_AUDIOF_ALL, NULL))) {
LogError("<li>Failed to initialise the DirectAudio perfomance object.");
return false;
} else {
LogInfo("<li>Initialised the DirectAudio perfomance object OK.");
}
//Get the our applications "sounds" directory.
CHAR strSoundPath[MAX_PATH];
GetCurrentDirectory(MAX_PATH, strSoundPath);
strcat(strSoundPath, "\\Sounds");
//Convert the path to unicode.
WCHAR wstrSoundPath[MAX_PATH];
MultiByteToWideChar(CP_ACP, 0, strSoundPath, –1, wstrSoundPath, MAX_PATH);
//Set the search directory.
if (FAILED(m_pDirectAudioLoader->SetSearchDirectory(GUID_DirectMusicAllTypes, wstrSoundPath, FALSE))) {
LogError("<li>Failed to set the search directory '%s'.", strSoundPath);