void SNDDXDeInit() { DWORD status=0; doterminate = true; while(!terminated) Sleep(1); terminated = false; if (lpDSB2) { lpDSB2->GetStatus(&status); if(status == DSBSTATUS_PLAYING) lpDSB2->Stop(); lpDSB2->Release(); lpDSB2 = NULL; } if (lpDSB) { lpDSB->Release(); lpDSB = NULL; } if (lpDS8) { lpDS8->Release(); lpDS8 = NULL; } delete stereodata16; stereodata16=0; }
/******************************************************************* * shutdownDirectSound * Releases the DirecSound device *******************************************************************/ void D3DUtil::shutdownDirectSound(void) { if (g_pDS) { g_pDS->Release(); g_pDS = NULL; } }
void CloseSound() { if (lpds) { if (lpdsbPrimary) { lpdsbPrimary->Stop(); lpdsbPrimary->Release(); lpdsbPrimary = NULL; } lpds->Release(); lpds = NULL; } return; }
/* ================== SNDDMA_Shutdown ================== */ void SNDDMA_Shutdown( void ) { Com_DPrintf( "Shutting down sound system\n" ); if ( pDS ) { Com_DPrintf( "Destroying DS buffers\n" ); if ( pDS ) { Com_DPrintf( "...setting NORMAL coop level\n" ); pDS->SetCooperativeLevel( g_wv.hWnd, DSSCL_PRIORITY ); } if ( pDSBuf ) { Com_DPrintf( "...stopping and releasing sound buffer\n" ); pDSBuf->Stop(); pDSBuf->Release(); } // only release primary buffer if it's not also the mixing buffer we just released if ( pDSPBuf && ( pDSBuf != pDSPBuf ) ) { Com_DPrintf( "...releasing primary buffer\n" ); pDSPBuf->Release(); } pDSBuf = NULL; pDSPBuf = NULL; dma.buffer = NULL; Com_DPrintf( "...releasing DS object\n" ); pDS->Release(); } if ( hInstDS ) { Com_DPrintf( "...freeing DSOUND.DLL\n" ); FreeLibrary( hInstDS ); hInstDS = NULL; } pDS = NULL; pDSBuf = NULL; pDSPBuf = NULL; dsound_init = false; memset ((void *)&dma, 0, sizeof (dma)); CoUninitialize( ); }
BOOL COggDlg::ReleaseDXSound(void) { if(m_ds){ Closeds(); if(m_dsb3d != NULL){m_dsb3d->Release();m_dsb3d =NULL;} if(m_dsb != NULL) {m_dsb->Release();m_dsb=NULL;} if (m_dsb1 != NULL) { m_dsb1->Release(); m_dsb1 = NULL; } if(m_lpDS3DBuffer != NULL){m_lpDS3DBuffer->Release();} m_dsb =NULL; m_lpDS3DBuffer= NULL; if(m_p!=NULL){m_p->Release();m_p=NULL;} if(m_ds){ m_ds->Release(); m_ds = NULL; } } return TRUE; }
void DXAudioOutput::run() { HRESULT hr; DSBUFFERDESC dsbdesc; WAVEFORMATEXTENSIBLE wfx; WAVEFORMATEXTENSIBLE wfxSet; int ns = 0; unsigned int chanmasks[32]; LPDIRECTSOUND8 pDS = NULL; LPDIRECTSOUNDBUFFER pDSBPrimary = NULL; LPDIRECTSOUNDBUFFER pDSBOutput = NULL; LPDIRECTSOUNDNOTIFY8 pDSNotify = NULL; DWORD dwBufferSize; DWORD dwLastWritePos; DWORD dwLastPlayPos; DWORD dwTotalPlayPos; int iLastwriteblock; LPVOID aptr1, aptr2; DWORD nbytes1, nbytes2; int playblock; int nowriteblock; DWORD dwPlayPosition, dwWritePosition; unsigned int iByteSize; bool bOk; DWORD dwSpeakerConfig; bool failed = false; bOk = false; DWORD dwMask = 0; bool bHead = false; ZeroMemory(&dsbdesc, sizeof(DSBUFFERDESC)); dsbdesc.dwSize = sizeof(DSBUFFERDESC); dsbdesc.dwFlags = DSBCAPS_PRIMARYBUFFER; if (! g.s.qbaDXOutput.isEmpty()) { LPGUID lpguid = reinterpret_cast<LPGUID>(g.s.qbaDXOutput.data()); if (FAILED(hr = DirectSoundCreate8(lpguid, &pDS, NULL))) { failed = true; } } if (! pDS && FAILED(hr = DirectSoundCreate8(&DSDEVID_DefaultVoicePlayback, &pDS, NULL))) { qWarning("DXAudioOutput: DirectSoundCreate failed: hr=0x%08lx", hr); goto cleanup; } else if (FAILED(hr = pDS->SetCooperativeLevel(g.mw->winId(), DSSCL_PRIORITY))) { qWarning("DXAudioOutput: SetCooperativeLevel failed: hr=0x%08lx", hr); goto cleanup; } else if (FAILED(hr = pDS->CreateSoundBuffer(&dsbdesc, &pDSBPrimary, NULL))) { qWarning("DXAudioOutput: CreateSoundBuffer (Primary) failed: hr=0x%08lx", hr); goto cleanup; } pDS->GetSpeakerConfig(&dwSpeakerConfig); switch (DSSPEAKER_CONFIG(dwSpeakerConfig)) { case DSSPEAKER_HEADPHONE: dwMask = KSAUDIO_SPEAKER_STEREO; bHead = true; break; case DSSPEAKER_MONO: dwMask = KSAUDIO_SPEAKER_MONO; break; case DSSPEAKER_QUAD: dwMask = KSAUDIO_SPEAKER_QUAD; break; case DSSPEAKER_STEREO: dwMask = KSAUDIO_SPEAKER_STEREO; break; case DSSPEAKER_SURROUND: dwMask = KSAUDIO_SPEAKER_SURROUND; break; case DSSPEAKER_5POINT1: dwMask = KSAUDIO_SPEAKER_5POINT1; break; case DSSPEAKER_7POINT1: dwMask = KSAUDIO_SPEAKER_7POINT1; break; case DSSPEAKER_7POINT1_SURROUND: dwMask = KSAUDIO_SPEAKER_7POINT1_SURROUND; break; case DSSPEAKER_5POINT1_SURROUND: dwMask = KSAUDIO_SPEAKER_5POINT1_SURROUND; break; default: dwMask = 0; break; } if (! g.s.doPositionalAudio()) dwMask = KSAUDIO_SPEAKER_MONO; for (int i=0;i<32;i++) { if (dwMask & (1 << i)) { chanmasks[ns++] = 1 << i; } } iMixerFreq = SAMPLE_RATE; iChannels = ns; eSampleFormat = SampleShort; iByteSize = iFrameSize * sizeof(short) * ns; ZeroMemory(&wfxSet, sizeof(wfxSet)); wfxSet.Format.wFormatTag = WAVE_FORMAT_PCM; ZeroMemory(&wfx, sizeof(wfx)); wfx.Format.wFormatTag = WAVE_FORMAT_PCM; wfx.Format.nChannels = qMax(ns, 1); wfx.Format.nSamplesPerSec = SAMPLE_RATE; wfx.Format.nBlockAlign = sizeof(short) * wfx.Format.nChannels; wfx.Format.nAvgBytesPerSec = wfx.Format.nSamplesPerSec * wfx.Format.nBlockAlign; wfx.Format.wBitsPerSample = 16; if (FAILED(hr = pDSBPrimary->SetFormat(reinterpret_cast<WAVEFORMATEX *>(&wfx)))) { qWarning("DXAudioOutput: SetFormat failed: hr=0x%08lx", hr); goto cleanup; } if (FAILED(hr = pDSBPrimary->GetFormat(reinterpret_cast<WAVEFORMATEX *>(&wfxSet), sizeof(wfxSet), NULL))) { qWarning("DXAudioOutput: GetFormat failed: hr=0x%08lx", hr); goto cleanup; } qWarning("DXAudioOutput: Primary buffer of %ld Hz, %d channels, %d bits",wfxSet.Format.nSamplesPerSec,wfxSet.Format.nChannels,wfxSet.Format.wBitsPerSample); ZeroMemory(&wfx, sizeof(wfx)); wfx.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; wfx.Format.nChannels = ns; wfx.Format.nSamplesPerSec = SAMPLE_RATE; wfx.Format.nBlockAlign = sizeof(short) * wfx.Format.nChannels; wfx.Format.nAvgBytesPerSec = wfx.Format.nSamplesPerSec * wfx.Format.nBlockAlign; wfx.Format.wBitsPerSample = 16; wfx.Format.cbSize = 32; wfx.Samples.wValidBitsPerSample = wfx.Format.wBitsPerSample; wfx.dwChannelMask = dwMask; wfx.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; ZeroMemory(&dsbdesc, sizeof(DSBUFFERDESC)); dsbdesc.dwSize = sizeof(DSBUFFERDESC); dsbdesc.dwFlags = DSBCAPS_GLOBALFOCUS|DSBCAPS_GETCURRENTPOSITION2; dsbdesc.dwFlags |= DSBCAPS_CTRLPOSITIONNOTIFY; dsbdesc.dwBufferBytes = wfx.Format.nChannels * iFrameSize * sizeof(short) * NBLOCKS; dsbdesc.lpwfxFormat = reinterpret_cast<WAVEFORMATEX *>(&wfx); if (FAILED(hr = pDS->CreateSoundBuffer(&dsbdesc, &pDSBOutput, NULL))) { qWarning("DXAudioOutputUser: CreateSoundBuffer (Secondary) failed: hr=0x%08lx", hr); goto cleanup; } if (FAILED(hr = pDSBOutput->QueryInterface(IID_IDirectSoundNotify, reinterpret_cast<void **>(&pDSNotify)))) { qWarning("DXAudioOutputUser: QueryInterface (Notify) failed: hr=0x%08lx", hr); goto cleanup; } qWarning("DXAudioOutputUser: New %dHz output buffer of %ld bytes", SAMPLE_RATE, dsbdesc.dwBufferBytes); if (failed) g.mw->msgBox(tr("Opening chosen DirectSound Output failed. Default device will be used.")); initializeMixer(chanmasks, bHead); if (FAILED(hr = pDSBOutput->Lock(0, 0, &aptr1, &nbytes1, &aptr2, &nbytes2, DSBLOCK_ENTIREBUFFER))) { qWarning("DXAudioOutputUser: Initial Lock failed: hr=0x%08lx", hr); goto cleanup; } dwBufferSize = nbytes1 + nbytes2; if (aptr1) ZeroMemory(aptr1, nbytes1); if (aptr2) ZeroMemory(aptr2, nbytes2); if (FAILED(hr = pDSBOutput->Unlock(aptr1, nbytes1, aptr2, nbytes2))) { qWarning("DXAudioOutputUser: Initial Unlock failed: hr=0x%08lx", hr); goto cleanup; } if (FAILED(hr = pDSBOutput->Play(0, 0, DSBPLAY_LOOPING))) { qWarning("DXAudioOutputUser: Play failed: hr=0x%08lx", hr); goto cleanup; } dwLastWritePos = 0; dwLastPlayPos = 0; dwTotalPlayPos = 0; iLastwriteblock = (NBLOCKS - 1 + g.s.iOutputDelay) % NBLOCKS; bOk = true; while (bRunning && ! FAILED(hr)) { if (FAILED(hr = pDSBOutput->GetCurrentPosition(&dwPlayPosition, &dwWritePosition))) { qWarning("DXAudioOutputUser: GetCurrentPosition failed: hr=0x%08lx", hr); break; } playblock = dwWritePosition / iByteSize; nowriteblock = (playblock + g.s.iOutputDelay + 1) % NBLOCKS; for (int block=(iLastwriteblock + 1) % NBLOCKS;(!FAILED(hr)) && (block!=nowriteblock);block=(block + 1) % NBLOCKS) { iLastwriteblock = block; if (FAILED(hr = pDSBOutput->Lock(block * iByteSize, iByteSize, &aptr1, &nbytes1, &aptr2, &nbytes2, 0))) { qWarning("DXAudioOutput: Lock block %u (%d bytes) failed: hr=0x%08lx",block, iByteSize, hr); break; } if (aptr2 || nbytes2) { qWarning("DXAudioOutput: Split buffer"); break; } if (!aptr1 || ! nbytes1) { qWarning("DXAudioOutput: Zerolock"); break; } if (! mix(reinterpret_cast<short *>(aptr1), iFrameSize)) ZeroMemory(aptr1, iByteSize); if (FAILED(hr = pDSBOutput->Unlock(aptr1, nbytes1, aptr2, nbytes2))) { qWarning("DXAudioOutput: Unlock %p(%lu) %p(%lu) failed: hr=0x%08lx",aptr1,nbytes1,aptr2,nbytes2,hr); break; } if (FAILED(hr = pDSBOutput->GetCurrentPosition(&dwPlayPosition, &dwWritePosition))) { qWarning("DXAudioOutputUser: GetCurrentPosition failed: hr=0x%08lx", hr); break; } playblock = dwWritePosition / iByteSize; nowriteblock = (playblock + g.s.iOutputDelay + 1) % NBLOCKS; } if (! FAILED(hr)) msleep(19); } if (FAILED(hr)) { g.mw->msgBox(tr("Lost DirectSound output device.")); } cleanup: if (! bOk) { g.mw->msgBox(tr("Opening chosen DirectSound Output failed. No audio will be heard.")); return; } if (pDSNotify) pDSNotify->Release(); if (pDSBOutput) { pDSBOutput->Stop(); pDSBOutput->Release(); } if (pDSBPrimary) pDSBPrimary->Release(); if (pDS) pDS->Release(); }
/* ================== FreeSound ================== */ void FreeSound (void) { int i; Com_Printf( "Shutting down sound system\n" ); if ( pDS ) DS_DestroyBuffers(); if ( hWaveOut ) { Com_Printf( "...resetting waveOut\n" ); waveOutReset (hWaveOut); if (lpWaveHdr) { Com_Printf( "...unpreparing headers\n" ); for (i=0 ; i< WAV_BUFFERS ; i++) waveOutUnprepareHeader (hWaveOut, lpWaveHdr+i, sizeof(WAVEHDR)); } Com_Printf( "...closing waveOut\n" ); waveOutClose (hWaveOut); if (hWaveHdr) { Com_Printf( "...freeing WAV header\n" ); GlobalUnlock(hWaveHdr); GlobalFree(hWaveHdr); } if (hData) { Com_Printf( "...freeing WAV buffer\n" ); GlobalUnlock(hData); GlobalFree(hData); } } if ( pDS ) { Com_Printf( "...releasing DirectSound 8 object\n" ); #ifdef QDSNDCOMPILERHACK pDS->lpVtbl->Release(pDS); #else pDS->Release(); #endif } if ( hInstDS ) { Com_Printf( "...freeing dsound.dll\n" ); FreeLibrary( hInstDS ); hInstDS = NULL; } pDS = NULL; pDSBuf = NULL; pDSPBuf = NULL; hWaveOut = 0; hData = 0; hWaveHdr = 0; lpData = NULL; lpWaveHdr = NULL; dsound_init = 0; wav_init = 0; }
/*** DLLメイン関数 ***/ BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { CHAR path[512],file[128],ext[64]; switch(ul_reason_for_call) { case DLL_PROCESS_DETACH: GetModuleFileName(NULL, path,MAX_PATH-1); DEBUG_OUT("AsukaLibは Module %s から切り離されました\n",path); DestroyMenu(MainPopup); if(D3D8inst) FreeLibrary(D3D8inst); if(DI8inst) FreeLibrary(DI8inst); if(DS8inst) FreeLibrary(DS8inst); if(MainDI8) MainDI8->Release();// DirectInputは明示的に生成したからRelease if(MainDS8) MainDS8->Release();// if(bIniLoaded) SaveIniData(&Ini); ReleaseSoundBufferChain(); return TRUE; case DLL_PROCESS_ATTACH: bIniLoaded = FALSE; GetModuleFileName(NULL, path,MAX_PATH-1); DEBUG_OUT("AsukaLibは Module %s から呼び出されました\n",path); hDLL = hModule; break; default: return TRUE; } GetModuleFileName(NULL,path,MAX_PATH-1); _splitpath_s(path,NULL,0,NULL,0,file,ARRAYSIZE(file),ext,ARRAYSIZE(ext)); strcat_s(file,ARRAYSIZE(file),ext); if(lstrcmpi(file,TARGET_EXE) != 0) { DEBUG_OUT("%sによるDLL呼び出しなのでフック中止(Target: %s)\n",file,TARGET_EXE); return TRUE; } LoadIniData(&Ini); bIniLoaded = TRUE; // ポップアップメニューのロード MainPopup = LoadMenu((HINSTANCE)hModule,MAKEINTRESOURCE(ID_POPUPMENU)); SubPopup = GetSubMenu(MainPopup,0); // Iniからデフォルト状態の復帰 CheckMenuItem(SubPopup,IDM_MUTE_BGM,Ini.BGMMute?MF_CHECKED:MF_UNCHECKED); CheckMenuItem(SubPopup,IDM_MUTE_SE,Ini.SEMute?MF_CHECKED:MF_UNCHECKED); CheckMenuItem(SubPopup,IDM_LOCK_CONFIG,Ini.LockConfig?MF_CHECKED:MF_UNCHECKED); CheckMenuItem(SubPopup,IDC_SAVEWINDOWSET,Ini.SaveWindowSettings?MF_CHECKED:MF_UNCHECKED); CheckMenuItem(SubPopup,IDM_RESIZABLE,Ini.WindowResizable?MF_CHECKED:MF_UNCHECKED); CheckMenuItem(SubPopup,IDM_HOLDASPECTRATIO,Ini.HoldAspectRatio?MF_CHECKED:MF_UNCHECKED); EnableMenuItem(SubPopup,IDM_HOLDASPECTRATIO,Ini.WindowResizable?MF_ENABLED:MF_GRAYED); EnableMenuItem(SubPopup,IDM_SIZE_640,Ini.WindowResizable?MF_ENABLED:MF_GRAYED); EnableMenuItem(SubPopup,IDM_SIZE_800,Ini.WindowResizable?MF_ENABLED:MF_GRAYED); EnableMenuItem(SubPopup,IDM_SIZE_960,Ini.WindowResizable?MF_ENABLED:MF_GRAYED); // Direct3Dをロード GetSystemDirectory(path,ARRAYSIZE(path)); strcat_s(path,ARRAYSIZE(path),"\\d3d8.dll"); D3D8inst = LoadLibrary(path); fpD3DCreate8 = (FuncPtrDirect3DCreate8)GetProcAddress(D3D8inst, "Direct3DCreate8"); // DirectInput8をロード GetSystemDirectory(path,ARRAYSIZE(path)); strcat_s(path,ARRAYSIZE(path),"\\dinput8.dll"); DI8inst = LoadLibrary(path); fpDI8Create = (FuncPtrDirectInput8Create)GetProcAddress(DI8inst, "DirectInput8Create"); // DirectSound8をロード GetSystemDirectory(path,ARRAYSIZE(path)); strcat_s(path,ARRAYSIZE(path),"\\dsound.dll"); DS8inst = LoadLibrary(path); fpDSCreate8 = (FuncPtrDirectSoundCreate8)GetProcAddress(DS8inst, "DirectSoundCreate8"); return TRUE; }
int main() { using namespace flamenco; LPDIRECTSOUND8 directSound; // Создаем интерфейс DirectSound. check_directx(DirectSoundCreate8(&GUID_NULL, &directSound, NULL)); check_directx(directSound->SetCooperativeLevel(GetForegroundWindow(), DSSCL_PRIORITY)); // Получаем первичный буфер. LPDIRECTSOUNDBUFFER primaryBuffer = NULL; DSBUFFERDESC descr; ZeroMemory(&descr, sizeof(DSBUFFERDESC)); descr.dwSize = sizeof(DSBUFFERDESC); descr.dwFlags = DSBCAPS_PRIMARYBUFFER; descr.lpwfxFormat = NULL; check_directx(directSound->CreateSoundBuffer(&descr, &primaryBuffer, NULL)); // Изменяем формат первичного буфера. WAVEFORMATEX wfx; ZeroMemory(&wfx, sizeof(WAVEFORMATEX)); wfx.cbSize = sizeof(WAVEFORMATEX); wfx.wFormatTag = WAVE_FORMAT_PCM; wfx.nChannels = 2; wfx.nSamplesPerSec = FREQUENCY; wfx.wBitsPerSample = 16; wfx.nBlockAlign = wfx.wBitsPerSample / 8 * wfx.nChannels; wfx.nAvgBytesPerSec = (u32)wfx.nSamplesPerSec * wfx.nBlockAlign; check_directx(primaryBuffer->SetFormat(&wfx)); primaryBuffer->Release(); // Формат буфера микшера. const u32 MIXER_BUFFER_SIZE_IN_BYTES = MIXER_BUFFER_SIZE_IN_SAMPLES * sizeof(s16); // Размер звукового буфера должен быть больше 100 ms, иначе GetCurrentPosition() // будет выдавать неправильные данные. const u32 SOUND_BUFFER_SIZE_IN_BYTES = 10 * MIXER_BUFFER_SIZE_IN_BYTES; DSBUFFERDESC desc; ZeroMemory(&desc, sizeof(DSBUFFERDESC)); desc.dwSize = sizeof(DSBUFFERDESC); desc.dwFlags = DSBCAPS_LOCSOFTWARE | DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_GLOBALFOCUS; desc.dwBufferBytes = SOUND_BUFFER_SIZE_IN_BYTES; desc.guid3DAlgorithm = DS3DALG_DEFAULT; desc.lpwfxFormat = &wfx; // Создаем буфер. LPDIRECTSOUNDBUFFER soundBuffer = NULL; check_directx(directSound->CreateSoundBuffer(&desc, &soundBuffer, NULL)); //reference<stream<ogg_decoder> > sound = stream<ogg_decoder>::create(std::auto_ptr<source>(new file_source("input.ogg"))); // Инициализация flamenco. mixer & mixer = mixer::singleton(); reference<sound_stream_base> sound = stream<wavpack_decoder>::create(std::auto_ptr<source>(new file_source("input.wv"))); //assert(!src.get()); mixer.attach(sound); /* reference<pin> sine = sine::create(400); reference<ogg> wave = ogg::create("input.ogg"); reference<pin> noise = noise::create(); reference<volume_pan> vp = volume_pan::create(sound, 1.0f, 0.0f); //mixer.attach(sine); mixer.attach(vp); //mixer.attach(noise); */ // Заполнение звукового буфера. s16 * bufferPtr; u32 bufferSize; check_directx(soundBuffer->Lock(0, 0, reinterpret_cast<void **>(&bufferPtr), &bufferSize, NULL, NULL, DSBLOCK_ENTIREBUFFER)); // Заполняем обе половинки буфера. mixer.mix(bufferPtr); mixer.mix(bufferPtr + MIXER_BUFFER_SIZE_IN_SAMPLES); check_directx(soundBuffer->Unlock(bufferPtr, bufferSize, NULL, 0)); // Проигрываем звук и дописываем данные по ходу. soundBuffer->Play(0, 0, DSBPLAY_LOOPING); u32 writeOffset = MIXER_BUFFER_SIZE_IN_BYTES * 2; while (true) { u32 cursorPos; soundBuffer->GetCurrentPosition(&cursorPos, NULL); // Определяем, нужно ли дописать очередную порцию данных. u32 offset = (SOUND_BUFFER_SIZE_IN_BYTES + writeOffset - cursorPos) % SOUND_BUFFER_SIZE_IN_BYTES; if (offset > MIXER_BUFFER_SIZE_IN_BYTES) { check_directx(soundBuffer->Lock(writeOffset, MIXER_BUFFER_SIZE_IN_BYTES, reinterpret_cast<void **>(&bufferPtr), &bufferSize, NULL, NULL, 0)); mixer.mix(bufferPtr); check_directx(soundBuffer->Unlock(bufferPtr, bufferSize, NULL, 0)); writeOffset = (writeOffset + MIXER_BUFFER_SIZE_IN_BYTES) % SOUND_BUFFER_SIZE_IN_BYTES; } // Не нужно опрашивать GetCurrentPosition() слишком часто. Sleep(LATENCY_MSEC >> 1); if (_kbhit()) { switch (_getch()) { case '+': //vp->pan.set(vp->pan() + 0.1f); continue; case '-': //vp->pan.set(vp->pan() - 0.1f); continue; case 'l': sound->looping.set(!sound->looping()); continue; } // Если нажата любая другая клавиша - выходим. break; } } // Освобождение ресурсов. soundBuffer->Release(); directSound->Release(); }
void KillDSound() { ds8->Release(); }