t3dlib3.cpp
资源名称:Source.rar [点击查看]
上传用户:husern
上传日期:2018-01-20
资源大小:42486k
文件大小:22k
源码类别:
游戏
开发平台:
Visual C++
- // T3DLIB3.CPP - Game Engine Part III, sound & music
- // INCLUDES ///////////////////////////////////////////////
- #define WIN32_LEAN_AND_MEAN
- #include <windows.h> // include important windows stuff
- #include <windowsx.h>
- #include <mmsystem.h>
- #include <objbase.h>
- #include <iostream.h> // include important C/C++ stuff
- #include <conio.h>
- #include <stdlib.h>
- #include <malloc.h>
- #include <memory.h>
- #include <string.h>
- #include <stdarg.h>
- #include <stdio.h>
- #include <math.h>
- #include <io.h>
- #include <fcntl.h>
- #include <direct.h>
- #include <wchar.h>
- #include <ddraw.h> // directX includes
- #include <dsound.h>
- #include <dmksctrl.h>
- #include <dmusici.h>
- #include <dmusicc.h>
- #include <dmusicf.h>
- #include "T3DLIB3.H"
- // DEFINES ////////////////////////////////////////////////
- // TYPES //////////////////////////////////////////////////
- // PROTOTYPES /////////////////////////////////////////////
- // EXTERNALS /////////////////////////////////////////////
- extern HWND main_window_handle; // access to main window handle in main module
- // GLOBALS ////////////////////////////////////////////////
- // directsound stuff
- LPDIRECTSOUND lpds = NULL; // directsound interface pointer
- DSBUFFERDESC dsbd; // directsound description
- DSCAPS dscaps; // directsound caps
- HRESULT dsresult; // general directsound result
- DSBCAPS dsbcaps; // directsound buffer caps
- LPDIRECTSOUNDBUFFER lpdsbprimary = NULL; // the primary mixing buffer
- pcm_sound sound_fx[MAX_SOUNDS]; // the array of secondary sound buffers
- WAVEFORMATEX pcmwf; // generic waveformat structure
- // direct music globals
- IDirectMusicPerformance *dm_perf = NULL; // the directmusic performance manager
- IDirectMusicLoader *dm_loader = NULL; // the directmusic loader
- // this hold all the directmusic midi objects
- DMUSIC_MIDI dm_midi[DM_NUM_SEGMENTS];
- int dm_active_id = -1; // currently active midi segment
- // FUNCTIONS //////////////////////////////////////////////
- int DSound_Load_WAV(char *filename, int control_flags)
- {
- // this function loads a .wav file, sets up the directsound
- // buffer and loads the data into memory, the function returns
- // the id number of the sound
- HMMIO hwav; // handle to wave file
- MMCKINFO parent, // parent chunk
- child; // child chunk
- WAVEFORMATEX wfmtx; // wave format structure
- int sound_id = -1, // id of sound to be loaded
- index; // looping variable
- UCHAR *snd_buffer, // temporary sound buffer to hold voc data
- *audio_ptr_1=NULL, // data ptr to first write buffer
- *audio_ptr_2=NULL; // data ptr to second write buffer
- DWORD audio_length_1=0, // length of first write buffer
- audio_length_2=0; // length of second write buffer
- // step one: are there any open id's ?
- for (index=0; index < MAX_SOUNDS; index++)
- {
- // make sure this sound is unused
- if (sound_fx[index].state==SOUND_NULL)
- {
- sound_id = index;
- break;
- } // end if
- } // end for index
- // did we get a free id?
- if (sound_id==-1)
- return(-1);
- // set up chunk info structure
- parent.ckid = (FOURCC)0;
- parent.cksize = 0;
- parent.fccType = (FOURCC)0;
- parent.dwDataOffset = 0;
- parent.dwFlags = 0;
- // copy data
- child = parent;
- // open the WAV file
- if ((hwav = mmioOpen(filename, NULL, MMIO_READ | MMIO_ALLOCBUF))==NULL)
- return(-1);
- // descend into the RIFF
- parent.fccType = mmioFOURCC('W', 'A', 'V', 'E');
- if (mmioDescend(hwav, &parent, NULL, MMIO_FINDRIFF))
- {
- // close the file
- mmioClose(hwav, 0);
- // return error, no wave section
- return(-1);
- } // end if
- // descend to the WAVEfmt
- child.ckid = mmioFOURCC('f', 'm', 't', ' ');
- if (mmioDescend(hwav, &child, &parent, 0))
- {
- // close the file
- mmioClose(hwav, 0);
- // return error, no format section
- return(-1);
- } // end if
- // now read the wave format information from file
- if (mmioRead(hwav, (char *)&wfmtx, sizeof(wfmtx)) != sizeof(wfmtx))
- {
- // close file
- mmioClose(hwav, 0);
- // return error, no wave format data
- return(-1);
- } // end if
- // make sure that the data format is PCM
- if (wfmtx.wFormatTag != WAVE_FORMAT_PCM)
- {
- // close the file
- mmioClose(hwav, 0);
- // return error, not the right data format
- return(-1);
- } // end if
- // now ascend up one level, so we can access data chunk
- if (mmioAscend(hwav, &child, 0))
- {
- // close file
- mmioClose(hwav, 0);
- // return error, couldn't ascend
- return(-1);
- } // end if
- // descend to the data chunk
- child.ckid = mmioFOURCC('d', 'a', 't', 'a');
- if (mmioDescend(hwav, &child, &parent, MMIO_FINDCHUNK))
- {
- // close file
- mmioClose(hwav, 0);
- // return error, no data
- return(-1);
- } // end if
- // finally!!!! now all we have to do is read the data in and
- // set up the directsound buffer
- // allocate the memory to load sound data
- snd_buffer = (UCHAR *)malloc(child.cksize);
- // read the wave data
- mmioRead(hwav, (char *)snd_buffer, child.cksize);
- // close the file
- mmioClose(hwav, 0);
- // set rate and size in data structure
- sound_fx[sound_id].rate = wfmtx.nSamplesPerSec;
- sound_fx[sound_id].size = child.cksize;
- sound_fx[sound_id].state = SOUND_LOADED;
- // set up the format data structure
- memset(&pcmwf, 0, sizeof(WAVEFORMATEX));
- pcmwf.wFormatTag = WAVE_FORMAT_PCM; // pulse code modulation
- pcmwf.nChannels = 1; // mono
- pcmwf.nSamplesPerSec = 11025; // always this rate
- pcmwf.nBlockAlign = 1;
- pcmwf.nAvgBytesPerSec = pcmwf.nSamplesPerSec * pcmwf.nBlockAlign;
- pcmwf.wBitsPerSample = 8;
- pcmwf.cbSize = 0;
- // prepare to create sounds buffer
- dsbd.dwSize = sizeof(DSBUFFERDESC);
- dsbd.dwFlags = control_flags | DSBCAPS_STATIC | DSBCAPS_LOCSOFTWARE;
- dsbd.dwBufferBytes = child.cksize;
- dsbd.lpwfxFormat = &pcmwf;
- // create the sound buffer
- if (FAILED(lpds->CreateSoundBuffer(&dsbd,&sound_fx[sound_id].dsbuffer,NULL)))
- {
- // release memory
- free(snd_buffer);
- // return error
- return(-1);
- } // end if
- // copy data into sound buffer
- if (FAILED(sound_fx[sound_id].dsbuffer->Lock(0,
- child.cksize,
- (void **) &audio_ptr_1,
- &audio_length_1,
- (void **)&audio_ptr_2,
- &audio_length_2,
- DSBLOCK_FROMWRITECURSOR)))
- return(0);
- // copy first section of circular buffer
- memcpy(audio_ptr_1, snd_buffer, audio_length_1);
- // copy last section of circular buffer
- memcpy(audio_ptr_2, (snd_buffer+audio_length_1),audio_length_2);
- // unlock the buffer
- if (FAILED(sound_fx[sound_id].dsbuffer->Unlock(audio_ptr_1,
- audio_length_1,
- audio_ptr_2,
- audio_length_2)))
- return(0);
- // release the temp buffer
- free(snd_buffer);
- // return id
- return(sound_id);
- } // end DSound_Load_WAV
- ///////////////////////////////////////////////////////////
- int DSound_Replicate_Sound(int source_id)
- {
- // this function replicates the sent sound and sends back the
- // id of the replicated sound, you would use this function
- // to make multiple copies of a gunshot or something that
- // you want to play multiple times simulataneously, but you
- // only want to load once
- if (source_id!=-1)
- {
- // duplicate the sound buffer
- // first hunt for an open id
- for (int id=0; id < MAX_SOUNDS; id++)
- {
- // is this sound open?
- if (sound_fx[id].state==SOUND_NULL)
- {
- // first make an identical copy
- sound_fx[id] = sound_fx[source_id];
- // now actually replicate the directsound buffer
- if (FAILED(lpds->DuplicateSoundBuffer(sound_fx[source_id].dsbuffer,
- &sound_fx[id].dsbuffer)))
- {
- // reset sound to NULL
- sound_fx[id].dsbuffer = NULL;
- sound_fx[id].state = SOUND_NULL;
- // return error
- return(-1);
- } // end if
- // now fix up id
- sound_fx[id].id = id;
- // return replicated sound
- return(id);
- } // end if found
- } // end for id
- } // end if
- else
- return(-1);
- // else failure
- return(-1);
- } // end DSound_Replicate_Sound
- //////////////////////////////////////////////////////////
- int DSound_Init(void)
- {
- // this function initializes the sound system
- static int first_time = 1; // used to track the first time the function
- // is entered
- // test for very first time
- if (first_time)
- {
- // clear everything out
- memset(sound_fx,0,sizeof(pcm_sound)*MAX_SOUNDS);
- // reset first time
- first_time = 0;
- // create a directsound object
- if (FAILED(DirectSoundCreate(NULL, &lpds, NULL)))
- return(0);
- // set cooperation level
- if (FAILED(lpds->SetCooperativeLevel((HWND)main_window_handle,DSSCL_NORMAL)))
- return(0);
- } // end if
- // initialize the sound fx array
- for (int index=0; index<MAX_SOUNDS; index++)
- {
- // test if this sound has been loaded
- if (sound_fx[index].dsbuffer)
- {
- // stop the sound
- sound_fx[index].dsbuffer->Stop();
- // release the buffer
- sound_fx[index].dsbuffer->Release();
- } // end if
- // clear the record out
- memset(&sound_fx[index],0,sizeof(pcm_sound));
- // now set up the fields
- sound_fx[index].state = SOUND_NULL;
- sound_fx[index].id = index;
- } // end for index
- // return sucess
- return(1);
- } // end DSound_Init
- ///////////////////////////////////////////////////////////
- int DSound_Shutdown(void)
- {
- // this function releases all the memory allocated and the directsound object
- // itself
- // first turn all sounds off
- DSound_Stop_All_Sounds();
- // now release all sound buffers
- for (int index=0; index<MAX_SOUNDS; index++)
- if (sound_fx[index].dsbuffer)
- sound_fx[index].dsbuffer->Release();
- // now release the directsound interface itself
- if (lpds)
- lpds->Release();
- // return success
- return(1);
- } // end DSound_Shutdown
- ///////////////////////////////////////////////////////////
- int DSound_Play(int id, int flags, int volume, int rate, int pan)
- {
- // this function plays a sound, the only parameter that
- // works is the flags which can be 0 to play once or
- // DSBPLAY_LOOPING
- if (sound_fx[id].dsbuffer)
- {
- // reset position to start
- if (FAILED(sound_fx[id].dsbuffer->SetCurrentPosition(0)))
- return(0);
- // play sound
- if (FAILED(sound_fx[id].dsbuffer->Play(0,0,flags)))
- return(0);
- } // end if
- // return success
- return(1);
- } // end DSound_Play
- ///////////////////////////////////////////////////////////
- int DSound_Set_Volume(int id,int vol)
- {
- // this function sets the volume on a sound 0-100
- if (sound_fx[id].dsbuffer->SetVolume(DSVOLUME_TO_DB(vol))!=DS_OK)
- return(0);
- // return success
- return(1);
- } // end DSound_Set_Volume
- ///////////////////////////////////////////////////////////
- int DSound_Set_Freq(int id,int freq)
- {
- // this function sets the playback rate
- if (sound_fx[id].dsbuffer->SetFrequency(freq)!=DS_OK)
- return(0);
- // return success
- return(1);
- } // end DSound_Set_Freq
- ///////////////////////////////////////////////////////////
- int DSound_Set_Pan(int id,int pan)
- {
- // this function sets the pan, -10,000 to 10,0000
- if (sound_fx[id].dsbuffer->SetPan(pan)!=DS_OK)
- return(0);
- // return success
- return(1);
- } // end DSound_Set_Pan
- ////////////////////////////////////////////////////////////
- int DSound_Stop_Sound(int id)
- {
- // this function stops a sound from playing
- if (sound_fx[id].dsbuffer)
- {
- sound_fx[id].dsbuffer->Stop();
- sound_fx[id].dsbuffer->SetCurrentPosition(0);
- } // end if
- // return success
- return(1);
- } // end DSound_Stop_Sound
- ///////////////////////////////////////////////////////////
- int DSound_Delete_All_Sounds(void)
- {
- // this function deletes all the sounds
- for (int index=0; index < MAX_SOUNDS; index++)
- DSound_Delete_Sound(index);
- // return success always
- return(1);
- } // end DSound_Delete_All_Sounds
- ///////////////////////////////////////////////////////////
- int DSound_Delete_Sound(int id)
- {
- // this function deletes a single sound and puts it back onto the available list
- // first stop it
- if (!DSound_Stop_Sound(id))
- return(0);
- // now delete it
- if (sound_fx[id].dsbuffer)
- {
- // release the com object
- sound_fx[id].dsbuffer->Release();
- sound_fx[id].dsbuffer = NULL;
- // return success
- return(1);
- } // end if
- // return success
- return(1);
- } // end DSound_Delete_Sound
- ///////////////////////////////////////////////////////////
- int DSound_Stop_All_Sounds(void)
- {
- // this function stops all sounds
- for (int index=0; index<MAX_SOUNDS; index++)
- DSound_Stop_Sound(index);
- // return success
- return(1);
- } // end DSound_Stop_All_Sounds
- ///////////////////////////////////////////////////////////
- int DSound_Status_Sound(int id)
- {
- // this function returns the status of a sound
- if (sound_fx[id].dsbuffer)
- {
- ULONG status;
- // get the status
- sound_fx[id].dsbuffer->GetStatus(&status);
- // return the status
- return(status);
- } // end if
- else // total failure
- return(-1);
- } // end DSound_Status_Sound
- ///////////////////////////////////////////////////////////
- int DMusic_Load_MIDI(char *filename)
- {
- // this function loads a midi segment
- DMUS_OBJECTDESC ObjDesc;
- HRESULT hr;
- IDirectMusicSegment* pSegment = NULL;
- int index; // loop var
- // look for open slot for midi segment
- int id = -1;
- for (index = 0; index < DM_NUM_SEGMENTS; index++)
- {
- // is this one open
- if (dm_midi[index].state == MIDI_NULL)
- {
- // validate id, but don't validate object until loaded
- id = index;
- break;
- } // end if
- } // end for index
- // found good id?
- if (id==-1)
- return(-1);
- // get current working directory
- char szDir[_MAX_PATH];
- WCHAR wszDir[_MAX_PATH];
- if(_getcwd( szDir, _MAX_PATH ) == NULL)
- {
- return(-1);;
- } // end if
- MULTI_TO_WIDE(wszDir, szDir);
- // tell the loader were to look for files
- hr = dm_loader->SetSearchDirectory(GUID_DirectMusicAllTypes,wszDir, FALSE);
- if (FAILED(hr))
- {
- return (-1);
- } // end if
- // convert filename to wide string
- WCHAR wfilename[_MAX_PATH];
- MULTI_TO_WIDE(wfilename, filename);
- // setup object description
- DD_INIT_STRUCT(ObjDesc);
- ObjDesc.guidClass = CLSID_DirectMusicSegment;
- wcscpy(ObjDesc.wszFileName, wfilename );
- ObjDesc.dwValidData = DMUS_OBJ_CLASS | DMUS_OBJ_FILENAME;
- // load the object and query it for the IDirectMusicSegment interface
- // This is done in a single call to IDirectMusicLoader::GetObject
- // note that loading the object also initializes the tracks and does
- // everything else necessary to get the MIDI data ready for playback.
- hr = dm_loader->GetObject(&ObjDesc,IID_IDirectMusicSegment, (void**) &pSegment);
- if (FAILED(hr))
- return(-1);
- // ensure that the segment plays as a standard MIDI file
- // you now need to set a parameter on the band track
- // Use the IDirectMusicSegment::SetParam method and let
- // DirectMusic find the trackby passing -1 (or 0xFFFFFFFF) in the dwGroupBits method parameter.
- hr = pSegment->SetParam(GUID_StandardMIDIFile,-1, 0, 0, (void*)dm_perf);
- if (FAILED(hr))
- return(-1);
- // This step is necessary because DirectMusic handles program changes and
- // bank selects differently for standard MIDI files than it does for MIDI
- // content authored specifically for DirectMusic.
- // The GUID_StandardMIDIFile parameter must be set before the instruments are downloaded.
- // The next step is to download the instruments.
- // This is necessary even for playing a simple MIDI file
- // because the default software synthesizer needs the DLS data
- // for the General MIDI instrument set
- // If you skip this step, the MIDI file will play silently.
- // Again, you call SetParam on the segment, this time specifying the GUID_Download parameter:
- hr = pSegment->SetParam(GUID_Download, -1, 0, 0, (void*)dm_perf);
- if (FAILED(hr))
- return(-1);
- // at this point we have MIDI loaded and a valid object
- dm_midi[id].dm_segment = pSegment;
- dm_midi[id].dm_segstate = NULL;
- dm_midi[id].state = MIDI_LOADED;
- // return id
- return(id);
- } // end DMusic_Load_MIDI
- //////////////////////////////////////////////////////////
- int DMusic_Play(int id)
- {
- // play sound based on id
- if (dm_midi[id].dm_segment && dm_midi[id].state!=MIDI_NULL)
- {
- // if there is an active midi then stop it
- if (dm_active_id!=-1)
- DMusic_Stop(dm_active_id);
- // play segment and force tracking of state variable
- dm_perf->PlaySegment(dm_midi[id].dm_segment, 0, 0, &dm_midi[id].dm_segstate);
- dm_midi[id].state = MIDI_PLAYING;
- // set the active midi segment
- dm_active_id = id;
- return(1);
- } // end if
- else
- return(0);
- } // end DMusic_Play
- //////////////////////////////////////////////////////////
- int DMusic_Stop(int id)
- {
- // stop a midi segment
- if (dm_midi[id].dm_segment && dm_midi[id].state!=MIDI_NULL)
- {
- // play segment and force tracking of state variable
- dm_perf->Stop(dm_midi[id].dm_segment, NULL, 0, 0);
- dm_midi[id].state = MIDI_STOPPED;
- // reset active id
- dm_active_id = -1;
- return(1);
- } // end if
- else
- return(0);
- } // end DMusic_Stop
- ///////////////////////////////////////////////////////////
- int DMusic_Delete_MIDI(int id)
- {
- // this function deletes one MIDI segment
- // Unload instruments this will cause silence.
- // CloseDown unloads all instruments, so this call is also not
- // strictly necessary.
- if (dm_midi[id].dm_segment)
- {
- dm_midi[id].dm_segment->SetParam(GUID_Unload, -1, 0, 0, (void*)dm_perf);
- // Release the segment and set to null
- dm_midi[id].dm_segment->Release();
- dm_midi[id].dm_segment = NULL;
- dm_midi[id].dm_segstate = NULL;
- dm_midi[id].state = MIDI_NULL;
- } // end if
- return(1);
- } // end DMusic_Delete_MIDI
- //////////////////////////////////////////////////////////
- int DMusic_Delete_All_MIDI(void)
- {
- // delete all the MIDI
- int index; // loop var
- // free up all the segments
- for (index = 0; index < DM_NUM_SEGMENTS; index++)
- {
- // Unload instruments this will cause silence.
- // CloseDown unloads all instruments, so this call is also not
- // strictly necessary.
- if (dm_midi[index].dm_segment)
- {
- dm_midi[index].dm_segment->SetParam(GUID_Unload, -1, 0, 0, (void*)dm_perf);
- // Release the segment and set to null
- dm_midi[index].dm_segment->Release();
- dm_midi[index].dm_segment = NULL;
- dm_midi[index].dm_segstate = NULL;
- dm_midi[index].state = MIDI_NULL;
- } // end if
- } // end for index
- return(1);
- } // end DMusic_Delete_All_MIDI
- //////////////////////////////////////////////////////////
- int DMusic_Status_MIDI(int id)
- {
- // this checks the status of a midi segment
- if (dm_midi[id].dm_segment && dm_midi[id].state !=MIDI_NULL )
- {
- // get the status and translate to our defines
- if (dm_perf->IsPlaying(dm_midi[id].dm_segment,NULL) == S_OK)
- dm_midi[id].state = MIDI_PLAYING;
- else
- dm_midi[id].state = MIDI_STOPPED;
- return(dm_midi[id].state);
- } // end if
- else
- return(0);
- } // end DMusic_Status_MIDI
- ///////////////////////////////////////////////////////////
- int DMusic_Init(void)
- {
- // this function initializes directmusic, it also checks if directsound has
- // been initialized, if so it connect the wave output to directsound, otherwise
- // it creates it's own directsound object, hence you must start directsound up
- // first if you want to use both directsound and directmusic
- int index; // looping var
- // set up directmusic
- // initialize COM
- if (FAILED(CoInitialize(NULL)))
- {
- // Terminate the application.
- return(0);
- } // end if
- // create the performance
- if (FAILED(CoCreateInstance(CLSID_DirectMusicPerformance,
- NULL,
- CLSCTX_INPROC,
- IID_IDirectMusicPerformance,
- (void**)&dm_perf)))
- {
- // return null
- return(0);
- } // end if
- // 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, lpds, main_window_handle)))
- {
- return(0);// Failure -- performance not initialized
- } // end if
- // add the port to the performance
- if (FAILED(dm_perf->AddPort(NULL)))
- {
- return(0);// Failure -- port not initialized
- } // end if
- // 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
- // reset all the midi segment objects
- for (index = 0; index < DM_NUM_SEGMENTS; index++)
- {
- // reset the object
- dm_midi[index].dm_segment = NULL;
- dm_midi[index].dm_segstate = NULL;
- dm_midi[index].state = MIDI_NULL;
- dm_midi[index].id = index;
- } // end for index
- // reset the active id
- dm_active_id = -1;
- // all good baby
- return(1);
- } // end DMusic_Init
- ////////////////////////////////////////////////////////////
- int DMusic_Shutdown(void)
- {
- int index;
- // If there is any music playing, stop it. This is
- // not really necessary, because the music will stop when
- // the instruments are unloaded or the performance is
- // closed down.
- if (dm_perf)
- dm_perf->Stop(NULL, NULL, 0, 0 );
- // delete all the midis if they already haven't been
- DMusic_Delete_All_MIDI();
- // CloseDown and Release the performance object.
- if (dm_perf)
- {
- dm_perf->CloseDown();
- dm_perf->Release();
- } // end if
- // Release the loader object.
- if (dm_loader)
- dm_loader->Release();
- // Release COM
- CoUninitialize();
- // return success
- return(1);
- } // end DMusic_Shutdown