Tricks of the Windows Game Programming Gurus:Sounding Off with DirectSound and DirectMusic

All ITKnowledge Source Code Search Tips Advanced Search |

| Tricks of the Windows Game Programming Gurus by Andre LaMothe Sams, Macmillan Computer Publishing ISBN: 0672313618 Pub Date: 09/27/99

Search this book:

Previous | Table of Contents | Next

#### Initializing COM

First you have to initialize COM with a call to `CoInitialize()`:

    // initialize COM

    if (FAILED(CoInitialize(NULL)))

       {

       // Terminate the application.

       return(0);

       }   // end if

This should happen at the beginning of your application, before you make any direct COM calls. If you have other pure COM calls and already have called it, don’t worry about it.

#### Creating the Performance

The next step is to create the master interface, which is the DirectMusic performance. Creation of this interface will also create an internal IDirectMusic interface, but you won’t need it, so it’s hidden away. To create an interface based on pure COM, use the `CoCreateInstance()` function with the interface ID and the class ID, along with storage for the new interface pointer. Take a look at the following call:

    // the directmusic performance manager

    IDirectMusicPerformance    *dm_perf = NULL;

    // create the performance

    if (FAILED(CoCreateInstance(CLSID_DirectMusicPerformance,

                                NULL,

                                CLSCTX_INPROC,

                                IID_IDirectMusicPerformance,

                                (void**)&dm_perf)))

       {

       // return null

       return(0);

       } // end if

Looks a bit cryptic, but within reason. After this call, `dm_perf` is ready to go and you can make calls to the interface functions. The first call you need to make is to initialize the performance with `IDirectMusicPerformance::Init()`. Here’s the prototype for it:

    HRESULT Init(IDirectMusic** ppDirectMusic,

                 LPDIRECTSOUND pDirectSound,

                 HWND hWnd);

`ppDirectMusic` is the address of the IDirectMusic interface if you explicitly created one. You haven’t, so make it `NULL`. `pDirectSound` is a pointer to the `IDirectSound` object.

> Warning: This is important, so read carefully: If you want to use DirectSound and DirectMusic together, you must start up DirectSound first and then pass the IDirectSound object in the call to `Init()`. However, if you’re using DirectMusic alone, pass `NULL` and DirectMusic will create an IDirectSound object itself. This is needed because DirectMusic ultimately goes through DirectSound, as shown in Figure 10.14.

Figure 10.14 Relationship between DirectMusic and DirectSound.

The moral of the story is that you must pass the main DirectSound object pointer, or `NULL` if you aren’t using DirectSound. You’ll do the later for illustrative purposes. Finally, you must send the window handle. That’s pretty easy—here’s the code:

    // initialize the performance, check if directsound is on-line if so, use

    // the directsound object, otherwise create a new one

    if (FAILED(dm_perf->Init(NULL, NULL, main_window_handle)))

       {

       return(0);// Failure — performance not initialized

       } // end if

#### Adding a Port to the Performance

The next step to get DirectMusic up and running is creating a port for the digital data to be streamed to. If you like, you can query DirectMusic via enumeration for all valid ports, or you can just use the Microsoft Software Synthesizer as the default. That’s my style—keep it simple. To add a port to the performance, use the `IDirectMusicPerformance::AddPort()`. Its prototype is shown here:

    HRESULT AddPort(IDirectMusicPort* pPort);

Here, `pPort` is a pointer to a previously created port that you want to play from. However, just use `NULL` and the default software synthesizer will be used:

    // add the port to the performance

    if (FAILED(dm_perf->AddPort(NULL)))

       {

       return(0);// Failure — port not initialized

       } // end if

### Loading a MIDI Segment

The next step in setting up DirectMusic is creating a IDirectMusicLoader object so that you can load your MIDI files. This is accomplished with a low-level COM call again, but it’s not bad.

#### Creating the Loader

The following code creates the loader:

    // the directmusic loader

    IDirectMusicLoader*dm_loader = NULL;

    // create the loader to load object(s) such as midi file

    if (FAILED(CoCreateInstance(

              CLSID_DirectMusicLoader,

              NULL,

              CLSCTX_INPROC,

              IID_IDirectMusicLoader,

              (void**)&dm_loader)))

       {

       // error

       return(0);

       } // end if

Interestingly enough, a number of interfaces have been created internally—including an IDirectMusic object and an IDirectMusicPort object—and you didn’t even know. In most cases, you would never need to make calls to the functions of these interfaces, so it’s cool, baby.

Previous | Table of Contents | Next

Copyright © Macmillan Computer Publishing, Inc.

Products | Contact Us | About Us | Privacy | Ad Info | Home
Use of this site is subject to certain Terms & Conditions, Copyright © 1996-2000 EarthWeb Inc. All rights reserved. Reproduction in whole or in part in any form or medium without express written permission of EarthWeb is prohibited. Read EarthWeb's privacy statement.