t3dlib3.cpp
上传用户:husern
上传日期:2018-01-20
资源大小:42486k
文件大小:22k
源码类别:

游戏

开发平台:

Visual C++

  1. // T3DLIB3.CPP - Game Engine Part III, sound & music
  2.  
  3. // INCLUDES ///////////////////////////////////////////////
  4. #define WIN32_LEAN_AND_MEAN  
  5. #include <windows.h>   // include important windows stuff
  6. #include <windowsx.h> 
  7. #include <mmsystem.h>
  8. #include <objbase.h>
  9. #include <iostream.h> // include important C/C++ stuff
  10. #include <conio.h>
  11. #include <stdlib.h>
  12. #include <malloc.h>
  13. #include <memory.h>
  14. #include <string.h>
  15. #include <stdarg.h>
  16. #include <stdio.h>
  17. #include <math.h>
  18. #include <io.h>
  19. #include <fcntl.h>
  20. #include <direct.h>
  21. #include <wchar.h>
  22. #include <ddraw.h>  // directX includes
  23. #include <dsound.h>
  24. #include <dmksctrl.h>
  25. #include <dmusici.h>
  26. #include <dmusicc.h>
  27. #include <dmusicf.h>
  28. #include "T3DLIB3.H"
  29. // DEFINES ////////////////////////////////////////////////
  30. // TYPES //////////////////////////////////////////////////
  31. // PROTOTYPES /////////////////////////////////////////////
  32. // EXTERNALS /////////////////////////////////////////////
  33. extern HWND main_window_handle;     // access to main window handle in main module
  34. // GLOBALS ////////////////////////////////////////////////
  35. // directsound stuff
  36. LPDIRECTSOUND lpds = NULL;    // directsound interface pointer
  37. DSBUFFERDESC dsbd;           // directsound description
  38. DSCAPS dscaps;         // directsound caps
  39. HRESULT dsresult;       // general directsound result
  40. DSBCAPS dsbcaps;        // directsound buffer caps
  41. LPDIRECTSOUNDBUFFER lpdsbprimary = NULL;   // the primary mixing buffer
  42. pcm_sound sound_fx[MAX_SOUNDS];    // the array of secondary sound buffers
  43. WAVEFORMATEX pcmwf;          // generic waveformat structure
  44. // direct music globals
  45. IDirectMusicPerformance    *dm_perf = NULL;    // the directmusic performance manager 
  46. IDirectMusicLoader         *dm_loader = NULL;  // the directmusic loader
  47. // this hold all the directmusic midi objects
  48. DMUSIC_MIDI                dm_midi[DM_NUM_SEGMENTS];
  49. int dm_active_id = -1;     // currently active midi segment
  50. // FUNCTIONS //////////////////////////////////////////////
  51. int DSound_Load_WAV(char *filename, int control_flags)
  52. {
  53. // this function loads a .wav file, sets up the directsound 
  54. // buffer and loads the data into memory, the function returns 
  55. // the id number of the sound
  56. HMMIO  hwav;    // handle to wave file
  57. MMCKINFO parent,  // parent chunk
  58.                 child;   // child chunk
  59. WAVEFORMATEX    wfmtx;   // wave format structure
  60. int sound_id = -1,       // id of sound to be loaded
  61. index;               // looping variable
  62. UCHAR *snd_buffer,       // temporary sound buffer to hold voc data
  63.       *audio_ptr_1=NULL, // data ptr to first write buffer 
  64.   *audio_ptr_2=NULL; // data ptr to second write buffer
  65. DWORD audio_length_1=0,  // length of first write buffer
  66.   audio_length_2=0;  // length of second write buffer
  67. // step one: are there any open id's ?
  68. for (index=0; index < MAX_SOUNDS; index++)
  69. {
  70.     // make sure this sound is unused
  71. if (sound_fx[index].state==SOUND_NULL)
  72.    {
  73.    sound_id = index;
  74.    break;
  75.    } // end if
  76. } // end for index
  77. // did we get a free id?
  78. if (sound_id==-1)
  79. return(-1);
  80. // set up chunk info structure
  81. parent.ckid      = (FOURCC)0;
  82. parent.cksize      = 0;
  83. parent.fccType     = (FOURCC)0;
  84. parent.dwDataOffset = 0;
  85. parent.dwFlags = 0;
  86. // copy data
  87. child = parent;
  88. // open the WAV file
  89. if ((hwav = mmioOpen(filename, NULL, MMIO_READ | MMIO_ALLOCBUF))==NULL)
  90.     return(-1);
  91. // descend into the RIFF 
  92. parent.fccType = mmioFOURCC('W', 'A', 'V', 'E');
  93. if (mmioDescend(hwav, &parent, NULL, MMIO_FINDRIFF))
  94.     {
  95.     // close the file
  96.     mmioClose(hwav, 0);
  97.     // return error, no wave section
  98.     return(-1); 
  99.     } // end if
  100. // descend to the WAVEfmt 
  101. child.ckid = mmioFOURCC('f', 'm', 't', ' ');
  102. if (mmioDescend(hwav, &child, &parent, 0))
  103.     {
  104.     // close the file
  105.     mmioClose(hwav, 0);
  106.     // return error, no format section
  107.     return(-1); 
  108.     } // end if
  109. // now read the wave format information from file
  110. if (mmioRead(hwav, (char *)&wfmtx, sizeof(wfmtx)) != sizeof(wfmtx))
  111.     {
  112.     // close file
  113.     mmioClose(hwav, 0);
  114.     // return error, no wave format data
  115.     return(-1);
  116.     } // end if
  117. // make sure that the data format is PCM
  118. if (wfmtx.wFormatTag != WAVE_FORMAT_PCM)
  119.     {
  120.     // close the file
  121.     mmioClose(hwav, 0);
  122.     // return error, not the right data format
  123.     return(-1); 
  124.     } // end if
  125. // now ascend up one level, so we can access data chunk
  126. if (mmioAscend(hwav, &child, 0))
  127.    {
  128.    // close file
  129.    mmioClose(hwav, 0);
  130.    // return error, couldn't ascend
  131.    return(-1); 
  132.    } // end if
  133. // descend to the data chunk 
  134. child.ckid = mmioFOURCC('d', 'a', 't', 'a');
  135. if (mmioDescend(hwav, &child, &parent, MMIO_FINDCHUNK))
  136.     {
  137.     // close file
  138.     mmioClose(hwav, 0);
  139.     // return error, no data
  140.     return(-1); 
  141.     } // end if
  142. // finally!!!! now all we have to do is read the data in and
  143. // set up the directsound buffer
  144. // allocate the memory to load sound data
  145. snd_buffer = (UCHAR *)malloc(child.cksize);
  146. // read the wave data 
  147. mmioRead(hwav, (char *)snd_buffer, child.cksize);
  148. // close the file
  149. mmioClose(hwav, 0);
  150. // set rate and size in data structure
  151. sound_fx[sound_id].rate  = wfmtx.nSamplesPerSec;
  152. sound_fx[sound_id].size  = child.cksize;
  153. sound_fx[sound_id].state = SOUND_LOADED;
  154. // set up the format data structure
  155. memset(&pcmwf, 0, sizeof(WAVEFORMATEX));
  156. pcmwf.wFormatTag   = WAVE_FORMAT_PCM;  // pulse code modulation
  157. pcmwf.nChannels   = 1;                // mono 
  158. pcmwf.nSamplesPerSec  = 11025;            // always this rate
  159. pcmwf.nBlockAlign   = 1;                
  160. pcmwf.nAvgBytesPerSec = pcmwf.nSamplesPerSec * pcmwf.nBlockAlign;
  161. pcmwf.wBitsPerSample  = 8;
  162. pcmwf.cbSize   = 0;
  163. // prepare to create sounds buffer
  164. dsbd.dwSize = sizeof(DSBUFFERDESC);
  165. dsbd.dwFlags = control_flags | DSBCAPS_STATIC | DSBCAPS_LOCSOFTWARE;
  166. dsbd.dwBufferBytes = child.cksize;
  167. dsbd.lpwfxFormat = &pcmwf;
  168. // create the sound buffer
  169. if (FAILED(lpds->CreateSoundBuffer(&dsbd,&sound_fx[sound_id].dsbuffer,NULL)))
  170.    {
  171.    // release memory
  172.    free(snd_buffer);
  173.    // return error
  174.    return(-1);
  175.    } // end if
  176. // copy data into sound buffer
  177. if (FAILED(sound_fx[sound_id].dsbuffer->Lock(0,  
  178.       child.cksize,
  179.       (void **) &audio_ptr_1, 
  180.       &audio_length_1,
  181.       (void **)&audio_ptr_2, 
  182.       &audio_length_2,
  183.       DSBLOCK_FROMWRITECURSOR)))
  184.  return(0);
  185. // copy first section of circular buffer
  186. memcpy(audio_ptr_1, snd_buffer, audio_length_1);
  187. // copy last section of circular buffer
  188. memcpy(audio_ptr_2, (snd_buffer+audio_length_1),audio_length_2);
  189. // unlock the buffer
  190. if (FAILED(sound_fx[sound_id].dsbuffer->Unlock(audio_ptr_1, 
  191.     audio_length_1, 
  192.     audio_ptr_2, 
  193.     audio_length_2)))
  194.        return(0);
  195. // release the temp buffer
  196. free(snd_buffer);
  197. // return id
  198. return(sound_id);
  199. } // end DSound_Load_WAV
  200. ///////////////////////////////////////////////////////////
  201. int DSound_Replicate_Sound(int source_id)
  202. {
  203. // this function replicates the sent sound and sends back the
  204. // id of the replicated sound, you would use this function
  205. // to make multiple copies of a gunshot or something that
  206. // you want to play multiple times simulataneously, but you
  207. // only want to load once
  208. if (source_id!=-1)
  209.     {
  210.     // duplicate the sound buffer
  211.     // first hunt for an open id
  212.     for (int id=0; id < MAX_SOUNDS; id++)
  213.         {
  214.         // is this sound open?
  215.         if (sound_fx[id].state==SOUND_NULL)
  216.             {
  217.             // first make an identical copy
  218.             sound_fx[id] = sound_fx[source_id];
  219.             // now actually replicate the directsound buffer
  220.             if (FAILED(lpds->DuplicateSoundBuffer(sound_fx[source_id].dsbuffer,
  221.                                            &sound_fx[id].dsbuffer)))
  222.                 {
  223.                 // reset sound to NULL
  224.                 sound_fx[id].dsbuffer = NULL;
  225.                 sound_fx[id].state    = SOUND_NULL;
  226.                 // return error
  227.                 return(-1);
  228.                 } // end if
  229.             // now fix up id
  230.             sound_fx[id].id = id;
  231.             
  232.             // return replicated sound
  233.             return(id);
  234.             } // end if found
  235.   
  236.         } // end for id
  237.     } // end if
  238. else
  239.    return(-1);
  240.     
  241. // else failure
  242. return(-1);
  243. } // end DSound_Replicate_Sound
  244. //////////////////////////////////////////////////////////
  245. int DSound_Init(void)
  246. {
  247. // this function initializes the sound system
  248. static int first_time = 1; // used to track the first time the function
  249.                            // is entered
  250. // test for very first time
  251. if (first_time)
  252. {
  253. // clear everything out
  254. memset(sound_fx,0,sizeof(pcm_sound)*MAX_SOUNDS);
  255. // reset first time
  256. first_time = 0;
  257. // create a directsound object
  258. if (FAILED(DirectSoundCreate(NULL, &lpds, NULL)))
  259. return(0);
  260. // set cooperation level
  261. if (FAILED(lpds->SetCooperativeLevel((HWND)main_window_handle,DSSCL_NORMAL)))
  262. return(0);
  263. } // end if
  264. // initialize the sound fx array
  265. for (int index=0; index<MAX_SOUNDS; index++)
  266. {
  267. // test if this sound has been loaded
  268. if (sound_fx[index].dsbuffer)
  269. {
  270. // stop the sound
  271. sound_fx[index].dsbuffer->Stop();
  272. // release the buffer
  273. sound_fx[index].dsbuffer->Release();
  274. } // end if
  275. // clear the record out
  276. memset(&sound_fx[index],0,sizeof(pcm_sound));
  277. // now set up the fields
  278. sound_fx[index].state = SOUND_NULL;
  279. sound_fx[index].id    = index;
  280. } // end for index
  281. // return sucess
  282. return(1);
  283. } // end DSound_Init
  284. ///////////////////////////////////////////////////////////
  285. int DSound_Shutdown(void)
  286. {
  287. // this function releases all the memory allocated and the directsound object
  288. // itself
  289. // first turn all sounds off
  290. DSound_Stop_All_Sounds();
  291. // now release all sound buffers
  292. for (int index=0; index<MAX_SOUNDS; index++)
  293. if (sound_fx[index].dsbuffer)
  294. sound_fx[index].dsbuffer->Release();
  295. // now release the directsound interface itself
  296. if (lpds)
  297.    lpds->Release();
  298. // return success
  299. return(1);
  300. } // end DSound_Shutdown
  301. ///////////////////////////////////////////////////////////
  302. int DSound_Play(int id, int flags, int volume, int rate, int pan)
  303. {
  304. // this function plays a sound, the only parameter that 
  305. // works is the flags which can be 0 to play once or
  306. // DSBPLAY_LOOPING
  307. if (sound_fx[id].dsbuffer)
  308. {
  309. // reset position to start
  310. if (FAILED(sound_fx[id].dsbuffer->SetCurrentPosition(0)))
  311. return(0);
  312. // play sound
  313. if (FAILED(sound_fx[id].dsbuffer->Play(0,0,flags)))
  314. return(0);
  315. } // end if
  316. // return success
  317. return(1);
  318. } // end DSound_Play
  319. ///////////////////////////////////////////////////////////
  320. int DSound_Set_Volume(int id,int vol)
  321. {
  322. // this function sets the volume on a sound 0-100
  323. if (sound_fx[id].dsbuffer->SetVolume(DSVOLUME_TO_DB(vol))!=DS_OK)
  324. return(0);
  325. // return success
  326. return(1);
  327. } // end DSound_Set_Volume
  328. ///////////////////////////////////////////////////////////
  329. int DSound_Set_Freq(int id,int freq)
  330. {
  331. // this function sets the playback rate
  332. if (sound_fx[id].dsbuffer->SetFrequency(freq)!=DS_OK)
  333. return(0);
  334. // return success
  335. return(1);
  336. } // end DSound_Set_Freq
  337. ///////////////////////////////////////////////////////////
  338. int DSound_Set_Pan(int id,int pan)
  339. {
  340. // this function sets the pan, -10,000 to 10,0000
  341. if (sound_fx[id].dsbuffer->SetPan(pan)!=DS_OK)
  342. return(0);
  343. // return success
  344. return(1);
  345. } // end DSound_Set_Pan
  346. ////////////////////////////////////////////////////////////
  347. int DSound_Stop_Sound(int id)
  348. {
  349. // this function stops a sound from playing
  350. if (sound_fx[id].dsbuffer)
  351.    {
  352.    sound_fx[id].dsbuffer->Stop();
  353.    sound_fx[id].dsbuffer->SetCurrentPosition(0);
  354.    } // end if
  355. // return success
  356. return(1);
  357. } // end DSound_Stop_Sound
  358. ///////////////////////////////////////////////////////////
  359. int DSound_Delete_All_Sounds(void)
  360. {
  361. // this function deletes all the sounds
  362. for (int index=0; index < MAX_SOUNDS; index++)
  363.     DSound_Delete_Sound(index);
  364. // return success always
  365. return(1);
  366. } // end DSound_Delete_All_Sounds
  367. ///////////////////////////////////////////////////////////
  368. int DSound_Delete_Sound(int id)
  369. {
  370. // this function deletes a single sound and puts it back onto the available list
  371. // first stop it
  372. if (!DSound_Stop_Sound(id))
  373.    return(0);
  374. // now delete it
  375. if (sound_fx[id].dsbuffer)
  376.    {
  377.    // release the com object
  378.    sound_fx[id].dsbuffer->Release();
  379.    sound_fx[id].dsbuffer = NULL;
  380.    
  381.    // return success
  382.    return(1);
  383.    } // end if
  384. // return success
  385. return(1);
  386. } // end DSound_Delete_Sound
  387. ///////////////////////////////////////////////////////////
  388. int DSound_Stop_All_Sounds(void)
  389. {
  390. // this function stops all sounds
  391. for (int index=0; index<MAX_SOUNDS; index++)
  392. DSound_Stop_Sound(index);
  393. // return success
  394. return(1);
  395. } // end DSound_Stop_All_Sounds
  396. ///////////////////////////////////////////////////////////
  397. int DSound_Status_Sound(int id)
  398. {
  399. // this function returns the status of a sound
  400. if (sound_fx[id].dsbuffer)
  401. {
  402. ULONG status; 
  403. // get the status
  404. sound_fx[id].dsbuffer->GetStatus(&status);
  405. // return the status
  406. return(status);
  407. } // end if
  408. else // total failure
  409. return(-1);
  410. } // end DSound_Status_Sound
  411. ///////////////////////////////////////////////////////////
  412. int DMusic_Load_MIDI(char *filename)
  413. {
  414. // this function loads a midi segment
  415. DMUS_OBJECTDESC ObjDesc; 
  416. HRESULT hr;
  417. IDirectMusicSegment* pSegment = NULL;
  418. int index; // loop var
  419.  
  420. // look for open slot for midi segment
  421. int id = -1;
  422. for (index = 0; index < DM_NUM_SEGMENTS; index++)
  423.     {
  424.     // is this one open
  425.     if (dm_midi[index].state == MIDI_NULL)
  426.        {
  427.        // validate id, but don't validate object until loaded
  428.        id = index;
  429.        break;
  430.        } // end if
  431.     } // end for index
  432. // found good id?
  433. if (id==-1)
  434.    return(-1);
  435. // get current working directory
  436. char szDir[_MAX_PATH];
  437. WCHAR wszDir[_MAX_PATH]; 
  438. if(_getcwd( szDir, _MAX_PATH ) == NULL)
  439.   {
  440.   return(-1);;
  441.   } // end if
  442. MULTI_TO_WIDE(wszDir, szDir);
  443. // tell the loader were to look for files
  444. hr = dm_loader->SetSearchDirectory(GUID_DirectMusicAllTypes,wszDir, FALSE);
  445. if (FAILED(hr)) 
  446.    {
  447.    return (-1);
  448.    } // end if
  449. // convert filename to wide string
  450. WCHAR wfilename[_MAX_PATH]; 
  451. MULTI_TO_WIDE(wfilename, filename);
  452.  
  453. // setup object description
  454. DD_INIT_STRUCT(ObjDesc);
  455. ObjDesc.guidClass = CLSID_DirectMusicSegment;
  456. wcscpy(ObjDesc.wszFileName, wfilename );
  457. ObjDesc.dwValidData = DMUS_OBJ_CLASS | DMUS_OBJ_FILENAME;
  458.  
  459. // load the object and query it for the IDirectMusicSegment interface
  460. // This is done in a single call to IDirectMusicLoader::GetObject
  461. // note that loading the object also initializes the tracks and does 
  462. // everything else necessary to get the MIDI data ready for playback.
  463. hr = dm_loader->GetObject(&ObjDesc,IID_IDirectMusicSegment, (void**) &pSegment);
  464. if (FAILED(hr))
  465.    return(-1);
  466.  
  467. // ensure that the segment plays as a standard MIDI file
  468. // you now need to set a parameter on the band track
  469. // Use the IDirectMusicSegment::SetParam method and let 
  470. // DirectMusic find the trackby passing -1 (or 0xFFFFFFFF) in the dwGroupBits method parameter.
  471. hr = pSegment->SetParam(GUID_StandardMIDIFile,-1, 0, 0, (void*)dm_perf);
  472. if (FAILED(hr))
  473.    return(-1);
  474.   
  475. // This step is necessary because DirectMusic handles program changes and 
  476. // bank selects differently for standard MIDI files than it does for MIDI 
  477. // content authored specifically for DirectMusic. 
  478. // The GUID_StandardMIDIFile parameter must be set before the instruments are downloaded. 
  479. // The next step is to download the instruments. 
  480. // This is necessary even for playing a simple MIDI file 
  481. // because the default software synthesizer needs the DLS data 
  482. // for the General MIDI instrument set
  483. // If you skip this step, the MIDI file will play silently.
  484. // Again, you call SetParam on the segment, this time specifying the GUID_Download parameter:
  485. hr = pSegment->SetParam(GUID_Download, -1, 0, 0, (void*)dm_perf);
  486. if (FAILED(hr))
  487.    return(-1);
  488. // at this point we have MIDI loaded and a valid object
  489. dm_midi[id].dm_segment  = pSegment;
  490. dm_midi[id].dm_segstate = NULL;
  491. dm_midi[id].state       = MIDI_LOADED;
  492.  
  493. // return id
  494. return(id);
  495.  
  496. } // end DMusic_Load_MIDI
  497. //////////////////////////////////////////////////////////
  498. int DMusic_Play(int id)
  499. {
  500. // play sound based on id
  501. if (dm_midi[id].dm_segment && dm_midi[id].state!=MIDI_NULL)
  502.    {
  503.    // if there is an active midi then stop it
  504.    if (dm_active_id!=-1)
  505.        DMusic_Stop(dm_active_id);
  506.    // play segment and force tracking of state variable
  507.    dm_perf->PlaySegment(dm_midi[id].dm_segment, 0, 0, &dm_midi[id].dm_segstate);
  508.    dm_midi[id].state = MIDI_PLAYING;
  509.    // set the active midi segment
  510.    dm_active_id = id;
  511.    return(1);
  512.    }  // end if
  513. else
  514.     return(0);
  515. } // end DMusic_Play
  516. //////////////////////////////////////////////////////////
  517. int DMusic_Stop(int id)
  518. {
  519. // stop a midi segment
  520. if (dm_midi[id].dm_segment && dm_midi[id].state!=MIDI_NULL)
  521.    {
  522.    // play segment and force tracking of state variable
  523.    dm_perf->Stop(dm_midi[id].dm_segment, NULL, 0, 0);
  524.    dm_midi[id].state = MIDI_STOPPED;
  525.    // reset active id
  526.    dm_active_id = -1;
  527.    return(1);
  528.    }  // end if
  529. else
  530.     return(0);
  531. } // end DMusic_Stop
  532. ///////////////////////////////////////////////////////////
  533. int DMusic_Delete_MIDI(int id)
  534. {
  535. // this function deletes one MIDI segment
  536. // Unload instruments this will cause silence.
  537. // CloseDown unloads all instruments, so this call is also not 
  538. // strictly necessary.
  539. if (dm_midi[id].dm_segment)
  540.    {
  541.    dm_midi[id].dm_segment->SetParam(GUID_Unload, -1, 0, 0, (void*)dm_perf); 
  542.    // Release the segment and set to null
  543.    dm_midi[id].dm_segment->Release(); 
  544.    dm_midi[id].dm_segment  = NULL;
  545.    dm_midi[id].dm_segstate = NULL;
  546.    dm_midi[id].state       = MIDI_NULL;
  547.    } // end if
  548. return(1);
  549. } // end DMusic_Delete_MIDI
  550. //////////////////////////////////////////////////////////
  551. int DMusic_Delete_All_MIDI(void)
  552. {
  553. // delete all the MIDI 
  554. int index; // loop var
  555. // free up all the segments
  556. for (index = 0; index < DM_NUM_SEGMENTS; index++)
  557.     {
  558.     // Unload instruments this will cause silence.
  559.     // CloseDown unloads all instruments, so this call is also not 
  560.     // strictly necessary.
  561.     if (dm_midi[index].dm_segment)
  562.        {
  563.        dm_midi[index].dm_segment->SetParam(GUID_Unload, -1, 0, 0, (void*)dm_perf); 
  564.        // Release the segment and set to null
  565.        dm_midi[index].dm_segment->Release(); 
  566.        dm_midi[index].dm_segment  = NULL;
  567.        dm_midi[index].dm_segstate = NULL;
  568.        dm_midi[index].state       = MIDI_NULL;
  569.        } // end if
  570.     } // end for index
  571. return(1);
  572. } // end DMusic_Delete_All_MIDI
  573. //////////////////////////////////////////////////////////
  574. int DMusic_Status_MIDI(int id)
  575. {
  576. // this checks the status of a midi segment
  577. if (dm_midi[id].dm_segment && dm_midi[id].state !=MIDI_NULL )
  578.    {
  579.    // get the status and translate to our defines
  580.    if (dm_perf->IsPlaying(dm_midi[id].dm_segment,NULL) == S_OK) 
  581.       dm_midi[id].state = MIDI_PLAYING;
  582.    else
  583.       dm_midi[id].state = MIDI_STOPPED;
  584.    return(dm_midi[id].state);
  585.    } // end if
  586. else
  587.    return(0);
  588. } // end DMusic_Status_MIDI
  589. ///////////////////////////////////////////////////////////
  590. int DMusic_Init(void)
  591. {
  592. // this function initializes directmusic, it also checks if directsound has
  593. // been initialized, if so it connect the wave output to directsound, otherwise
  594. // it creates it's own directsound object, hence you must start directsound up
  595. // first if you want to use both directsound and directmusic
  596. int index; // looping var
  597. // set up directmusic
  598. // initialize COM
  599. if (FAILED(CoInitialize(NULL)))
  600.    {    
  601.    // Terminate the application.
  602.    return(0);
  603.    }   // end if
  604. // create the performance
  605. if (FAILED(CoCreateInstance(CLSID_DirectMusicPerformance,
  606.                             NULL,
  607.                             CLSCTX_INPROC,
  608.                             IID_IDirectMusicPerformance,
  609.                             (void**)&dm_perf)))    
  610.    {
  611.    // return null        
  612.    return(0);
  613.    } // end if
  614. // initialize the performance, check if directsound is on-line if so, use the
  615. // directsound object, otherwise create a new one
  616. if (FAILED(dm_perf->Init(NULL, lpds, main_window_handle)))
  617.    {
  618.    return(0);// Failure -- performance not initialized
  619.    } // end if 
  620. // add the port to the performance
  621. if (FAILED(dm_perf->AddPort(NULL)))
  622.    {    
  623.    return(0);// Failure -- port not initialized
  624.    } // end if
  625. // create the loader to load object(s) such as midi file
  626. if (FAILED(CoCreateInstance(
  627.           CLSID_DirectMusicLoader,
  628.           NULL,
  629.           CLSCTX_INPROC, 
  630.           IID_IDirectMusicLoader,
  631.           (void**)&dm_loader)))
  632.    {
  633.    // error
  634.    return(0);
  635.    } // end if
  636. // reset all the midi segment objects
  637. for (index = 0; index < DM_NUM_SEGMENTS; index++)
  638.     {
  639.     // reset the object
  640.     dm_midi[index].dm_segment  = NULL;  
  641.     dm_midi[index].dm_segstate = NULL;  
  642.     dm_midi[index].state       = MIDI_NULL;
  643.     dm_midi[index].id          = index;
  644.     } // end for index
  645. // reset the active id
  646. dm_active_id = -1;
  647. // all good baby
  648. return(1);
  649. } // end DMusic_Init
  650. ////////////////////////////////////////////////////////////
  651. int DMusic_Shutdown(void)
  652. {
  653. int index;
  654. // If there is any music playing, stop it. This is 
  655. // not really necessary, because the music will stop when
  656. // the instruments are unloaded or the performance is    
  657. // closed down.
  658. if (dm_perf)
  659.    dm_perf->Stop(NULL, NULL, 0, 0 ); 
  660. // delete all the midis if they already haven't been
  661. DMusic_Delete_All_MIDI();
  662. // CloseDown and Release the performance object.    
  663. if (dm_perf)
  664.    {
  665.    dm_perf->CloseDown();
  666.    dm_perf->Release();     
  667.    } // end if
  668. // Release the loader object.
  669. if (dm_loader)
  670.    dm_loader->Release();     
  671. // Release COM
  672. CoUninitialize(); 
  673. // return success
  674. return(1);
  675. } // end DMusic_Shutdown