DirectSound && DirectMusic 库文件部分
- /*2008.10.4
- T3D图形库
- ——<<windows游戏
- 编程大师技巧>>
- */
- // 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 "DS&DM_LIB.h"
- // EXTERNALS /
- extern HWND main_window_handle; // 窗口句柄
- // 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 stuff
- IDirectMusicPerformance *dm_perf = NULL; // the directmusic performance manager
- IDirectMusicLoader *dm_loader = NULL; // the directmusic loader
- DMUSIC_MIDI dm_midi[DM_NUM_SEGMENTS]; // 定义了所有的midi音乐对象
- int dm_active_id = -1; // 当前的DM音乐文件id号
- // 函数定义 //
- int DSound_Load_WAV(char *filename, int control_flags /* = DSBCAPS_CTRLDEFAULT */)
- {
- //此函数加载一个.wav文件,设置directsound缓冲,加载数据进内存并返回声音文件的id号
- HMMIO hwav;
- MMCKINFO parent,
- child;
- WAVEFORMATEX wfmtx;
- int sound_id = -1,
- index;
- UCHAR *snd_buffer,
- *audio_ptr_1=NULL,
- *audio_ptr_2=NULL;
- DWORD audio_length_1=0,
- audio_length_2=0;
- for (index=0;index<MAX_SOUNDS;index++)
- {
- if (sound_fx[index].state==SOUND_NULL)
- {
- sound_id = index;
- break;
- }
- }
- if (sound_id==-1)
- return(-1);
- parent.ckid =(FOURCC)0;
- parent.ckid =0;
- parent.fccType =(FOURCC)0;
- parent.dwDataOffset =0;
- parent.dwFlags =0;
- child = parent;
- //打开.wav文件
- if((hwav = mmioOpen(filename,NULL,MMIO_READ | MMIO_ALLOCBUF))==NULL)
- return(-1);
- parent.fccType = mmioFOURCC('W','A','V','E');
- //定位到wave区
- if (mmioDescend(hwav,&parent,NULL,MMIO_FINDRIFF))
- {
- mmioClose(hwav,0);
- return(-1);
- }
- child.ckid = mmioFOURCC('f','m','t',' ');
- //定位到fmt区
- if (mmioDescend(hwav,&child,&parent,0))
- {
- mmioClose(hwav,0);
- return(-1);
- }
- //读取.wav文件格式信息
- if (mmioRead(hwav,(char*)&wfmtx,sizeof(wfmtx))!=sizeof(wfmtx))
- {
- mmioClose(hwav,0);
- return(-1);
- }
- //若格式并非PCM
- if (wfmtx.wFormatTag!=WAVE_FORMAT_PCM)
- {
- mmioClose(hwav,0);
- return(-1);
- }
- if (mmioAscend(hwav,&child,0))
- {
- mmioClose(hwav,0);
- return(-1);
- }
- child.ckid = mmioFOURCC('d','a','t','a');
- //定位到data区
- if (mmioDescend(hwav,&child,&parent,MMIO_FINDCHUNK))
- {
- mmioClose(hwav,0);
- return(-1);
- }
- //开辟足够的内存(声音数据大小)赋予临时缓冲
- snd_buffer = (UCHAR*)malloc(child.cksize);
- //读数据内容到缓冲
- mmioRead(hwav,(char*)snd_buffer,child.cksize);
- mmioClose(hwav,0);
- sound_fx[sound_id].rate = wfmtx.nSamplesPerSec;
- sound_fx[sound_id].size = child.cksize;
- sound_fx[sound_id].state= SOUND_LOADED; //标记
- memset(&pcmwf,0,sizeof(WAVEFORMATEX));
- pcmwf.wFormatTag = WAVE_FORMAT_PCM;
- pcmwf.nChannels = 1;
- pcmwf.nSamplesPerSec = 11025;
- pcmwf.nBlockAlign = 1;
- pcmwf.nAvgBytesPerSec = pcmwf.nSamplesPerSec*pcmwf.nBlockAlign;
- pcmwf.wBitsPerSample = 8;
- pcmwf.cbSize = 0;
- dsbd.dwSize = sizeof(DSBUFFERDESC);
- dsbd.dwFlags = control_flags | DSBCAPS_STATIC | DSBCAPS_LOCSOFTWARE; // 默认控制|静态声音|系统内存
- dsbd.dwBufferBytes = child.cksize;
- dsbd.lpwfxFormat = &pcmwf;
- //创建DS缓冲区
- if (FAILED(lpds->CreateSoundBuffer(&dsbd,&sound_fx[sound_id].dsbuffer,NULL)))
- {
- free(snd_buffer);
- return(-1);
- }
- 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(-1);
- //将临时缓冲的声音数据转到DS缓冲
- memcpy(audio_ptr_1,snd_buffer,audio_length_1);
- memcpy(audio_ptr_2,(snd_buffer+audio_length_1),audio_length_2);
- if (FAILED(sound_fx[sound_id].dsbuffer->Unlock(audio_ptr_1,
- audio_length_1,
- audio_ptr_2,
- audio_length_2)))
- return(-1);
- free(snd_buffer);
- return(sound_id);
- }
- // copy DS声音文件,你需要先加载一个,然后传入该声音的id索引,
- //函数返回copy的新的DS声音文件ID号
- int DSound_Replicate_Sound(int source_id)
- {
- if (source_id!=-1)
- {
- for (int id=0;id<MAX_SOUNDS;id++)
- {
- if (sound_fx[id].state==SOUND_NULL)
- {
- sound_fx[id] = sound_fx[source_id];
- //DS 缓冲区copy过程
- if (FAILED(lpds->DuplicateSoundBuffer(sound_fx[source_id].dsbuffer,
- &sound_fx[id].dsbuffer)))
- {
- //失败则还原标记
- sound_fx[id].dsbuffer = NULL;
- sound_fx[id].state = SOUND_NULL;
- return(-1);
- }
- sound_fx[id].id = id;
- return(id);
- }
- }
- }
- else
- return(-1);
- return(-1);
- }
- int DSound_Init(void)
- {
- static int first_time = 1;
- //如果是第一次初始化(创建DS接口对象及设置相应协作模式)
- if (first_time)
- {
- memset(sound_fx,0,sizeof(pcm_sound)*MAX_SOUNDS);
- first_time = 0;
- if (FAILED(DirectSoundCreate(NULL,&lpds,NULL)))
- return(0);
- if (FAILED(lpds->SetCooperativeLevel((HWND)main_window_handle,DSSCL_NORMAL)))
- return(0);
- }
- //
- for (int index=0;index<MAX_SOUNDS;index++)
- {
- if (sound_fx[index].dsbuffer)
- {
- sound_fx[index].dsbuffer->Stop();
- sound_fx[index].dsbuffer->Release();
- }
- memset(&sound_fx[index],0,sizeof(pcm_sound));
- sound_fx[index].state = SOUND_NULL;
- sound_fx[index].id = index; //标记索引
- }
- return(1);
- }
- int DSound_Shutdown(void)
- {
- //首先关闭所有声音
- DSound_Stop_All_Sounds();
- //然后释放DS缓冲
- for (int index=0;index<MAX_SOUNDS;index++)
- if (sound_fx[index].dsbuffer)
- sound_fx[index].dsbuffer->Release();
- //最后释放DS接口
- if (lpds)
- lpds->Release();
- return(1);
- }
- int DSound_Play(int id, int flags/* =0 */, int volume/* =0 */, int rate/* =0 */, int pan/* =0 */)
- {
- if (sound_fx[id].dsbuffer)
- {
- // 设置DS缓冲区为起始播放
- if(FAILED(sound_fx[id].dsbuffer->SetCurrentPosition(0)))
- return(0);
- if(FAILED(sound_fx[id].dsbuffer->Play(0,0,flags)))
- return(0);
- }
- return(1);
- }
- int DSound_Set_Volume(int id,int vol)
- {
- //此函数设置DS声音大小
- if (sound_fx[id].dsbuffer->SetVolume(DSVOLUME_TO_DB(vol))!=DS_OK)
- return(0);
- return(1);
- }
- int DSound_Set_Freq(int id,int freq)
- {
- //此函数设置DS 声音频率
- if(sound_fx[id].dsbuffer->SetFrequency(freq)!=DS_OK)
- return(0);
- return(1);
- }
- int DSound_Set_Pan(int id,int pan)
- {
- //此函数设置DS 声音平衡性(+为偏右)
- if(sound_fx[id].dsbuffer->SetPan(pan)!=DS_OK)
- return(0);
- return(1);
- }
- int DSound_Stop_Sound(int id)
- {
- if (sound_fx[id].dsbuffer)
- {
- sound_fx[id].dsbuffer->Stop();
- sound_fx[id].dsbuffer->SetCurrentPosition(0);
- }
- return(1);
- }
- int DSound_Stop_All_Sounds(void)
- {
- for (int index=0;index<MAX_SOUNDS;index++)
- {
- DSound_Stop_Sound(index);
- }
- return(1);
- }
- int DSound_Delete_Sound(int id)
- {
- if(!DSound_Stop_Sound(id))
- return(0);
- if (sound_fx[id].dsbuffer)
- {
- sound_fx[id].dsbuffer->Release();
- sound_fx[id].dsbuffer = NULL;
- return(1);
- }
- return(1);
- }
- int DSound_Delete_All_Sounds(void)
- {
- for(int index=0;index<MAX_SOUNDS;index++)
- DSound_Delete_Sound(index);
- return(1);
- }
- int DSound_Status_Sound(int id)
- {
- //此函数取得当前DS缓冲区状态
- if (sound_fx[id].dsbuffer)
- {
- ULONG status;
- sound_fx[id].dsbuffer->GetStatus(&status);
- return(status);
- }
- else
- return(-1);
- }
- ///
- int DMusic_Load_MIDI(char *filename)
- {
- //此函数加载一个midi段(返回索引id)
- DMUS_OBJECTDESC ObjDesc;
- HRESULT hr;
- IDirectMusicSegment* pSegment = NULL;
- int index;
- int id = -1;
- for (index = 0; index < DM_NUM_SEGMENTS; index++)
- {
- if (dm_midi[index].state == MIDI_NULL)
- {
- id = index;
- break;
- }
- }
- if (id==-1)
- return(-1);
- //取得当前工作目录
- char szDir[_MAX_PATH];
- WCHAR wszDir[_MAX_PATH];
- if(_getcwd( szDir, _MAX_PATH ) == NULL)
- {
- return(-1);;
- }
- //多字节字符转换为宽字节字符串
- MULTI_TO_WIDE(wszDir, szDir);
- // 告诉加载器搜索目录
- hr = dm_loader->SetSearchDirectory(GUID_DirectMusicAllTypes,wszDir, FALSE);
- if (FAILED(hr))
- {
- return (-1);
- }
- WCHAR wfilename[_MAX_PATH];
- MULTI_TO_WIDE(wfilename, filename);
- // 初始化ObjDesc
- DD_INIT_STRUCT(ObjDesc);
- ObjDesc.guidClass = CLSID_DirectMusicSegment;
- wcscpy(ObjDesc.wszFileName, wfilename );
- ObjDesc.dwValidData = DMUS_OBJ_CLASS | DMUS_OBJ_FILENAME; //标记有效数据
- //取得DM 段
- hr = dm_loader->GetObject(&ObjDesc,IID_IDirectMusicSegment, (void**) &pSegment);
- if (FAILED(hr))
- return(-1);
- //设置midi相关参数
- hr = pSegment->SetParam(GUID_StandardMIDIFile,-1, 0, 0, (void*)dm_perf);
- if (FAILED(hr))
- return(-1);
- hr = pSegment->SetParam(GUID_Download, -1, 0, 0, (void*)dm_perf);
- if (FAILED(hr))
- return(-1);
- dm_midi[id].dm_segment = pSegment; //标记DM段
- dm_midi[id].dm_segstate = NULL;
- dm_midi[id].state = MIDI_LOADED; //标记状态
- return(id);
- }
- int DMusic_Play(int id)
- {
- if (dm_midi[id].dm_segment && dm_midi[id].state!=MIDI_NULL)
- {
- //如果当前有音乐在播放则关闭它
- if(dm_active_id!=-1)
- DMusic_Stop(dm_active_id);
- dm_perf->PlaySegment(dm_midi[id].dm_segment,0,0,&dm_midi[id].dm_segstate);
- dm_midi[id].state = MIDI_PLAYING;
- dm_active_id = id;
- return(1);
- }
- else
- return(0);
- }
- int DMusic_Stop(int id)
- {
- if (dm_midi[id].dm_segment && dm_midi[id].state!=NULL)
- {
- dm_perf->Stop(dm_midi[id].dm_segment,NULL,0,0);
- dm_midi[id].state = MIDI_STOPPED;
- // 重置活动的音乐索引id
- dm_active_id = -1;
- }
- return(1);
- }
- int DMusic_Delete_MIDI(int id)
- {
- if (dm_midi[id].dm_segment)
- {
- //首先卸载段
- dm_midi[id].dm_segment->SetParam(GUID_Unload,-1,0,0,(void*)dm_perf);
- //然后释放段内存
- dm_midi[id].dm_segment->Release();
- dm_midi[id].dm_segment = NULL;
- //重置标记
- dm_midi[id].dm_segstate = NULL;
- dm_midi[id].state = MIDI_NULL;
- }
- return(1);
- }
- int DMusic_Delete_All_MIDI(void)
- {
- //删除所有MIDI资源
- int index;
- for (index=0;index<DM_NUM_SEGMENTS;index++)
- {
- if (dm_midi[index].dm_segment)
- {
- dm_midi[index].dm_segment->SetParam(GUID_Unload,-1,0,0,(void*)dm_perf);
- dm_midi[index].dm_segment->Release();
- dm_midi[index].dm_segment = NULL;
- dm_midi[index].dm_segstate = NULL;
- dm_midi[index].state = MIDI_NULL;
- }
- }
- return(1);
- }
- int DMusic_Status_MIDI(int id)
- {
- //返回当前音乐播放状态
- if (dm_midi[id].dm_segment && dm_midi[id].state!=MIDI_NULL)
- {
- 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);
- }
- else
- return(0);
- }
- int DMusic_Init(void)
- {
- int index;
- //初始化COM
- if (FAILED(CoInitialize(NULL)))
- return(0);
- //创建DirectMusicPerformance接口对象
- if (FAILED(CoCreateInstance(CLSID_DirectMusicPerformance,
- NULL,
- CLSCTX_INPROC,
- IID_IDirectMusicPerformance,
- (void**)&dm_perf)))
- {
- return(0);
- }
- //初始化DMP (传入DS对象)
- if (FAILED(dm_perf->Init(NULL,lpds,main_window_handle)))
- {
- return(0);
- }
- //默认连接微软软件合成器端口
- if (FAILED(dm_perf->AddPort(NULL)))
- {
- return(0);
- }
- //创建midi加载器
- if (FAILED(CoCreateInstance(CLSID_DirectMusicLoader,
- NULL,
- CLSCTX_INPROC,
- IID_IDirectMusicLoader,
- (void**)&dm_loader)))
- {
- return(0);
- }
- //初始化dm_midi结构体
- for (index=0;index<DM_NUM_SEGMENTS;index++)
- {
- dm_midi[index].dm_segment = NULL;
- dm_midi[index].dm_segstate= NULL;
- dm_midi[index].state = MIDI_NULL;
- dm_midi[index].id = index;
- }
- dm_active_id = -1;
- return(1);
- }
- int DMusic_Shutdown(void)
- {
- //停止播放音乐
- if(dm_perf)
- dm_perf->Stop(NULL,NULL,0,0);
- //删除midi资源
- DMusic_Delete_All_MIDI();
- //释放dm_perf
- if (dm_perf)
- {
- dm_perf->CloseDown();
- dm_perf->Release();
- }
- //释放dm_loader
- if(dm_loader)
- dm_loader->Release();
- //释放COM
- CoUninitialize();
- return(1);
- }