static int InitDSound(HWND hWnd) { HRESULT hr; pDirectSoundCreate8 SoundCreate; dsoundDLL = LoadLibrary("dsound.dll"); if (dsoundDLL == NULL) { WriteLog("not find dsound.dll"); } SoundCreate = (pDirectSoundCreate8)GetProcAddress(dsoundDLL, "DirectSoundCreate8"); hr = SoundCreate(NULL, &lpDS, NULL); if (FAILED(hr)) { goto end; } hr = lpDS->SetCooperativeLevel(hWnd, DSSCL_PRIORITY); if (FAILED(hr)) { goto end; } DSBUFFERDESC desc; ZeroMemory(&desc,sizeof(DSBUFFERDESC)); desc.dwSize = sizeof(DSBUFFERDESC); desc.dwFlags = DSBCAPS_PRIMARYBUFFER; hr = lpDS->CreateSoundBuffer(&desc, &lpDSP, NULL); if (FAILED(hr)) { goto end; } WriteLog("init sound\n"); return 1; end: return 0; }
bool Dsoundinit( HWND hwnd ) { // SBArrの初期化 initSBArr(); // DirectSound8 の作成 if (FAILED(DirectSoundCreate8(NULL,&lpDS,NULL))) { MessageBox(NULL,"DirectSound オブジェクトの作成に失敗しました。","DirectSoundエラー",MB_OK | MB_ICONSTOP); return false; } // DirectSound の協調レベルを設定 if (FAILED(lpDS->SetCooperativeLevel(hwnd,DSSCL_PRIORITY))) { MessageBox(NULL,"DirectSound の協調レベルの設定に失敗しました。","DirectSoundエラー",MB_OK | MB_ICONSTOP); // 閉じる SendMessage(hwnd,WM_CLOSE,0,0); return false; } // プライマリ サウンドバッファ作成 DSBUFFERDESC desc; ZeroMemory(&desc,sizeof(DSBUFFERDESC)); desc.dwSize = sizeof(DSBUFFERDESC); desc.dwFlags = DSBCAPS_PRIMARYBUFFER; if (FAILED(lpDS->CreateSoundBuffer(&desc,&lpDSP,NULL))) { MessageBox(NULL,"プライマリサウンドバッファの作成に失敗しました。","DirectSoundエラー",MB_OK | MB_ICONSTOP); // 閉じる SendMessage(hwnd,WM_CLOSE,0,0); return false; } //ここまでは一回行えばOKの処理 //SEの数だけセカンダリバッファにデータ読み込み //読み込みファイル名をリストから読み込む initSBFileList(); int nCount; for(nCount = 0;nCount <= SE_MAX - 1;nCount++){ // WAVE ファイルの読み込み // MessageBox(NULL,SBArr[nCount].cSeFileName,"",MB_OK); SBArr[nCount].SB_lpDSB = LoadWave(SBArr[nCount].cSeFileName); //効果音 if (SBArr[nCount].SB_lpDSB == NULL) { MessageBox(NULL,"ファイルの読み込みに失敗しました。","DirectSoundエラー",MB_OK | MB_ICONSTOP); // 閉じる SendMessage(hwnd,WM_CLOSE,0,0); return false; } } return true; }
SOUNDBUFFER CreateBuffer() { LPDIRECTSOUNDBUFFER ret; ds8->CreateSoundBuffer(&bufdesc, &ret, NULL); ret->SetVolume(1000); return ((int*)ret); }
static LPDIRECTSOUNDBUFFER OpenSoundFile(char *name) { DSBUFFERDESC DSBufDESC; WAVEFORMATEX waveFormat; void* buf; DWORD size; HMMIO hmmio; MMCKINFO cParent, cSub; LPDIRECTSOUNDBUFFER lpDSBuf = NULL; MMIOINFO mem; int fileSize; char *data = LoadFile(name, &fileSize); memset(&mem, 0, sizeof(MMIOINFO)); mem.pchBuffer = data; mem.cchBuffer = fileSize; mem.fccIOProc = FOURCC_MEM; hmmio = mmioOpen(NULL, &mem, MMIO_ALLOCBUF | MMIO_READ); cParent.fccType = mmioFOURCC('W','A','V','E'); if (mmioDescend(hmmio, &cParent, NULL, MMIO_FINDRIFF) != MMSYSERR_NOERROR) { return NULL; } cSub.ckid = mmioFOURCC('f','m','t',' '); if (mmioDescend(hmmio, &cSub, &cParent, MMIO_FINDCHUNK) != MMSYSERR_NOERROR) { goto end; } mmioRead(hmmio, (char*)&waveFormat, cSub.cksize); mmioAscend(hmmio, &cSub, 0); if (waveFormat.wFormatTag != WAVE_FORMAT_PCM) { goto end; } cSub.ckid = mmioFOURCC('d','a','t','a'); if (mmioDescend(hmmio, &cSub, &cParent, MMIO_FINDCHUNK) != MMSYSERR_NOERROR) { goto end; } ZeroMemory(&DSBufDESC, sizeof(DSBUFFERDESC)); DSBufDESC.dwSize = sizeof(DSBUFFERDESC); DSBufDESC.dwFlags = DSBCAPS_CTRLPAN|DSBCAPS_CTRLVOLUME|DSBCAPS_GLOBALFOCUS; DSBufDESC.dwBufferBytes = cSub.cksize; DSBufDESC.lpwfxFormat = &waveFormat; lpDS->CreateSoundBuffer(&DSBufDESC, &lpDSBuf, NULL); lpDSBuf->Lock(0, cSub.cksize, &buf, &size, NULL, 0, 0); mmioRead(hmmio, (HPSTR)buf, (LONG)cSub.cksize); lpDSBuf->Unlock(buf, size, NULL, 0); mmioClose(hmmio, MMIO_FHOPEN); return lpDSBuf; end: mmioClose(hmmio, MMIO_FHOPEN); free(data); return NULL; }
BOOL InitSound() { DSBUFFERDESC dsbdesc; if (!hWnd) { return true; } if (!lpds) { //Create DirectSound interface if (DirectSoundCreate8(NULL, &lpds, NULL)) { Error("DirectSoundCreate8(NULL, &lpds, NULL)"); return true; } //Set cooperative level if (lpds->SetCooperativeLevel(hWnd, DSSCL_NORMAL)) { Error("lpds->SetCooperativeLevel(hWnd, DSSCL_NORMAL)"); CloseSound(); return true; } } //Get primary buffer and set it to run silently if (!lpdsbPrimary) { ZeroMemory(&dsbdesc, sizeof(dsbdesc)); dsbdesc.dwSize = sizeof(dsbdesc); dsbdesc.dwFlags = DSBCAPS_PRIMARYBUFFER; if (lpds->CreateSoundBuffer(&dsbdesc, &lpdsbPrimary, NULL)) { Error("lpds->CreateSoundBuffer(&dsbdesc, &lpdsbPrimary, NULL)"); CloseSound(); return true; } if (lpdsbPrimary->Play(0, 0, DSBPLAY_LOOPING)) { Error("lpdsbPrimary->Play(0, 0, DSBPLAY_LOOPING)"); CloseSound(); return true; } } Settings.SoundEnabled = true; return false; }
// WAVE ファイルの読み込み LPDIRECTSOUNDBUFFER LoadWave(char *name) { char *buf; UINT readsize; WAVEFORMATEX wf; LPDIRECTSOUNDBUFFER lpDSB = NULL; DSBUFFERDESC desc; LPVOID pMem1,pMem2; DWORD size1,size2; // WAVE ファイルを開く if (!YWaveOpen(name)) { return NULL; } // メモリ領域の確保 buf = (char *)malloc(m_ckIn.cksize); // 読み込み ZeroMemory(&wf,sizeof(WAVEFORMATEX)); if (!YWaveRead(m_ckIn.cksize,buf,&readsize,&wf)) { free(buf); return NULL; } // サウンドバッファの作成 ZeroMemory(&desc,sizeof(DSBUFFERDESC)); desc.dwSize = sizeof(DSBUFFERDESC); desc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_GLOBALFOCUS | DSBCAPS_LOCDEFER | DSBCAPS_CTRLVOLUME; desc.dwBufferBytes = readsize; desc.lpwfxFormat = &wf; if (FAILED(lpDS->CreateSoundBuffer(&desc,&lpDSB,NULL))) { free(buf); return NULL; } // 領域をロック if (FAILED(lpDSB->Lock(0,readsize,&pMem1,&size1,&pMem2,&size2,0))) { free(buf); return 0; } // 書き込み memcpy(pMem1,buf,size1); if (size2) { memcpy(pMem2,buf + size1,size2); } // ロック解除 lpDSB->Unlock(pMem1,size1,pMem2,size2); free(buf); // 閉じる YWaveClose(); return lpDSB; }
//获得3D收听对象 HRESULT get3DListener(LPDIRECTSOUND8 lpds, LPDIRECTSOUND3DBUFFER8* ppListener){ DSBUFFERDESC dsbd; LPDIRECTSOUNDBUFFER lpdsbPrimary; LPDIRECTSOUND3DLISTENER lp3DListener = NULL; HRESULT hr; ZeroMemory(&dsbd, sizeof(DSBUFFERDESC)); dsbd.dwSize = sizeof(DSBUFFERDESC); dsbd.dwFlags = DSBCAPS_CTRL3D | DSBCAPS_PRIMARYBUFFER; if (SUCCEEDED(hr = lpds->CreateSoundBuffer(&dsbd, &lpdsbPrimary, NULL))){ hr = lpdsbPrimary->QueryInterface(IID_IDirectSound3DListener8, (LPVOID*)ppListener); lpdsbPrimary->Release(); } return hr; }
BOOL ApplicationCreateWritePrimaryBuffer( LPDIRECTSOUND8 lpDirectSound, LPDIRECTSOUNDBUFFER8 *lplpDsb, LPDWORD lpdwBufferSize, HWND hwnd ){ DSBUFFERDESC dsbdesc; DSBCAPS dsbcaps; HRESULT hr; WAVEFORMATEX wf; memset(&wf, 0, sizeof(WAVEFORMATEX)); wf.wFormatTag = WAVE_FORMAT_PCM; wf.nChannels = 2; wf.nSamplesPerSec = 22050; wf.nBlockAlign = 4; wf.nAvgBytesPerSec = wf.nSamplesPerSec * wf.nBlockAlign; wf.wBitsPerSample = 16; memset(&dsbdesc, 0, sizeof(DSBUFFERDESC)); dsbdesc.dwSize = sizeof(DSBUFFERDESC); dsbdesc.dwFlags = DSBCAPS_PRIMARYBUFFER; //缓存大小由声音硬件返回 dsbdesc.dwBufferBytes = 0; dsbdesc.lpwfxFormat = NULL;//对于主缓存来说必须是NULL //得到写数据协作权限 hr = lpDirectSound->SetCooperativeLevel(hwnd, DSSCL_WRITEPRIMARY); if (SUCCEEDED(hr)){ hr = lpDirectSound->CreateSoundBuffer(&dsbdesc, lplpDsb, NULL); if (SUCCEEDED(hr)){ hr = (*lplpDsb)->SetFormat(&wf); if (SUCCEEDED(hr)){ dsbcaps.dwSize = sizeof(DSBCAPS); (*lplpDsb)->GetCaps(&dsbcaps); *lpdwBufferSize = dsbcaps.dwBufferBytes; return TRUE; } } } //失败 *lplpDsb = NULL; *lpdwBufferSize = 0; return FALSE; }
CString COggDlg::init(HWND hwnd,int sm) { DirectSoundCreate8(NULL,&m_ds,NULL); if(m_ds==NULL) return _T("DirectSoundを生成できません。\nDirectX7が正常にインストールされているか確認してください。"); if(m_ds->SetCooperativeLevel(hwnd,DSSCL_PRIORITY)!=DS_OK){ return _T("DirectSoundの強調レベルを設定できません。\nDirectX7が正常にインストールされているか確認してください。"); } hw=0; // ZeroMemory(&d,sizeof(d));d.dwSize=sizeof(d);HRESULT r =m_ds->GetCaps(&d); // if(r!=DS_OK){ // return "DirectSoundの情報を獲得出来ません。\nDirectX7が正常にインストールされているか確認してください。"; // } // if(d.dwFlags & (DSCAPS_SECONDARYSTEREO|DSCAPS_PRIMARYSTEREO |DSCAPS_PRIMARY16BIT) && d.dwFreeHwMemBytes!=0){ // hw=DSBCAPS_LOCHARDWARE; // }::timeSetEvent m_p=NULL; DSBUFFERDESC dss; ZeroMemory(&dss,sizeof(dss)); dss.dwSize=sizeof(dss); // dss.dwFlags=DSBCAPS_CTRL3D | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLPAN | DSBCAPS_CTRLFREQUENCY|DSBCAPS_PRIMARYBUFFER|hw; dss.dwFlags=DSBCAPS_PRIMARYBUFFER; dss.lpwfxFormat=NULL; dss.dwBufferBytes=0; if(m_ds->CreateSoundBuffer(&dss,&m_p,NULL)!=DS_OK){ return _T("DirectSoundのプライマリバッファを生成できません。\nDirectX7が正常にインストールされているか確認してください。"); } if(m_p!=NULL){ // //PCMWAVEFORMAT p; WAVEFORMATEX p; ZeroMemory(&p,sizeof(p)); p.wFormatTag=WAVE_FORMAT_PCM; p.nChannels= wavch; p.nSamplesPerSec= wavbit; p.wBitsPerSample = wavsam; p.nBlockAlign = p.nChannels * p.wBitsPerSample / 8; p.nAvgBytesPerSec = p.nSamplesPerSec * p.nBlockAlign; p.cbSize = 0; m_p->SetFormat(&p); } //m_p->QueryInterface(IID_IDirectSound3DListener, (LPVOID*)&m_listener); //m_listener->SetPosition(0.0f, 0.0f, 0.0f, DS3D_IMMEDIATE); return _T(""); }
//get the DIRECTSOUNDBUFFER8 interface HRESULT CreateBaseBuffer(LPDIRECTSOUND8 lpDirectSound, LPDIRECTSOUNDBUFFER8 * ppDsb8){ WAVEFORMATEX wfx; DSBUFFERDESC dsbdesc; LPDIRECTSOUNDBUFFER pDsb = NULL; HRESULT hr; //set up WAV buffer format memset(&wfx, 0, sizeof(WAVEFORMATEX)); wfx.wFormatTag = WAVE_FORMAT_PCM; wfx.nChannels = 2; wfx.nSamplesPerSec = 22050; wfx.nBlockAlign = 4; wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign; wfx.wBitsPerSample = 16; //set up DSBUFFERDESC structure memset(&dsbdesc, 0, sizeof(DSBUFFERDESC)); dsbdesc.dwSize = sizeof(DSBUFFERDESC); //the rule of using following flags is that use only what you will control dsbdesc.dwFlags = DSBCAPS_CTRLPAN | DSBCAPS_CTRLVOLUME | //IDirectSound::SetVolume() is success only if this flag was set DSBCAPS_CTRLFREQUENCY | DSBCAPS_GLOBALFOCUS; //ensure that even if the window is in the backgroud,that mean you can hear the sound when you lose the focus of the window dsbdesc.dwBufferBytes = 3 * wfx.nAvgBytesPerSec;//create a buffer that is big enough to hold 3 seconds of streaming data dsbdesc.lpwfxFormat = &wfx;//if the was not specified, ds will place it in hardware-controlled memory. //you can check the location of the buffer by using GetCaps() function, //create buffer hr = lpDirectSound->CreateSoundBuffer(&dsbdesc, &pDsb, NULL); if (SUCCEEDED(hr)){ hr = pDsb->QueryInterface(IID_IDirectSoundBuffer8, (LPVOID*)ppDsb8); pDsb->Release(); } //the created buffer owned by device object,and released when device object release the resources //you can also create multiple buffer by using function IDirectSound8::DuplicateSoundBuffer(),but the memory is share with original buffer,so if one buffer changed,others will be reflected. return hr; }
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(); }
BOOL NewSoundBuffer(SOUNDBUFFER *pSoundBuffer) { DSBPOSITIONNOTIFY dsbpn[3]; DSBUFFERDESC dsbd; WAVEFORMATEX wfx; DWORD dw; wfx.wFormatTag = WAVE_FORMAT_PCM; wfx.nChannels = 2; wfx.nSamplesPerSec = 22050; wfx.wBitsPerSample = 8; wfx.nBlockAlign = wfx.wBitsPerSample / 8 * wfx.nChannels; wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign; ZeroMemory(&dsbd, sizeof(dsbd)); dsbd.dwSize = sizeof(dsbd); dsbd.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_GLOBALFOCUS | DSBCAPS_CTRLPOSITIONNOTIFY; dsbd.lpwfxFormat = &wfx; dsbd.dwBufferBytes = BufferSize * 3; if (lpds->CreateSoundBuffer(&dsbd, &pSoundBuffer->lpdsb, NULL)) { return true; } if (!(pSoundBuffer->hEvent[0] = CreateEvent(NULL, false, false, NULL))) { DestroySoundBuffer(pSoundBuffer); return true; } if (!(pSoundBuffer->hEvent[1] = CreateEvent(NULL, false, false, NULL))) { DestroySoundBuffer(pSoundBuffer); return true; } if (!(pSoundBuffer->hEvent[2] = CreateEvent(NULL, false, false, NULL))) { DestroySoundBuffer(pSoundBuffer); return true; } if (pSoundBuffer->lpdsb->QueryInterface(IID_IDirectSoundNotify, (void **)&pSoundBuffer->lpdsn)) { DestroySoundBuffer(pSoundBuffer); return true; } dsbpn[0].hEventNotify = pSoundBuffer->hEvent[0]; dsbpn[0].dwOffset = 0; dsbpn[1].hEventNotify = pSoundBuffer->hEvent[1]; dsbpn[1].dwOffset = BufferSize; dsbpn[2].hEventNotify = pSoundBuffer->hEvent[2]; dsbpn[2].dwOffset = BufferSize * 2; if (pSoundBuffer->lpdsn->SetNotificationPositions(3, dsbpn)) { DestroySoundBuffer(pSoundBuffer); return true; } InitializeCriticalSection(&pSoundBuffer->csSound); if (!CreateThread(NULL, NULL, SoundThreadProc, pSoundBuffer, NULL, &dw)) { DestroySoundBuffer(pSoundBuffer); return true; } return false; }
/** * @brief Creates the primary buffer and the secondary buffers. * @param[in] p_direct_sound_8 pointer to the IDirectSound8 interface. This interface is a factory for creating both the primary buffer and the secondary buffers. * @param[out] pp_primary_buffer pointer to the memory location which will be written with the primary buffer interface pointer. * @param[out] pp_secondary_buffer pointer to the memory location which will be written with the secondary buffer interface pointer. * @param[in] p_wfe pointer to the WAVEFORMATEX structure. This parameter defines the buffer format (number of samples per second, how many bytes per sample and so on). * @param[in] single_buffer_size size of the single play buffer * @return */ static HRESULT create_buffers(LPDIRECTSOUND8 p_ds, WAVEFORMATEX * p_wfex, size_t number_of_chunks, size_t single_buffer_size, LPDIRECTSOUNDBUFFER * pp_primary_sound_buffer, LPDIRECTSOUNDBUFFER8 * pp_secondary_sound_buffer) { HRESULT hr; DSBUFFERDESC bufferDesc; LPDIRECTSOUNDBUFFER lpDSB = NULL; if (NULL != *pp_primary_sound_buffer || NULL != *pp_secondary_sound_buffer) { debug_outputln("%s %4.4u : %p %p", __FILE__, __LINE__, *pp_primary_sound_buffer, *pp_secondary_sound_buffer); return E_INVALIDARG; } ZeroMemory(&bufferDesc, sizeof(bufferDesc)); bufferDesc.dwSize = sizeof(bufferDesc); bufferDesc.dwFlags = DSBCAPS_PRIMARYBUFFER; bufferDesc.guid3DAlgorithm = DS3DALG_DEFAULT; /* All others must be null for primary buffer */ hr = p_ds->CreateSoundBuffer(&bufferDesc, pp_primary_sound_buffer, NULL); if (FAILED(hr)) { debug_outputln("%s %4.4u : %x", __FILE__, __LINE__, hr); goto error; } hr = (*pp_primary_sound_buffer)->SetFormat(p_wfex); if (FAILED(hr)) { debug_outputln("%s %4.4u : %8.8x", __FILE__, __LINE__, hr); goto error; } get_buffer_caps("Primary: ", *pp_primary_sound_buffer); /* Secondary buffer */ bufferDesc.dwFlags = DSBCAPS_CTRLVOLUME /* The buffer has volume control capability. */ | DSBCAPS_CTRLPAN /* The buffer has pan control capability. */ | DSBCAPS_CTRLFREQUENCY /* The buffer has frequency control capability. */ | DSBCAPS_GLOBALFOCUS /* With this flag set, an application using DirectSound can continue to play its buffers if the user switches focus to another application, even if the new application uses DirectSound. */ | DSBCAPS_CTRLPOSITIONNOTIFY; /* The buffer has position notification capability. */ /* double buffering - one buffer being played, whereas the other is being filled in */ bufferDesc.dwBufferBytes = number_of_chunks * single_buffer_size; bufferDesc.lpwfxFormat = p_wfex; hr = p_ds->CreateSoundBuffer(&bufferDesc, &lpDSB, NULL); if (FAILED(hr)) { debug_outputln("%s %4.4u : %x", __FILE__, __LINE__, hr); goto error; } hr = lpDSB->QueryInterface(IID_IDirectSoundBuffer8, (LPVOID*)pp_secondary_sound_buffer); if (FAILED(hr)) { debug_outputln("%s %4.4u : %x", __FILE__, __LINE__, hr); goto error; } get_buffer_caps("Secondary: ", *pp_secondary_sound_buffer); if (NULL != lpDSB) { lpDSB->Release(); lpDSB = NULL; } return hr; error: if (NULL != *pp_secondary_sound_buffer) { (*pp_secondary_sound_buffer)->Release(); *pp_secondary_sound_buffer = NULL; } if (NULL != *pp_primary_sound_buffer) { (*pp_primary_sound_buffer)->Release(); *pp_primary_sound_buffer = NULL; } if (NULL != lpDSB) { lpDSB->Release(); lpDSB = NULL; } return hr; }
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(); }
bool DirectSound::init(long sampleRate) { HRESULT hr; DWORD freq; DSBUFFERDESC dsbdesc; int i; hr = CoCreateInstance( CLSID_DirectSound8, NULL, CLSCTX_INPROC_SERVER, IID_IDirectSound8, (LPVOID *)&pDirectSound ); if( hr != S_OK ) { systemMessage( IDS_CANNOT_CREATE_DIRECTSOUND, NULL, hr ); return false; } pDirectSound->Initialize( &DSDEVID_DefaultPlayback ); if( hr != DS_OK ) { systemMessage( IDS_CANNOT_CREATE_DIRECTSOUND, NULL, hr ); return false; } if( FAILED( hr = pDirectSound->SetCooperativeLevel( theApp.m_pMainWnd->GetSafeHwnd(), DSSCL_EXCLUSIVE ) ) ) { systemMessage( IDS_CANNOT_SETCOOPERATIVELEVEL, _T("Cannot SetCooperativeLevel %08x"), hr ); return false; } // Create primary sound buffer ZeroMemory( &dsbdesc, sizeof(DSBUFFERDESC) ); dsbdesc.dwSize = sizeof(DSBUFFERDESC); dsbdesc.dwFlags = DSBCAPS_PRIMARYBUFFER; if( dsoundDisableHardwareAcceleration ) { dsbdesc.dwFlags |= DSBCAPS_LOCSOFTWARE; } if( FAILED( hr = pDirectSound->CreateSoundBuffer( &dsbdesc, &dsbPrimary, NULL ) ) ) { systemMessage(IDS_CANNOT_CREATESOUNDBUFFER, _T("Cannot CreateSoundBuffer %08x"), hr); return false; } freq = sampleRate; // calculate the number of samples per frame first // then multiply it with the size of a sample frame (16 bit * stereo) soundBufferLen = ( freq / 60 ) * 4; soundBufferTotalLen = soundBufferLen * 10; soundNextPosition = 0; ZeroMemory( &wfx, sizeof(WAVEFORMATEX) ); wfx.wFormatTag = WAVE_FORMAT_PCM; wfx.nChannels = 2; wfx.nSamplesPerSec = freq; wfx.wBitsPerSample = 16; wfx.nBlockAlign = wfx.nChannels * wfx.wBitsPerSample / 8; wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign; if( FAILED( hr = dsbPrimary->SetFormat( &wfx ) ) ) { systemMessage( IDS_CANNOT_SETFORMAT_PRIMARY, _T("CreateSoundBuffer(primary) failed %08x"), hr ); return false; } // Create secondary sound buffer ZeroMemory( &dsbdesc, sizeof(DSBUFFERDESC) ); dsbdesc.dwSize = sizeof(DSBUFFERDESC); dsbdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRLPOSITIONNOTIFY | DSBCAPS_GLOBALFOCUS; if( dsoundDisableHardwareAcceleration ) { dsbdesc.dwFlags |= DSBCAPS_LOCSOFTWARE; } dsbdesc.dwBufferBytes = soundBufferTotalLen; dsbdesc.lpwfxFormat = &wfx; if( FAILED( hr = pDirectSound->CreateSoundBuffer( &dsbdesc, &dsbSecondary, NULL ) ) ) { systemMessage( IDS_CANNOT_CREATESOUNDBUFFER, _T("CreateSoundBuffer(secondary) failed %08x"), hr ); return false; } if( FAILED( hr = dsbSecondary->SetCurrentPosition( 0 ) ) ) { systemMessage( 0, _T("dsbSecondary->SetCurrentPosition failed %08x"), hr ); return false; } if( SUCCEEDED( hr = dsbSecondary->QueryInterface( IID_IDirectSoundNotify8, (LPVOID*)&dsbNotify ) ) ) { dsbEvent = CreateEvent( NULL, FALSE, FALSE, NULL ); DSBPOSITIONNOTIFY notify[10]; for( i = 0; i < 10; i++ ) { notify[i].dwOffset = i * soundBufferLen; notify[i].hEventNotify = dsbEvent; } if( FAILED( dsbNotify->SetNotificationPositions( 10, notify ) ) ) { dsbNotify->Release(); dsbNotify = NULL; CloseHandle(dsbEvent); dsbEvent = NULL; } } // Play primary buffer if( FAILED( hr = dsbPrimary->Play( 0, 0, DSBPLAY_LOOPING ) ) ) { systemMessage( IDS_CANNOT_PLAY_PRIMARY, _T("Cannot Play primary %08x"), hr ); return false; } return true; }
/* ** DS_CreateBuffers */ static int DS_CreateBuffers( void ) { DSBUFFERDESC dsbuf; DSBCAPS dsbcaps; WAVEFORMATEX pformat, format; DWORD dwWrite; memset (&format, 0, sizeof(format)); format.wFormatTag = WAVE_FORMAT_PCM; format.nChannels = dma.channels; format.wBitsPerSample = dma.samplebits; format.nSamplesPerSec = dma.speed; format.nBlockAlign = format.nChannels * format.wBitsPerSample / 8; format.cbSize = 0; format.nAvgBytesPerSec = format.nSamplesPerSec * format.nBlockAlign; Com_Printf( "Creating DirectSound 8 buffers\n" ); Com_Printf("...setting PRIORITY coop level: " ); #ifdef QDSNDCOMPILERHACK if ( DS_OK != pDS->lpVtbl->SetCooperativeLevel( pDS, cl_hwnd, DSSCL_PRIORITY ) ) #else if ( DS_OK != pDS->SetCooperativeLevel( cl_hwnd, DSSCL_PRIORITY ) ) #endif { Com_Printf ("failed\n"); FreeSound (); return 0; } Com_Printf("ok\n" ); // get access to the primary buffer, if possible, so we can set the // sound hardware format memset (&dsbuf, 0, sizeof(dsbuf)); dsbuf.dwSize = sizeof(DSBUFFERDESC); dsbuf.dwFlags = DSBCAPS_PRIMARYBUFFER; // | DSBCAPS_CTRL3D; dsbuf.dwBufferBytes = 0; dsbuf.lpwfxFormat = NULL; memset(&dsbcaps, 0, sizeof(dsbcaps)); dsbcaps.dwSize = sizeof(dsbcaps); primary_format_set = 0; if (!pDSPBuf) { Com_Printf( "...creating primary buffer: " ); #ifdef QDSNDCOMPILERHACK if (DS_OK == pDS->lpVtbl->CreateSoundBuffer(pDS, &dsbuf, &pDSPBuf, NULL)) #else if (DS_OK == pDS->CreateSoundBuffer(&dsbuf, &pDSPBuf, NULL)) #endif { pformat = format; Com_Printf( "ok\n" ); #ifdef QDSNDCOMPILERHACK if (DS_OK != pDSPBuf->lpVtbl->SetFormat (pDSPBuf, &pformat)) #else if (DS_OK != pDSPBuf->SetFormat (&pformat)) #endif { if (snd_firsttime) Com_Printf ("...setting primary sound format: failed\n"); } else { if (snd_firsttime) Com_Printf ("...setting primary sound format: ok\n"); primary_format_set = 1; } } else Com_Printf( "failed\n" ); } if ( !primary_format_set || !s_primary->value) { // create the secondary buffer we'll actually work with memset (&dsbuf, 0, sizeof(DSBUFFERDESC)); dsbuf.dwSize = sizeof(DSBUFFERDESC); dsbuf.dwFlags = DSBCAPS_CTRLFREQUENCY | DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_LOCHARDWARE; //| DSBCAPS_MUTE3DATMAXDISTANCE; // | DSBCAPS_CTRL3D; //dsbuf.dwFlags |= DSBCAPS_CTRLVOLUME; // Allow volume control //dsbuf.dwBufferBytes = format.nAvgBytesPerSec * SECONDARY_BUFFER_LEN_SECONDS; dsbuf.dwBufferBytes = SECONDARY_BUFFER_SIZE * s_buffersize->value; dsbuf.lpwfxFormat = &format; //dsbuf.guid3DAlgorithm = DS3DALG_DEFAULT; //dsbuf.guid3DAlgorithm = DS3DALG_HRTF_FULL; // Use high quality 3D processing memset(&dsbcaps, 0, sizeof(dsbcaps)); dsbcaps.dwSize = sizeof(dsbcaps); Com_Printf( "...creating secondary buffer: " ); //pDSPBuf->QueryInterface(IID_IDirectSoundBuffer8, (LPVOID*) pDSBuf); //myDirectSoundIID = &IID_IDirectSoundBuffer8; //pDSPBuf->lpVtbl->QueryInterface(pDSPBuf, myDirectSoundIID, &pDSBuf); if (!pDSBuf) { //MessageBox (NULL, "Got Here!\n\n", "Quake II", MB_OK | MB_SETFOREGROUND | MB_ICONEXCLAMATION); #ifdef QDSNDCOMPILERHACK if (DS_OK != pDS->lpVtbl->CreateSoundBuffer(pDS, &dsbuf, &pDSBuf, NULL)) #else if (DS_OK != pDS->CreateSoundBuffer(&dsbuf, &pDSBuf, NULL)) #endif //if (DS_OK != pDSPBuf->lpVtbl->QueryInterface(pDSPBuf, myDirectSoundIID, &pDSBuf)) { Com_Printf( "failed\n" ); Com_Printf( "Attempting to locate buffer in software...\n"); dsbuf.dwFlags = DSBCAPS_CTRLFREQUENCY | DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_LOCSOFTWARE; //pDSBuf->lpVtbl->Release(pDSBuf); pDSBuf = NULL; #ifdef QDSNDCOMPILERHACK if (DS_OK != pDS->lpVtbl->CreateSoundBuffer(pDS, &dsbuf, &pDSBuf, NULL)) #else if (DS_OK != pDS->CreateSoundBuffer(&dsbuf, &pDSBuf, NULL)) #endif //if (DS_OK != pDSPBuf->lpVtbl->QueryInterface(pDSPBuf, myDirectSoundIID, &pDSBuf)) { // NeVo - try switching to primary s_primary->value = 1; Com_Printf( "failed\n" ); Com_Printf( "Attempting fallback to primary buffer...\n"); //pDSBuf->lpVtbl->Release(pDSBuf); pDSBuf = NULL; return DS_CreateBuffers(); //FreeSound (); //return 0; } Com_Printf( "ok\n" ); Com_Printf( "Sound Buffer in Software\n" ); } else { Com_Printf( "ok\n" ); Com_Printf( "Sound Buffer in Hardware\n" ); } } dma.channels = format.nChannels; dma.samplebits = format.wBitsPerSample; dma.speed = format.nSamplesPerSec; #ifdef QDSNDCOMPILERHACK if (DS_OK != pDSBuf->lpVtbl->GetCaps (pDSBuf, &dsbcaps)) #else if (DS_OK != pDSBuf->GetCaps (&dsbcaps)) #endif { Com_Printf ("*** GetCaps failed ***\n"); FreeSound (); return 0; } Com_Printf ("...using secondary sound buffer\n"); } else { Com_Printf( "...using primary buffer\n" ); Com_Printf( "...setting WRITEPRIMARY coop level: " ); #ifdef QDSNDCOMPILERHACK if (DS_OK != pDS->lpVtbl->SetCooperativeLevel (pDS, cl_hwnd, DSSCL_WRITEPRIMARY)) #else if (DS_OK != pDS->SetCooperativeLevel (cl_hwnd, DSSCL_WRITEPRIMARY)) #endif { Com_Printf( "failed\n" ); FreeSound (); return 0; } Com_Printf( "ok\n" ); #ifdef QDSNDCOMPILERHACK if (DS_OK != pDSPBuf->lpVtbl->GetCaps (pDSPBuf, &dsbcaps)) #else if (DS_OK != pDSPBuf->GetCaps (&dsbcaps)) #endif { Com_Printf ("*** GetCaps failed ***\n"); return 0; } pDSBuf = pDSPBuf; } // Make sure mixer is active //if ( !s_primary->value) #ifdef QDSNDCOMPILERHACK pDSBuf->lpVtbl->Play(pDSBuf, 0, 0, DSBPLAY_LOOPING); #else pDSBuf->Play (0, 0, DSBPLAY_LOOPING); #endif //else // pDSPBuf->lpVtbl->Play(pDSPBuf, 0, 0, DSBPLAY_LOOPING); if (snd_firsttime) Com_Printf(" %d channel(s)\n" " %d bits/sample\n" " %d bytes/sec\n", dma.channels, dma.samplebits, dma.speed); gSndBufSize = dsbcaps.dwBufferBytes; /* we don't want anyone to access the buffer directly w/o locking it first. */ lpData = NULL; //if ( !s_primary->value) //{ #ifdef QDSNDCOMPILERHACK pDSBuf->lpVtbl->Stop(pDSBuf); pDSBuf->lpVtbl->GetCurrentPosition(pDSBuf, &mmstarttime.u.sample, &dwWrite); pDSBuf->lpVtbl->Play(pDSBuf, 0, 0, DSBPLAY_LOOPING); #else pDSBuf->Stop(); pDSBuf->GetCurrentPosition(&mmstarttime.u.sample, &dwWrite); pDSBuf->Play(0, 0, DSBPLAY_LOOPING); #endif //} //else //{ // pDSPBuf->lpVtbl->Stop(pDSPBuf); // pDSPBuf->lpVtbl->GetCurrentPosition(pDSPBuf, &mmstarttime.u.sample, &dwWrite); // pDSPBuf->lpVtbl->Play(pDSPBuf, 0, 0, DSBPLAY_LOOPING); //} dma.samples = gSndBufSize/(dma.samplebits/8); dma.samplepos = 0; dma.submission_chunk = 1; dma.buffer = (unsigned char *) lpData; sample16 = (dma.samplebits/8) - 1; return 1; }
// Create // create 'empty' sound buffer into the memory HRESULT CSoundWave::Create( CSoundEngine& soundEngine, DWORD dwFrequency, DWORD dwBitsPerSample, DWORD dwChannels, DWORD dwBytes, DWORD dwDuplicates, DWORD dwFlags) { // set original freq m_OriginalFrequency = dwFrequency; HRESULT hres; WAVEFORMATEX wfx; DSBUFFERDESC desc; // init the wave format ::memset(&wfx, 0, sizeof(WAVEFORMATEX)); wfx.wFormatTag = WAVE_FORMAT_PCM; wfx.nChannels = (WORD)dwChannels; wfx.nSamplesPerSec = dwFrequency; wfx.wBitsPerSample = (WORD)dwBitsPerSample; wfx.nBlockAlign = wfx.wBitsPerSample / 8 * wfx.nChannels; wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign; // init the buffer desc ::memset(&desc, 0, sizeof(DSBUFFERDESC)); desc.dwSize = sizeof(DSBUFFERDESC); desc.dwFlags = dwFlags; desc.dwBufferBytes = dwBytes; desc.lpwfxFormat = &wfx; // create sound buffer(s)... LPDIRECTSOUND8 pDS = soundEngine.GetDirectSound(); m_ppDSB = new LPDIRECTSOUNDBUFFER8[dwDuplicates + 1]; if (!m_ppDSB) { return E_OUTOFMEMORY; } // set pointers in array to NULL ::memset(m_ppDSB, 0, sizeof(LPDIRECTSOUNDBUFFER8) * (dwDuplicates + 1)); m_dwBufferCount = dwDuplicates + 1; // create the first sound buffer // first sound buffer is special one, // it is the only one that actually contains // any sound data. The duplicate buffers have only // separate play positions, pointing into the data // in first buffer LPDIRECTSOUNDBUFFER pDSB = NULL; hres = pDS->CreateSoundBuffer(&desc, &pDSB, NULL); if (FAILED(hres)) { Release(); return hres; } // query the latest sound buffer interface hres = pDSB->QueryInterface( IID_IDirectSoundBuffer8, (void**)&m_ppDSB[0]); pDSB->Release(); if (FAILED(hres)) { Release(); return hres; } // create the duplicates DWORD i; for (i=0; i<dwDuplicates; i++) { if ((dwFlags & DSBCAPS_CTRLFX)) { // real time effects required, all duplicate buffers // must have their own wave data hres = pDS->CreateSoundBuffer(&desc, &pDSB, NULL); } else { // no real time effect required, use duplicate buffers // to save memory hres = pDS->DuplicateSoundBuffer(m_ppDSB[0], &pDSB); } if (SUCCEEDED(hres)) { hres = pDSB->QueryInterface( IID_IDirectSoundBuffer8, (void**)&m_ppDSB[i + 1]); pDSB->Release(); if (FAILED(hres)) { Release(); return hres; } } else { if (FAILED(hres)) { Release(); return hres; } } } return S_OK; }
// ****************************************************************** // Laden einer WAV-Datei LPDIRECTSOUNDBUFFER tbLoadWAVFile(LPDIRECTSOUND8 pDSound, tbVFile* pVFile, DWORD dwFlags, GUID GUID3DAlgorithm) { HRESULT hResult; tbRIFFHeader RIFFHeader; tbWAVChunkHeader ChunkHeader; BOOL bFormatChunkRead = FALSE; BOOL bDataChunkRead = FALSE; DWORD dwNumBytesToRead; WAVEFORMATEX WaveFormat; void* pSoundData = NULL; DSBUFFERDESC BufferDesc; LPDIRECTSOUNDBUFFER pSoundBuffer; void* pSoundBufferData; DWORD dwSoundBufferDataSize; // Parameter prüfen if(pDSound == NULL) TB_ERROR_NULL_POINTER("pDSound", NULL); if(pVFile == NULL) TB_ERROR_NULL_POINTER("pVFile", NULL); // RIFF-Header lesen und prüfen if(pVFile->Read(sizeof(tbRIFFHeader), &RIFFHeader)) TB_ERROR("Fehler beim Lesen des RIFF-Headers!", NULL); if(strnicmp(RIFFHeader.acRIFF, "RIFF", 4)) TB_ERROR("RIFF-Signatur nicht gefunden!", NULL); if(strnicmp(RIFFHeader.acFormat, "WAVE", 4)) TB_ERROR("WAVE-Signatur nicht gefunden - die Datei ist keine WAV-Datei!", NULL); // ------------------------------------------------------------------ // WAV-Chunks einlesen while(TRUE) { // Chunk-Header lesen. Bei einem Lesefehler haben wir das Dateiende erreicht. if(pVFile->Read(sizeof(tbWAVChunkHeader), &ChunkHeader)) break; if(!strnicmp(ChunkHeader.acType, "fmt ", 4)) { // Es ist der Format-Chunk! // Prüfen, ob die Größe der Daten in Ordnung ist. Wenn sie größer ist als // die Größe der WAVEFORMATEX-Struktur, dann lassen wir die restlichen Bytes weg. dwNumBytesToRead = TB_MIN(ChunkHeader.dwDataSize, sizeof(WAVEFORMATEX)); if(pVFile->Read(dwNumBytesToRead, &WaveFormat)) TB_ERROR("Fehler beim Lesen des Soundformats!", NULL); bFormatChunkRead = TRUE; } else if(!strnicmp(ChunkHeader.acType, "data", 4)) { // Es ist der Daten-Chunk! // Genügend Speicher reservieren und dann die Daten lesen. pSoundData = tbMemAlloc(ChunkHeader.dwDataSize); if(pSoundData == NULL) TB_ERROR_OUT_OF_MEMORY(NULL); if(pVFile->Read(ChunkHeader.dwDataSize, pSoundData)) TB_ERROR("Fehler beim Lesen der Sounddaten!", NULL); bDataChunkRead = TRUE; } else { // Unbekannter Chunk - überspringen pVFile->Seek(TB_VFSO_CURSOR, ChunkHeader.dwDataSize); } } // Prüfen, ob alle wichtigen Chunks vorhanden waren if(!(bFormatChunkRead && bDataChunkRead)) { // Fehler! TB_SAFE_MEMFREE(pSoundData); TB_ERROR("Die Chunks \"fmt \" und \"data\" müssen beide vorhanden sein!", NULL); } // ------------------------------------------------------------------ // DSBUFFERDESC-Struktur ausfüllen BufferDesc.dwSize = sizeof(DSBUFFERDESC); BufferDesc.dwFlags = dwFlags; BufferDesc.dwBufferBytes = tbMemGetSize(pSoundData); BufferDesc.dwReserved = 0; BufferDesc.lpwfxFormat = &WaveFormat; BufferDesc.guid3DAlgorithm = GUID3DAlgorithm; // Puffer erstellen if(FAILED(hResult = pDSound->CreateSoundBuffer(&BufferDesc, &pSoundBuffer, NULL))) { // Fehler! TB_ERROR_DIRECTX("pDSound->CreateSoundBuffer", hResult, NULL); } // ------------------------------------------------------------------ // Puffer komplett sperren hResult = pSoundBuffer->Lock(0, 0, &pSoundBufferData, &dwSoundBufferDataSize, NULL, NULL, DSBLOCK_ENTIREBUFFER); if(FAILED(hResult)) { // Fehler! TB_SAFE_MEMFREE(pSoundData); TB_SAFE_RELEASE(pSoundBuffer); TB_ERROR_DIRECTX("pSoundBuffer->Lock", hResult, NULL); } // Die Daten hineinschreiben und den Puffer entsperren memcpy(pSoundBufferData, pSoundData, TB_MIN(tbMemGetSize(pSoundData), (int)(dwSoundBufferDataSize))); pSoundBuffer->Unlock(pSoundBufferData, dwSoundBufferDataSize, NULL, 0); // Die Sounddaten freigeben TB_SAFE_MEMFREE(pSoundData); // Den Soundpuffer zurückliefern return pSoundBuffer; }
int SNDDXInit(int buffersize) { DSBUFFERDESC dsbdesc; WAVEFORMATEX wfx; HRESULT ret; char tempstr[512]; if (FAILED(ret = DirectSoundCreate8(NULL, &lpDS8, NULL))) { sprintf(tempstr, "DirectSound8Create error: %s - %s", DXGetErrorString8(ret), DXGetErrorDescription8(ret)); MessageBox (NULL, tempstr, "Error", MB_OK | MB_ICONINFORMATION); return -1; } if (FAILED(ret = lpDS8->SetCooperativeLevel(MainWindow->getHWnd(), DSSCL_PRIORITY))) { sprintf(tempstr, "IDirectSound8_SetCooperativeLevel error: %s - %s", DXGetErrorString8(ret), DXGetErrorDescription8(ret)); MessageBox (NULL, tempstr, "Error", MB_OK | MB_ICONINFORMATION); return -1; } memset(&dsbdesc, 0, sizeof(dsbdesc)); dsbdesc.dwSize = sizeof(DSBUFFERDESC); dsbdesc.dwFlags = DSBCAPS_PRIMARYBUFFER; dsbdesc.dwBufferBytes = 0; dsbdesc.lpwfxFormat = NULL; if (FAILED(ret = lpDS8->CreateSoundBuffer(&dsbdesc, &lpDSB, NULL))) { sprintf(tempstr, "Error when creating primary sound buffer: %s - %s", DXGetErrorString8(ret), DXGetErrorDescription8(ret)); MessageBox (NULL, tempstr, "Error", MB_OK | MB_ICONINFORMATION); return -1; } soundbufsize = buffersize * 2; // caller already multiplies buffersize by 2 soundoffset = 0; memset(&wfx, 0, sizeof(wfx)); wfx.wFormatTag = WAVE_FORMAT_PCM; wfx.nChannels = 2; wfx.nSamplesPerSec = DESMUME_SAMPLE_RATE; wfx.wBitsPerSample = 16; wfx.nBlockAlign = (wfx.wBitsPerSample / 8) * wfx.nChannels; wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign; if (FAILED(ret = lpDSB->SetFormat(&wfx))) { sprintf(tempstr, "IDirectSoundBuffer8_SetFormat error: %s - %s", DXGetErrorString8(ret), DXGetErrorDescription8(ret)); MessageBox (NULL, tempstr, "Error", MB_OK | MB_ICONINFORMATION); return -1; } memset(&dsbdesc, 0, sizeof(dsbdesc)); dsbdesc.dwSize = sizeof(DSBUFFERDESC); dsbdesc.dwFlags = DSBCAPS_GLOBALFOCUS | DSBCAPS_STICKYFOCUS | DSBCAPS_CTRLVOLUME | DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_LOCHARDWARE; dsbdesc.dwBufferBytes = soundbufsize; dsbdesc.lpwfxFormat = &wfx; if (FAILED(ret = lpDS8->CreateSoundBuffer(&dsbdesc, &lpDSB2, NULL))) { if (ret == DSERR_CONTROLUNAVAIL || ret == DSERR_INVALIDCALL || ret == E_FAIL || ret == E_NOTIMPL) { // Try using a software buffer instead dsbdesc.dwFlags = DSBCAPS_GLOBALFOCUS | DSBCAPS_STICKYFOCUS | DSBCAPS_CTRLVOLUME | DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_LOCSOFTWARE; if (FAILED(ret = lpDS8->CreateSoundBuffer(&dsbdesc, &lpDSB2, NULL))) { sprintf(tempstr, "Error when creating secondary sound buffer: %s - %s", DXGetErrorString8(ret), DXGetErrorDescription8(ret)); MessageBox (NULL, tempstr, "Error", MB_OK | MB_ICONINFORMATION); return -1; } } else { sprintf(tempstr, "Error when creating secondary sound buffer: %s - %s", DXGetErrorString8(ret), DXGetErrorDescription8(ret)); MessageBox (NULL, tempstr, "Error", MB_OK | MB_ICONINFORMATION); return -1; } } lpDSB2->Play(0, 0, DSBPLAY_LOOPING); if ((stereodata16 = new s16[soundbufsize / sizeof(s16)]) == NULL) return -1; memset(stereodata16, 0, soundbufsize); soundvolume = DSBVOLUME_MAX; issoundmuted = 0; doterminate = false; terminated = false; CreateThread(0,0,SNDDXThread,0,0,0); return 0; }
int SNDDMA_InitDS () { HRESULT hresult; DSBUFFERDESC dsbuf; DSBCAPS dsbcaps; WAVEFORMATEX format; Com_Printf( "Initializing DirectSound\n"); // Create IDirectSound using the primary sound device if( FAILED( hresult = DirectSoundCreate8(NULL, &pDS, NULL) ) ) { Com_Printf ("failed\n"); SNDDMA_Shutdown (); return false; } hresult = pDS->Initialize(NULL); Com_DPrintf( "ok\n" ); Com_DPrintf("...setting DSSCL_PRIORITY coop level: " ); if ( DS_OK != pDS->SetCooperativeLevel( g_wv.hWnd, DSSCL_PRIORITY ) ) { Com_Printf ("failed\n"); SNDDMA_Shutdown (); return false; } Com_DPrintf("ok\n" ); // create the secondary buffer we'll actually work with dma.channels = 2; dma.samplebits = 16; // if (s_khz->integer == 44) // dma.speed = 44100; // else if (s_khz->integer == 22) // dma.speed = 22050; // else // dma.speed = 11025; dma.speed = 22050; memset (&format, 0, sizeof(format)); format.wFormatTag = WAVE_FORMAT_PCM; format.nChannels = dma.channels; format.wBitsPerSample = dma.samplebits; format.nSamplesPerSec = dma.speed; format.nBlockAlign = format.nChannels * format.wBitsPerSample / 8; format.cbSize = 0; format.nAvgBytesPerSec = format.nSamplesPerSec*format.nBlockAlign; memset (&dsbuf, 0, sizeof(dsbuf)); dsbuf.dwSize = sizeof(DSBUFFERDESC); // Micah: take advantage of 2D hardware.if available. dsbuf.dwFlags = DSBCAPS_LOCHARDWARE; dsbuf.dwFlags |= DSBCAPS_GETCURRENTPOSITION2; dsbuf.dwBufferBytes = SECONDARY_BUFFER_SIZE; dsbuf.lpwfxFormat = &format; memset(&dsbcaps, 0, sizeof(dsbcaps)); dsbcaps.dwSize = sizeof(dsbcaps); Com_DPrintf( "...creating secondary buffer: " ); if (DS_OK == pDS->CreateSoundBuffer(&dsbuf, &pDSBuf, NULL)) { Com_Printf( "locked hardware. ok\n" ); } else { // Couldn't get hardware, fallback to software. dsbuf.dwFlags = DSBCAPS_LOCSOFTWARE; dsbuf.dwFlags |= DSBCAPS_GETCURRENTPOSITION2; if (DS_OK != pDS->CreateSoundBuffer(&dsbuf, &pDSBuf, NULL)) { Com_Printf( "failed\n" ); SNDDMA_Shutdown (); return false; } Com_DPrintf( "forced to software. ok\n" ); } // Make sure mixer is active if ( DS_OK != pDSBuf->Play(0, 0, DSBPLAY_LOOPING) ) { Com_Printf ("*** Looped sound play failed ***\n"); SNDDMA_Shutdown (); return false; } // get the returned buffer size if ( DS_OK != pDSBuf->GetCaps (&dsbcaps) ) { Com_Printf ("*** GetCaps failed ***\n"); SNDDMA_Shutdown (); return false; } gSndBufSize = dsbcaps.dwBufferBytes; dma.channels = format.nChannels; dma.samplebits = format.wBitsPerSample; dma.speed = format.nSamplesPerSec; dma.samples = gSndBufSize/(dma.samplebits/8); dma.submission_chunk = 1; dma.buffer = NULL; // must be locked first sample16 = (dma.samplebits/8) - 1; SNDDMA_BeginPainting (); if (dma.buffer) memset(dma.buffer, 0, dma.samples * dma.samplebits/8); SNDDMA_Submit (); return 1; }