The DirectMusic API Rapper
Did you get my joke with the title? The DirectMusic API is even simpler than the DirectSound API. I have created functions to initialize DirectMusic, create all the COM objects for you, and enable you to focus on loading and playing MIDI files. Here's the basic functionality list:
Initialize and shut down DirectMusic with single calls
Load MIDI files off disk
Play a MIDI file
Stop a MIDI that is currently playing
Test the play status of a MIDI segment
Automatically connect to DirectSound if DirectSound has previously been initialized
Delete MIDI segments from memory
Let's take a look at each function one by one.
NOTE
Unless otherwise stated, all functions return TRUE (1) if successful, and FALSE (0) if not.
Function Prototype:
int DMusic_Init(void);
Purpose:
Dmusic_Init() initializes DirectMusic and creates all necessary COM objects. You make this call before any other calls to the DirectMusic library. In addition, if you want to use DirectSound, make sure to initialize DirectSound before calling DMusic_Init(). Here's an example of using the function:
Example:
if (!DMusic_Init()) { /* error */ }
Function Prototype:
int DMusic_Shutdown(void);
Purpose:
DMusic_Shutdown() shuts down the entire DirectMusic engine. It releases all COM objects, in addition to unloading all loaded MIDI segments. Call this function at the end of your application, but before the call to shutdown DirectSoundif you have DirectSound support. Here's an example:
Example:
if (!DMusic_Shutdown()) { /* error */ } // now shutdown DirectSound...
Function Prototype:
int DMusic_Load_MIDI(char *filename);
Purpose:
DMusic_Load_MIDI() loads a MIDI segment into memory and allocates a record in the midi_ids[] array. The function returns the ID of the loaded MIDI segment, or 1 if not successful. The returned ID is used as a reference for all other calls. Here's an example of loading a couple of MIDI files:
Example:
// load files int explode_id = DMusic_Load_MIDI("explosion.mid"); int weapon_id = DMusic_Load_MIDI("laser.mid"); // test files if (explode_id == -1 || weapon_id == -1) { /* there was a problem */ }
Function Prototype:
int DMusic_Delete_MIDI(int id);
Purpose:
DMusic_Delete_MIDI() deletes a previously loaded MIDI segment from the system. Simply supply the ID to delete. Here's an example of deleting the previously loaded MIDI files in the preceding example:
Example:
if (!DMusic_Delete_MIDI(explode_id) || !DMusic_Delete_MIDI(weapon_id) ) { /* error */ }
Function Prototype:
int DMusic_Delete_All_MIDI(void);
Purpose:
DMusic_Delete_All_MIDI() simply deletes all MIDI segments from the system in one call. Here's an example:
Example:
// delete both of our segments if (!DMusic_Delete_All_MIDI()) { /* error */ }
Function Prototype:
int DMusic_Play(int id);
Purpose:
DMusic_Play() plays a MIDI segment from the beginning. Simply supply the ID of the segment you want to play. Here's an example:
Example:
// load file int explode_id = DMusic_Load_MIDI("explosion.mid"); // play it if (!DMusic_Play(explode_id)) { /* error */ }
Function Prototype:
int DMusic_Stop(int id);
Purpose:
DMusic_Stop() stops a currently playing segment. If the segment is already stopped, the function has no effect. Here's an example:
Example:
// stop the laser blast if (!DMusic_Stop(weapon_id)) { /* error */ }
Function Prototype:
int DMusic_Status_MIDI(int id);
Purpose:
DMusic_Status() tests the status of any MIDI segment based on its ID. The status codes are as follows:
#define MIDI_NULL 0 // this midi object is not loaded #define MIDI_LOADED 1 // this midi object is loaded #define MIDI_PLAYING 2 // this midi object is loaded and playing #define MIDI_STOPPED 3 // this midi object is loaded, but stopped
Here's an example of changing state based on a MIDI segment completing:
Example:
// main game loop while(1) { if (DMusic_Status(explode_id) == MIDI_STOPPED) game_state = GAME_MUSIC_OVER; } // end while
That's it for the DirectSound and DirectMusic APIs. As I said, later in the chapter you will see demo examples of both, but for now, let's continue with putting together the final T3D Game Console and bring our virtual computer interface all together in one glorious ...Whoooaaa! I'm getting a little carried away here. I'm mean, let's finish up.
The T3DLIB Library at a Glance
At this point, we have three main .CPP|H modules that make up the T3D library:
T3DLIB1.CPP|HDirectDraw plus graphics algorithms
T3DLIB2.CPP|HDirectInput
T3DLIB3.CPP|HDirectSound & DirectMusic
Keep this in mind when compiling programs. If you want to compile a demo program, call it DEMOX_Y.CPP, and then look at its .H includes. If you see it include any of the preceding related .H library modules, you'll obviously need to include the .CPP files, too.
To compile any of the programs, make sure to include both the library source files, as well as all the DirectX .LIB filesand please, for the sake of God, set your compiler to Win32 .EXE as the target!