static HRESULT test_block_align(LPGUID lpGuid) { HRESULT rc; LPDIRECTSOUND dso=NULL; LPDIRECTSOUNDBUFFER secondary=NULL; DSBUFFERDESC bufdesc; DSBCAPS dsbcaps; WAVEFORMATEX wfx; DWORD pos, pos2; int ref; /* Create the DirectSound object */ rc=pDirectSoundCreate(lpGuid,&dso,NULL); ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED, "DirectSoundCreate() failed: %08x\n",rc); if (rc!=DS_OK) return rc; init_format(&wfx,WAVE_FORMAT_PCM,11025,16,2); ZeroMemory(&bufdesc, sizeof(bufdesc)); bufdesc.dwSize=sizeof(bufdesc); bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2; bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec + 1; bufdesc.lpwfxFormat=&wfx; rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL); ok(rc==DS_OK,"IDirectSound_CreateSoundBuffer() " "should have returned DS_OK, returned: %08x\n", rc); if (rc==DS_OK && secondary!=NULL) { ZeroMemory(&dsbcaps, sizeof(dsbcaps)); dsbcaps.dwSize = sizeof(dsbcaps); rc=IDirectSoundBuffer_GetCaps(secondary,&dsbcaps); ok(rc==DS_OK,"IDirectSoundBuffer_GetCaps() should have returned DS_OK, " "returned: %08x\n", rc); if (rc==DS_OK && wfx.nBlockAlign > 1) { ok(dsbcaps.dwBufferBytes==(wfx.nAvgBytesPerSec + wfx.nBlockAlign), "Buffer size not a multiple of nBlockAlign: requested %d, " "got %d, should be %d\n", bufdesc.dwBufferBytes, dsbcaps.dwBufferBytes, wfx.nAvgBytesPerSec + wfx.nBlockAlign); rc = IDirectSoundBuffer_SetCurrentPosition(secondary, 0); ok(rc == DS_OK, "Could not set position to 0: %08x\n", rc); rc = IDirectSoundBuffer_GetCurrentPosition(secondary, &pos, NULL); ok(rc == DS_OK, "Could not get position: %08x\n", rc); rc = IDirectSoundBuffer_SetCurrentPosition(secondary, 1); ok(rc == DS_OK, "Could not set position to 1: %08x\n", rc); rc = IDirectSoundBuffer_GetCurrentPosition(secondary, &pos2, NULL); ok(rc == DS_OK, "Could not get new position: %08x\n", rc); ok(pos == pos2, "Positions not the same! Old position: %d, new position: %d\n", pos, pos2); } ref=IDirectSoundBuffer_Release(secondary); ok(ref==0,"IDirectSoundBuffer_Release() secondary has %d references, " "should have 0\n",ref); } ref=IDirectSound_Release(dso); ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref); if (ref!=0) return DSERR_GENERIC; return rc; }
static HRESULT WINAPI IDirectMusicPerformance8Impl_CreateStandardAudioPath (LPDIRECTMUSICPERFORMANCE8 iface, DWORD dwType, DWORD dwPChannelCount, BOOL fActivate, IDirectMusicAudioPath** ppNewPath) { IDirectMusicAudioPathImpl *default_path; IDirectMusicAudioPath *pPath; DSBUFFERDESC desc; WAVEFORMATEX format; LPDIRECTSOUNDBUFFER buffer; HRESULT hr = S_OK; IDirectMusicPerformance8Impl *This = (IDirectMusicPerformance8Impl *)iface; FIXME("(%p)->(%d, %d, %d, %p): semi-stub\n", This, dwType, dwPChannelCount, fActivate, ppNewPath); if (NULL == ppNewPath) { return E_POINTER; } DMUSIC_CreateDirectMusicAudioPathImpl (&IID_IDirectMusicAudioPath, (LPVOID*)&pPath, NULL); default_path = (IDirectMusicAudioPathImpl*)((char*)(pPath) - offsetof(IDirectMusicAudioPathImpl,AudioPathVtbl)); default_path->pPerf = (IDirectMusicPerformance8*) This; /* Secondary buffer description */ memset(&format, 0, sizeof(format)); format.wFormatTag = WAVE_FORMAT_PCM; format.nChannels = 1; format.nSamplesPerSec = 44000; format.nAvgBytesPerSec = 44000*2; format.nBlockAlign = 2; format.wBitsPerSample = 16; format.cbSize = 0; memset(&desc, 0, sizeof(desc)); desc.dwSize = sizeof(desc); desc.dwFlags = DSBCAPS_CTRLFX | DSBCAPS_CTRLPAN | DSBCAPS_CTRLVOLUME | DSBCAPS_GLOBALFOCUS; desc.dwBufferBytes = DSBSIZE_MIN; desc.dwReserved = 0; desc.lpwfxFormat = &format; desc.guid3DAlgorithm = GUID_NULL; switch(dwType) { case DMUS_APATH_DYNAMIC_3D: desc.dwFlags |= DSBCAPS_CTRL3D | DSBCAPS_CTRLFREQUENCY | DSBCAPS_MUTE3DATMAXDISTANCE; break; case DMUS_APATH_DYNAMIC_MONO: desc.dwFlags |= DSBCAPS_CTRLFREQUENCY; break; case DMUS_APATH_SHARED_STEREOPLUSREVERB: /* normally we have to create 2 buffers (one for music other for reverb) * in this case. See msdn */ case DMUS_APATH_DYNAMIC_STEREO: desc.dwFlags |= DSBCAPS_CTRLFREQUENCY; format.nChannels = 2; format.nBlockAlign *= 2; format.nAvgBytesPerSec *=2; break; default: HeapFree(GetProcessHeap(), 0, default_path); *ppNewPath = NULL; return E_INVALIDARG; } /* FIXME: Should we create one secondary buffer for each PChannel? */ hr = IDirectSound8_CreateSoundBuffer ((LPDIRECTSOUND8) This->pDirectSound, &desc, &buffer, NULL); if (FAILED(hr)) { HeapFree(GetProcessHeap(), 0, default_path); *ppNewPath = NULL; return DSERR_BUFFERLOST; } default_path->pDSBuffer = buffer; /* Update description for creating primary buffer */ desc.dwFlags |= DSBCAPS_PRIMARYBUFFER; desc.dwBufferBytes = 0; desc.lpwfxFormat = NULL; hr = IDirectSound8_CreateSoundBuffer ((LPDIRECTSOUND8) This->pDirectSound, &desc, &buffer, NULL); if (FAILED(hr)) { IDirectSoundBuffer_Release(default_path->pDSBuffer); HeapFree(GetProcessHeap(), 0, default_path); *ppNewPath = NULL; return DSERR_BUFFERLOST; } default_path->pPrimary = buffer; *ppNewPath = pPath; TRACE(" returning IDirectMusicPerformance interface at %p.\n", *ppNewPath); return IDirectMusicAudioPath_Activate(*ppNewPath, fActivate); }
HRESULT DSoundRender_create(IUnknown * pUnkOuter, LPVOID * ppv) { HRESULT hr; DSoundRenderImpl * pDSoundRender; TRACE("(%p, %p)\n", pUnkOuter, ppv); *ppv = NULL; if (pUnkOuter) return CLASS_E_NOAGGREGATION; pDSoundRender = CoTaskMemAlloc(sizeof(DSoundRenderImpl)); if (!pDSoundRender) return E_OUTOFMEMORY; ZeroMemory(pDSoundRender, sizeof(DSoundRenderImpl)); hr = BaseRenderer_Init(&pDSoundRender->renderer, &DSoundRender_Vtbl, (IUnknown*)pDSoundRender, &CLSID_DSoundRender, (DWORD_PTR)(__FILE__ ": DSoundRenderImpl.csFilter"), &BaseFuncTable); BasicAudio_Init(&pDSoundRender->basicAudio,&IBasicAudio_Vtbl); pDSoundRender->IReferenceClock_iface.lpVtbl = &IReferenceClock_Vtbl; pDSoundRender->IAMDirectSound_iface.lpVtbl = &IAMDirectSound_Vtbl; pDSoundRender->IAMFilterMiscFlags_iface.lpVtbl = &IAMFilterMiscFlags_Vtbl; if (SUCCEEDED(hr)) { hr = DirectSoundCreate8(NULL, &pDSoundRender->dsound, NULL); if (FAILED(hr)) ERR("Cannot create Direct Sound object (%x)\n", hr); else hr = IDirectSound_SetCooperativeLevel(pDSoundRender->dsound, GetDesktopWindow(), DSSCL_PRIORITY); if (SUCCEEDED(hr)) { IDirectSoundBuffer *buf; DSBUFFERDESC buf_desc; memset(&buf_desc,0,sizeof(DSBUFFERDESC)); buf_desc.dwSize = sizeof(DSBUFFERDESC); buf_desc.dwFlags = DSBCAPS_PRIMARYBUFFER; hr = IDirectSound_CreateSoundBuffer(pDSoundRender->dsound, &buf_desc, &buf, NULL); if (SUCCEEDED(hr)) { IDirectSoundBuffer_Play(buf, 0, 0, DSBPLAY_LOOPING); IDirectSoundBuffer_Release(buf); } hr = S_OK; } } if (SUCCEEDED(hr)) { pDSoundRender->blocked = CreateEventW(NULL, TRUE, TRUE, NULL); if (!pDSoundRender->blocked || FAILED(hr)) { IBaseFilter_Release(&pDSoundRender->renderer.filter.IBaseFilter_iface); return HRESULT_FROM_WIN32(GetLastError()); } *ppv = pDSoundRender; } else { BaseRendererImpl_Release(&pDSoundRender->renderer.filter.IBaseFilter_iface); CoTaskMemFree(pDSoundRender); } return hr; }
/************************************************************************** * MCICDA_Play [internal] */ static DWORD MCICDA_Play(UINT wDevID, DWORD dwFlags, LPMCI_PLAY_PARMS lpParms) { WINE_MCICDAUDIO* wmcda = MCICDA_GetOpenDrv(wDevID); DWORD ret = 0, start, end; HANDLE oldcb; DWORD br; CDROM_PLAY_AUDIO_MSF play; CDROM_SUB_Q_DATA_FORMAT fmt; SUB_Q_CHANNEL_DATA data; CDROM_TOC toc; TRACE("(%04X, %08X, %p);\n", wDevID, dwFlags, lpParms); if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK; if (wmcda == NULL) return MCIERR_INVALID_DEVICE_ID; if (!DeviceIoControl(wmcda->handle, IOCTL_CDROM_READ_TOC, NULL, 0, &toc, sizeof(toc), &br, NULL)) { WARN("error reading TOC !\n"); return MCICDA_GetError(wmcda); } if (dwFlags & MCI_FROM) { start = MCICDA_CalcFrame(wmcda, lpParms->dwFrom); if ( (ret=MCICDA_SkipDataTracks(wmcda, &start)) ) return ret; TRACE("MCI_FROM=%08X -> %u\n", lpParms->dwFrom, start); } else { fmt.Format = IOCTL_CDROM_CURRENT_POSITION; if (!DeviceIoControl(wmcda->handle, IOCTL_CDROM_READ_Q_CHANNEL, &fmt, sizeof(fmt), &data, sizeof(data), &br, NULL)) { return MCICDA_GetError(wmcda); } start = FRAME_OF_ADDR(data.CurrentPosition.AbsoluteAddress); if ( (ret=MCICDA_SkipDataTracks(wmcda, &start)) ) return ret; } if (dwFlags & MCI_TO) { end = MCICDA_CalcFrame(wmcda, lpParms->dwTo); if ( (ret=MCICDA_SkipDataTracks(wmcda, &end)) ) return ret; TRACE("MCI_TO=%08X -> %u\n", lpParms->dwTo, end); } else { end = FRAME_OF_TOC(toc, toc.LastTrack + 1) - 1; } if (end < start) return MCIERR_OUTOFRANGE; TRACE("Playing from %u to %u\n", start, end); oldcb = InterlockedExchangePointer(&wmcda->hCallback, (dwFlags & MCI_NOTIFY) ? HWND_32(LOWORD(lpParms->dwCallback)) : NULL); if (oldcb) mciDriverNotify(oldcb, wmcda->wNotifyDeviceID, MCI_NOTIFY_ABORTED); if (start == end || start == FRAME_OF_TOC(toc,toc.LastTrack+1)-1) { if (dwFlags & MCI_NOTIFY) { oldcb = InterlockedExchangePointer(&wmcda->hCallback, NULL); if (oldcb) mciDriverNotify(oldcb, wDevID, MCI_NOTIFY_SUCCESSFUL); } return MMSYSERR_NOERROR; } if (wmcda->hThread != 0) { SetEvent(wmcda->stopEvent); WaitForSingleObject(wmcda->hThread, INFINITE); CloseHandle(wmcda->hThread); wmcda->hThread = 0; CloseHandle(wmcda->stopEvent); wmcda->stopEvent = 0; IDirectSoundBuffer_Stop(wmcda->dsBuf); IDirectSoundBuffer_Release(wmcda->dsBuf); wmcda->dsBuf = NULL; IDirectSound_Release(wmcda->dsObj); wmcda->dsObj = NULL; } if (pDirectSoundCreate) { WAVEFORMATEX format; DSBUFFERDESC desc; DWORD lockLen; void *cdData; HRESULT hr; hr = pDirectSoundCreate(NULL, &wmcda->dsObj, NULL); if (SUCCEEDED(hr)) { IDirectSound_SetCooperativeLevel(wmcda->dsObj, GetDesktopWindow(), DSSCL_PRIORITY); /* The "raw" frame is relative to the start of the first track */ wmcda->start = start - FRAME_OF_TOC(toc, toc.FirstTrack); wmcda->end = end - FRAME_OF_TOC(toc, toc.FirstTrack); memset(&format, 0, sizeof(format)); format.wFormatTag = WAVE_FORMAT_PCM; format.nChannels = 2; format.nSamplesPerSec = 44100; format.wBitsPerSample = 16; format.nBlockAlign = format.nChannels * format.wBitsPerSample / 8; format.nAvgBytesPerSec = format.nSamplesPerSec * format.nBlockAlign; format.cbSize = 0; memset(&desc, 0, sizeof(desc)); desc.dwSize = sizeof(desc); desc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_GLOBALFOCUS; desc.dwBufferBytes = (CDDA_FRAG_SIZE - (CDDA_FRAG_SIZE%RAW_SECTOR_SIZE)) * CDDA_FRAG_COUNT; desc.lpwfxFormat = &format; hr = IDirectSound_CreateSoundBuffer(wmcda->dsObj, &desc, &wmcda->dsBuf, NULL); } if (SUCCEEDED(hr)) { hr = IDirectSoundBuffer_Lock(wmcda->dsBuf, 0, 0, &cdData, &lockLen, NULL, NULL, DSBLOCK_ENTIREBUFFER); } if (SUCCEEDED(hr)) { RAW_READ_INFO rdInfo; int readok; rdInfo.DiskOffset.QuadPart = wmcda->start<<11; rdInfo.SectorCount = min(desc.dwBufferBytes/RAW_SECTOR_SIZE, wmcda->end-wmcda->start); rdInfo.TrackMode = CDDA; readok = DeviceIoControl(wmcda->handle, IOCTL_CDROM_RAW_READ, &rdInfo, sizeof(rdInfo), cdData, lockLen, &br, NULL); IDirectSoundBuffer_Unlock(wmcda->dsBuf, cdData, lockLen, NULL, 0); if (readok) { wmcda->start += rdInfo.SectorCount; wmcda->stopEvent = CreateEventA(NULL, TRUE, FALSE, NULL); } if (wmcda->stopEvent != 0) wmcda->hThread = CreateThread(NULL, 0, MCICDA_playLoop, wmcda, 0, &br); if (wmcda->hThread != 0) { hr = IDirectSoundBuffer_Play(wmcda->dsBuf, 0, 0, DSBPLAY_LOOPING); if (SUCCEEDED(hr)) { /* FIXME: implement MCI_WAIT and send notification only in that case */ if (0) { oldcb = InterlockedExchangePointer(&wmcda->hCallback, NULL); if (oldcb) mciDriverNotify(oldcb, wmcda->wNotifyDeviceID, FAILED(hr) ? MCI_NOTIFY_FAILURE : MCI_NOTIFY_SUCCESSFUL); } return ret; } SetEvent(wmcda->stopEvent); WaitForSingleObject(wmcda->hThread, INFINITE); CloseHandle(wmcda->hThread); wmcda->hThread = 0; } } if (wmcda->stopEvent != 0) { CloseHandle(wmcda->stopEvent); wmcda->stopEvent = 0; } if (wmcda->dsBuf) { IDirectSoundBuffer_Release(wmcda->dsBuf); wmcda->dsBuf = NULL; } if (wmcda->dsObj) { IDirectSound_Release(wmcda->dsObj); wmcda->dsObj = NULL; } } play.StartingM = start / CDFRAMES_PERMIN; play.StartingS = (start / CDFRAMES_PERSEC) % 60; play.StartingF = start % CDFRAMES_PERSEC; play.EndingM = end / CDFRAMES_PERMIN; play.EndingS = (end / CDFRAMES_PERSEC) % 60; play.EndingF = end % CDFRAMES_PERSEC; if (!DeviceIoControl(wmcda->handle, IOCTL_CDROM_PLAY_AUDIO_MSF, &play, sizeof(play), NULL, 0, &br, NULL)) { wmcda->hCallback = NULL; ret = MCIERR_HARDWARE; } /* The independent CD player has no means to signal MCI_NOTIFY when it's done. * Native sends a notification with MCI_WAIT only. */ return ret; }
/* * Destroy stream. */ PJ_DEF(pj_status_t) pjmedia_snd_stream_close(pjmedia_snd_stream *stream) { PJ_ASSERT_RETURN(stream != NULL, PJ_EINVAL); pjmedia_snd_stream_stop(stream); if (stream->thread) { pj_assert(stream->thread_quit_event); SetEvent(stream->thread_quit_event); pj_thread_join(stream->thread); pj_thread_destroy(stream->thread); stream->thread = NULL; } if (stream->thread_quit_event) { CloseHandle(stream->thread_quit_event); stream->thread_quit_event = NULL; } if (stream->play_strm.lpDsNotify) { IDirectSoundNotify_Release( stream->play_strm.lpDsNotify ); stream->play_strm.lpDsNotify = NULL; } if (stream->play_strm.hEvent) { CloseHandle(stream->play_strm.hEvent); stream->play_strm.hEvent = NULL; } if (stream->play_strm.ds.play.lpDsBuffer) { IDirectSoundBuffer_Release( stream->play_strm.ds.play.lpDsBuffer ); stream->play_strm.ds.play.lpDsBuffer = NULL; } if (stream->play_strm.ds.play.lpDs) { IDirectSound_Release( stream->play_strm.ds.play.lpDs ); stream->play_strm.ds.play.lpDs = NULL; } if (stream->rec_strm.lpDsNotify) { IDirectSoundNotify_Release( stream->rec_strm.lpDsNotify ); stream->rec_strm.lpDsNotify = NULL; } if (stream->rec_strm.hEvent) { CloseHandle(stream->rec_strm.hEvent); stream->rec_strm.hEvent = NULL; } if (stream->rec_strm.ds.capture.lpDsBuffer) { IDirectSoundCaptureBuffer_Release( stream->rec_strm.ds.capture.lpDsBuffer ); stream->rec_strm.ds.capture.lpDsBuffer = NULL; } if (stream->rec_strm.ds.capture.lpDs) { IDirectSoundCapture_Release( stream->rec_strm.ds.capture.lpDs ); stream->rec_strm.ds.capture.lpDs = NULL; } pj_pool_release(stream->pool); return PJ_SUCCESS; }
static HRESULT test_frequency(LPGUID lpGuid) { HRESULT rc; LPDIRECTSOUND dso=NULL; LPDIRECTSOUNDBUFFER primary=NULL,secondary=NULL; DSBUFFERDESC bufdesc; DSCAPS dscaps; WAVEFORMATEX wfx, wfx1; DWORD f, r; int ref; int rates[] = { 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000, 96000 }; /* Create the DirectSound object */ rc=DirectSoundCreate(lpGuid,&dso,NULL); ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED, "DirectSoundCreate() failed: %s\n",DXGetErrorString8(rc)); if (rc!=DS_OK) return rc; /* Get the device capabilities */ ZeroMemory(&dscaps, sizeof(dscaps)); dscaps.dwSize=sizeof(dscaps); rc=IDirectSound_GetCaps(dso,&dscaps); ok(rc==DS_OK,"IDirectSound_GetCaps() failed: %s\n",DXGetErrorString8(rc)); if (rc!=DS_OK) goto EXIT; /* We must call SetCooperativeLevel before creating primary buffer */ /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */ rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY); ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n", DXGetErrorString8(rc)); if (rc!=DS_OK) goto EXIT; ZeroMemory(&bufdesc, sizeof(bufdesc)); bufdesc.dwSize=sizeof(bufdesc); bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER; rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL); ok(rc==DS_OK && primary!=NULL, "IDirectSound_CreateSoundBuffer() failed to create a primary buffer " "%s\n",DXGetErrorString8(rc)); if (rc==DS_OK && primary!=NULL) { rc=IDirectSoundBuffer_GetFormat(primary,&wfx1,sizeof(wfx1),NULL); ok(rc==DS_OK,"IDirectSoundBuffer8_Getformat() failed: %s\n", DXGetErrorString8(rc)); if (rc!=DS_OK) goto EXIT1; for (f=0;f<sizeof(fmts)/sizeof(fmts[0]);f++) { for (r=0;r<sizeof(rates)/sizeof(rates[0]);r++) { init_format(&wfx,WAVE_FORMAT_PCM,11025,fmts[f].bits, fmts[f].channels); secondary=NULL; ZeroMemory(&bufdesc, sizeof(bufdesc)); bufdesc.dwSize=sizeof(bufdesc); bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2|DSBCAPS_CTRLFREQUENCY; bufdesc.dwBufferBytes=align((wfx.nAvgBytesPerSec*rates[r]/11025)* BUFFER_LEN/1000,wfx.nBlockAlign); bufdesc.lpwfxFormat=&wfx; if (winetest_interactive) { trace(" Testing a secondary buffer at %ldx%dx%d " "with a primary buffer at %ldx%dx%d\n", wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels, wfx1.nSamplesPerSec,wfx1.wBitsPerSample,wfx1.nChannels); } rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL); ok(rc==DS_OK && secondary!=NULL, "IDirectSound_CreateSoundBuffer() failed to create a secondary " "buffer %s\n",DXGetErrorString8(rc)); if (rc==DS_OK && secondary!=NULL) { test_buffer(dso,&secondary,0,FALSE,0,FALSE,0, winetest_interactive,1.0,0,NULL,0,0,TRUE,rates[r]); ref=IDirectSoundBuffer_Release(secondary); ok(ref==0,"IDirectSoundBuffer_Release() has %d references, " "should have 0\n",ref); } } } EXIT1: ref=IDirectSoundBuffer_Release(primary); ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, " "should have 0\n",ref); } /* Set the CooperativeLevel back to normal */ /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */ rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL); ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %s\n", DXGetErrorString8(rc)); EXIT: ref=IDirectSound_Release(dso); ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n",ref); if (ref!=0) return DSERR_GENERIC; return rc; }
/* * Test the primary buffer at different formats while keeping the * secondary buffer at a constant format. */ static HRESULT test_primary_secondary8(LPGUID lpGuid) { HRESULT rc; LPDIRECTSOUND8 dso=NULL; LPDIRECTSOUNDBUFFER primary=NULL,secondary=NULL; DSBUFFERDESC bufdesc; DSCAPS dscaps; WAVEFORMATEX wfx, wfx2; int ref; unsigned int f; /* Create the DirectSound object */ rc=pDirectSoundCreate8(lpGuid,&dso,NULL); ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED, "DirectSoundCreate8() failed: %08x\n",rc); if (rc!=DS_OK) return rc; /* Get the device capabilities */ ZeroMemory(&dscaps, sizeof(dscaps)); dscaps.dwSize=sizeof(dscaps); rc=IDirectSound8_GetCaps(dso,&dscaps); ok(rc==DS_OK,"IDirectSound8_GetCaps() failed: %08x\n",rc); if (rc!=DS_OK) goto EXIT; /* We must call SetCooperativeLevel before creating primary buffer */ /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */ rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY); ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel() failed: %08x\n", rc); if (rc!=DS_OK) goto EXIT; ZeroMemory(&bufdesc, sizeof(bufdesc)); bufdesc.dwSize=sizeof(bufdesc); bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER; rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&primary,NULL); ok(rc==DS_OK && primary!=NULL, "IDirectSound8_CreateSoundBuffer() failed to create a primary buffer " "%08x\n",rc); if (rc==DS_OK && primary!=NULL) { for (f=0;f<NB_FORMATS;f++) { /* We must call SetCooperativeLevel to be allowed to call * SetFormat */ /* DSOUND: Setting DirectSound cooperative level to * DSSCL_PRIORITY */ rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY); ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel() failed: %08x\n", rc); if (rc!=DS_OK) goto EXIT; init_format(&wfx,WAVE_FORMAT_PCM,formats[f][0],formats[f][1], formats[f][2]); wfx2=wfx; rc=IDirectSoundBuffer_SetFormat(primary,&wfx); ok(rc==DS_OK || rc==DSERR_INVALIDPARAM, /* 2003 */ "IDirectSoundBuffer_SetFormat(%s) failed: %08x\n", format_string(&wfx), rc); /* There is no guarantee that SetFormat will actually change the * format to what we asked for. It depends on what the soundcard * supports. So we must re-query the format. */ rc=IDirectSoundBuffer_GetFormat(primary,&wfx,sizeof(wfx),NULL); ok(rc==DS_OK,"IDirectSoundBuffer_GetFormat() failed: %08x\n", rc); if (rc==DS_OK && (wfx.wFormatTag!=wfx2.wFormatTag || wfx.nSamplesPerSec!=wfx2.nSamplesPerSec || wfx.wBitsPerSample!=wfx2.wBitsPerSample || wfx.nChannels!=wfx2.nChannels)) { trace("Requested primary format tag=0x%04x %dx%dx%d " "avg.B/s=%d align=%d\n", wfx2.wFormatTag,wfx2.nSamplesPerSec,wfx2.wBitsPerSample, wfx2.nChannels,wfx2.nAvgBytesPerSec,wfx2.nBlockAlign); trace("Got tag=0x%04x %dx%dx%d avg.B/s=%d align=%d\n", wfx.wFormatTag,wfx.nSamplesPerSec,wfx.wBitsPerSample, wfx.nChannels,wfx.nAvgBytesPerSec,wfx.nBlockAlign); } /* Set the CooperativeLevel back to normal */ /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */ rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL); ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel() failed: %08x\n", rc); init_format(&wfx2,WAVE_FORMAT_PCM,11025,16,2); secondary=NULL; ZeroMemory(&bufdesc, sizeof(bufdesc)); bufdesc.dwSize=sizeof(bufdesc); bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2; bufdesc.dwBufferBytes=align(wfx.nAvgBytesPerSec*BUFFER_LEN/1000, wfx.nBlockAlign); bufdesc.lpwfxFormat=&wfx2; if (winetest_interactive) { trace(" Testing a primary buffer at %dx%dx%d with a " "secondary buffer at %dx%dx%d\n", wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels, wfx2.nSamplesPerSec,wfx2.wBitsPerSample,wfx2.nChannels); } rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL); ok(rc==DS_OK && secondary!=NULL, "IDirectSound_CreateSoundBuffer() failed to create a secondary " "buffer %08x\n",rc); if (rc==DS_OK && secondary!=NULL) { test_buffer8(dso,&secondary,0,FALSE,0,FALSE,0, winetest_interactive,1.0,0,NULL,0,0); ref=IDirectSoundBuffer_Release(secondary); ok(ref==0,"IDirectSoundBuffer_Release() has %d references, " "should have 0\n",ref); } } ref=IDirectSoundBuffer_Release(primary); ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, " "should have 0\n",ref); } /* Set the CooperativeLevel back to normal */ /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */ rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL); ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel() failed: %08x\n", rc); EXIT: ref=IDirectSound8_Release(dso); ok(ref==0,"IDirectSound8_Release() has %d references, should have 0\n",ref); if (ref!=0) return DSERR_GENERIC; return rc; }
int I2_PlaySound(void *data, boolean play3d, sound3d_t *desc, int pan) { sampleheader_t *header = data; byte *sample = (byte*) data + sizeof(sampleheader_t); sndsource_t *sndbuf; void *writePtr1=NULL, *writePtr2=NULL; DWORD writeBytes1, writeBytes2; int samplelen = header->length, freq = header->frequency, bits = 8; // Can we play sounds? if(!initOk || data == NULL) return 0; // Sorry... if(snd_Resample != 1 && snd_Resample != 2 && snd_Resample != 4) { ST_Message("I2_PlaySound: invalid resample factor.\n"); snd_Resample = 1; } // Get a buffer that's doing nothing. sndbuf = I2_GetFreeSource(play3d); sndbuf->startTime = I_GetTime(); // Prepare the audio data. if(snd_Resample == 1 && !snd_16bits) // Play sounds as normal? { // No resampling necessary. sndbuf->freq = header->frequency; } else { // Resample the sound. sample = I_Resample8bitSound(sample, header->length, freq, snd_Resample, snd_16bits, &samplelen); if(snd_16bits) bits = 16; freq *= snd_Resample; sndbuf->freq = freq; } if(sndbuf->source) { // Release the old source. I2_KillSource(sndbuf); } // Create a new source. if(FAILED(hr = CreateDSBuffer(play3d? DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLFREQUENCY | DSBCAPS_CTRL3D | DSBCAPS_MUTE3DATMAXDISTANCE | DSBCAPS_STATIC : DSBCAPS_CTRLPAN | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLFREQUENCY | DSBCAPS_STATIC, header->length * snd_Resample, freq, bits, 1, &sndbuf->source))) { ST_Message("I2_PlaySound: couldn't create a new buffer (result = %d).\n", hr & 0xffff); memset(sndbuf, 0, sizeof(*sndbuf)); return 0; } if(play3d) { // Query the 3D interface. if(FAILED(hr = IDirectSoundBuffer_QueryInterface(sndbuf->source, &IID_IDirectSound3DBuffer, &sndbuf->source3D))) { ST_Message("I2_PlaySound: couldn't get 3D buffer interface (result = %d).\n", hr & 0xffff); IDirectSoundBuffer_Release(sndbuf->source); memset(sndbuf, 0, sizeof(*sndbuf)); return 0; } } // Lock the buffer. if(FAILED(hr = IDirectSoundBuffer_Lock(sndbuf->source, 0, samplelen, &writePtr1, &writeBytes1, &writePtr2, &writeBytes2, 0))) { I_Error("I2_PlaySound: couldn't lock source (result = %d).\n", hr & 0xffff); } // Copy the data over. memcpy(writePtr1, sample, writeBytes1); if(writePtr2) memcpy(writePtr2, (char*) sample + writeBytes1, writeBytes2); // Unlock the buffer. if(FAILED(hr = IDirectSoundBuffer_Unlock(sndbuf->source, writePtr1, writeBytes1, writePtr2, writeBytes2))) { I_Error("I2_PlaySound: couldn't unlock source (result = %d).\n", hr & 0xffff); return 0; } if(play3d) { // Set the 3D parameters of the source. if(desc->flags & DDSOUNDF_VERY_LOUD) { // You can hear this from very far away (e.g. thunderclap). IDirectSound3DBuffer_SetMinDistance(sndbuf->source3D, 10000, DS3D_DEFERRED); IDirectSound3DBuffer_SetMaxDistance(sndbuf->source3D, 20000, DS3D_DEFERRED); } else { IDirectSound3DBuffer_SetMinDistance(sndbuf->source3D, 100, DS3D_DEFERRED); IDirectSound3DBuffer_SetMaxDistance(sndbuf->source3D, MAX_SND_DIST, DS3D_DEFERRED); } if(desc->flags & DDSOUNDF_LOCAL) IDirectSound3DBuffer_SetMode(sndbuf->source3D, DS3DMODE_DISABLE, DS3D_DEFERRED); } else { // If playing in 2D mode, set the pan. I2_SetPan(sndbuf, pan/1000.0f); } I2_UpdateSource(sndbuf, desc); // Start playing the buffer. if(FAILED(hr = IDirectSoundBuffer_Play(sndbuf->source, 0, 0, 0))) { I_Error("I2_PlaySound: couldn't start source (result = %d).\n", hr & 0xffff); return 0; } // Return the handle to the sound source. return (sndbuf->id = idGen++); }
int I2_Init() { DSBUFFERDESC desc; LPDIRECTSOUNDBUFFER bufTemp; if(initOk) return true; // Don't init a second time. if(FAILED(hr = EAXDirectSoundCreate(NULL, &dsound, NULL))) { // EAX can't be initialized. Use normal DS, then. ST_Message("I2_Init: EAX 2 couldn't be initialized (result: %i).\n", hr & 0xffff); if(FAILED(hr = DirectSoundCreate(NULL, &dsound, NULL))) { ST_Message("I2_Init: Couldn't create dsound (result: %i).\n", hr & 0xffff); return false; } } // Set the cooperative level. if(FAILED(hr = IDirectSound_SetCooperativeLevel(dsound, hWndMain, DSSCL_PRIORITY))) { ST_Message("I2_Init: Couldn't set dSound cooperative level (result: %i).\n", hr & 0xffff); return false; } // Get the listener. memset(&desc, 0, sizeof(desc)); desc.dwSize = sizeof(desc); desc.dwFlags = DSBCAPS_CTRL3D | DSBCAPS_PRIMARYBUFFER; if(SUCCEEDED(IDirectSound_CreateSoundBuffer(dsound, &desc, &bufTemp, NULL))) { // Query the listener interface. IDirectSoundBuffer_QueryInterface(bufTemp, &IID_IDirectSound3DListener, &dsListener); } // Release the primary buffer interface, we won't need it. IDirectSoundBuffer_Release(bufTemp); // Try to get the EAX listener property set. Create a temporary secondary buffer for it. if(SUCCEEDED( CreateDSBuffer(DSBCAPS_STATIC | DSBCAPS_CTRL3D, DSBSIZE_MIN, 22050, 8, 1, &bufTemp) )) { // Now try to get the property set. if(SUCCEEDED(hr = IDirectSoundBuffer_QueryInterface(bufTemp, &IID_IKsPropertySet, &eaxListener))) { DWORD support = 0, revsize = 0; // Check for support. if(FAILED(hr = IKsPropertySet_QuerySupport(eaxListener, &DSPROPSETID_EAX_ListenerProperties, DSPROPERTY_EAXLISTENER_ENVIRONMENT, &support)) || ((support & NEEDED_SUPPORT) != NEEDED_SUPPORT)) { ST_Message("I2_Init: Property set acquired, but EAX 2 not supported.\n Result:%i, support:%x\n", hr&0xffff, support); IKsPropertySet_Release(eaxListener); eaxListener = NULL; } else { // EAX is supported! ST_Message("I2_Init: EAX 2 available.\n"); } } // Release the temporary buffer interface. IDirectSoundBuffer_Release(bufTemp); } // Get the caps. dsCaps.dwSize = sizeof(dsCaps); IDirectSound_GetCaps(dsound, &dsCaps); ST_Message("I2_Init: Number of hardware 3D buffers: %i\n", dsCaps.dwMaxHw3DAllBuffers); // Configure the DS3D listener. if(dsListener) { IDirectSound3DListener_SetDistanceFactor(dsListener, 1/36.0f, DS3D_DEFERRED); IDirectSound3DListener_SetDopplerFactor(dsListener, 2, DS3D_DEFERRED); } // Success! initOk = true; return true; }
/* This function tries to create a primary audio buffer, and returns the number of audio chunks available in the created buffer. */ static int CreatePrimary(LPDIRECTSOUND sndObj, HWND focus, LPDIRECTSOUNDBUFFER *sndbuf, WAVEFORMATEX *wavefmt, Uint32 chunksize) { HRESULT result; DSBUFFERDESC format; DSBCAPS caps; int numchunks; /* Try to set primary mixing privileges */ result = IDirectSound_SetCooperativeLevel(sndObj, focus, DSSCL_WRITEPRIMARY); if ( result != DS_OK ) { #ifdef DEBUG_SOUND SetDSerror("DirectSound SetCooperativeLevel", result); #endif return(-1); } /* Try to create the primary buffer */ memset(&format, 0, sizeof(format)); format.dwSize = sizeof(format); format.dwFlags=(DSBCAPS_PRIMARYBUFFER|DSBCAPS_GETCURRENTPOSITION2); format.dwFlags |= DSBCAPS_STICKYFOCUS; #ifdef USE_POSITION_NOTIFY format.dwFlags |= DSBCAPS_CTRLPOSITIONNOTIFY; #endif result = IDirectSound_CreateSoundBuffer(sndObj, &format, sndbuf, NULL); if ( result != DS_OK ) { #ifdef DEBUG_SOUND SetDSerror("DirectSound CreateSoundBuffer", result); #endif return(-1); } /* Check the size of the fragment buffer */ memset(&caps, 0, sizeof(caps)); caps.dwSize = sizeof(caps); result = IDirectSoundBuffer_GetCaps(*sndbuf, &caps); if ( result != DS_OK ) { #ifdef DEBUG_SOUND SetDSerror("DirectSound GetCaps", result); #endif IDirectSoundBuffer_Release(*sndbuf); return(-1); } if ( (chunksize > caps.dwBufferBytes) || ((caps.dwBufferBytes%chunksize) != 0) ) { /* The primary buffer size is not a multiple of 'chunksize' -- this hopefully doesn't happen when 'chunksize' is a power of 2. */ IDirectSoundBuffer_Release(*sndbuf); SDL_SetError( "Primary buffer size is: %d, cannot break it into chunks of %d bytes\n", caps.dwBufferBytes, chunksize); return(-1); } numchunks = (caps.dwBufferBytes/chunksize); /* Set the primary audio format */ result = IDirectSoundBuffer_SetFormat(*sndbuf, wavefmt); if ( result != DS_OK ) { #ifdef DEBUG_SOUND SetDSerror("DirectSound SetFormat", result); #endif IDirectSoundBuffer_Release(*sndbuf); return(-1); } return(numchunks); }
void I2_KillSource(sndsource_t *src) { if(src->source3D) IDirectSound3DBuffer_Release(src->source3D); if(src->source) IDirectSoundBuffer_Release(src->source); memset(src, 0, sizeof(*src)); }
static ALCboolean DSoundResetPlayback(ALCdevice *device) { DSoundData *pData = (DSoundData*)device->ExtraData; DSBUFFERDESC DSBDescription; WAVEFORMATEXTENSIBLE OutputType; DWORD speakers; HRESULT hr; memset(&OutputType, 0, sizeof(OutputType)); switch(device->FmtType) { case DevFmtByte: device->FmtType = DevFmtUByte; break; case DevFmtUShort: device->FmtType = DevFmtShort; break; case DevFmtUByte: case DevFmtShort: case DevFmtFloat: break; } hr = IDirectSound_GetSpeakerConfig(pData->lpDS, &speakers); if(SUCCEEDED(hr) && ConfigValueExists(NULL, "format")) { switch(device->FmtChans) { case DevFmtMono: speakers = DSSPEAKER_COMBINED(DSSPEAKER_MONO, 0); break; case DevFmtStereo: speakers = DSSPEAKER_COMBINED(DSSPEAKER_STEREO, 0); break; case DevFmtQuad: speakers = DSSPEAKER_COMBINED(DSSPEAKER_QUAD, 0); break; case DevFmtX51: speakers = DSSPEAKER_COMBINED(DSSPEAKER_5POINT1, 0); break; case DevFmtX61: /* ??? */ ; break; case DevFmtX71: speakers = DSSPEAKER_COMBINED(DSSPEAKER_7POINT1, 0); break; } } if(SUCCEEDED(hr)) { speakers = DSSPEAKER_CONFIG(speakers); if(speakers == DSSPEAKER_MONO) { device->FmtChans = DevFmtMono; OutputType.dwChannelMask = SPEAKER_FRONT_CENTER; } else if(speakers == DSSPEAKER_STEREO || speakers == DSSPEAKER_HEADPHONE) { device->FmtChans = DevFmtStereo; OutputType.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT; } else if(speakers == DSSPEAKER_QUAD) { device->FmtChans = DevFmtQuad; OutputType.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT; } else if(speakers == DSSPEAKER_5POINT1) { device->FmtChans = DevFmtX51; OutputType.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT; } else if(speakers == DSSPEAKER_7POINT1) { device->FmtChans = DevFmtX71; OutputType.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT | SPEAKER_SIDE_LEFT | SPEAKER_SIDE_RIGHT; } OutputType.Format.wFormatTag = WAVE_FORMAT_PCM; OutputType.Format.nChannels = ChannelsFromDevFmt(device->FmtChans); OutputType.Format.wBitsPerSample = BytesFromDevFmt(device->FmtType) * 8; OutputType.Format.nBlockAlign = OutputType.Format.nChannels*OutputType.Format.wBitsPerSample/8; OutputType.Format.nSamplesPerSec = device->Frequency; OutputType.Format.nAvgBytesPerSec = OutputType.Format.nSamplesPerSec*OutputType.Format.nBlockAlign; OutputType.Format.cbSize = 0; } if(OutputType.Format.nChannels > 2 || OutputType.Format.wBitsPerSample > 16) { OutputType.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; OutputType.Samples.wValidBitsPerSample = OutputType.Format.wBitsPerSample; OutputType.Format.cbSize = 22; if(OutputType.Format.wBitsPerSample == 32) OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT; else OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; } else { if(SUCCEEDED(hr)) { memset(&DSBDescription,0,sizeof(DSBUFFERDESC)); DSBDescription.dwSize=sizeof(DSBUFFERDESC); DSBDescription.dwFlags=DSBCAPS_PRIMARYBUFFER; hr = IDirectSound_CreateSoundBuffer(pData->lpDS, &DSBDescription, &pData->DSpbuffer, NULL); } if(SUCCEEDED(hr)) hr = IDirectSoundBuffer_SetFormat(pData->DSpbuffer,&OutputType.Format); } if(SUCCEEDED(hr)) { memset(&DSBDescription,0,sizeof(DSBUFFERDESC)); DSBDescription.dwSize=sizeof(DSBUFFERDESC); DSBDescription.dwFlags=DSBCAPS_GLOBALFOCUS|DSBCAPS_GETCURRENTPOSITION2; DSBDescription.dwBufferBytes=device->UpdateSize * device->NumUpdates * OutputType.Format.nBlockAlign; DSBDescription.lpwfxFormat=&OutputType.Format; hr = IDirectSound_CreateSoundBuffer(pData->lpDS, &DSBDescription, &pData->DSsbuffer, NULL); } if(SUCCEEDED(hr)) { SetDefaultWFXChannelOrder(device); pData->thread = StartThread(DSoundProc, device); if(!pData->thread) hr = E_FAIL; } if(FAILED(hr)) { if (pData->DSsbuffer) IDirectSoundBuffer_Release(pData->DSsbuffer); pData->DSsbuffer = NULL; if (pData->DSpbuffer) IDirectSoundBuffer_Release(pData->DSpbuffer); pData->DSpbuffer = NULL; return ALC_FALSE; } return ALC_TRUE; }
static GstCaps * gst_directsound_probe_supported_formats (GstDirectSoundSink * dsoundsink, const GstCaps * template_caps) { HRESULT hRes; DSBUFFERDESC descSecondary; WAVEFORMATEX wfx; GstCaps *caps; GstCaps *tmp, *tmp2; LPDIRECTSOUNDBUFFER tmpBuffer; caps = gst_caps_copy (template_caps); /* * Check availability of digital output by trying to create an SPDIF buffer */ #ifdef WAVE_FORMAT_DOLBY_AC3_SPDIF /* fill the WAVEFORMATEX structure with some standard AC3 over SPDIF params */ memset (&wfx, 0, sizeof (wfx)); wfx.cbSize = 0; wfx.wFormatTag = WAVE_FORMAT_DOLBY_AC3_SPDIF; wfx.nChannels = 2; wfx.nSamplesPerSec = 48000; wfx.wBitsPerSample = 16; wfx.nBlockAlign = 4; wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign; // create a secondary directsound buffer memset (&descSecondary, 0, sizeof (DSBUFFERDESC)); descSecondary.dwSize = sizeof (DSBUFFERDESC); descSecondary.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_GLOBALFOCUS; descSecondary.dwBufferBytes = 6144; descSecondary.lpwfxFormat = &wfx; hRes = IDirectSound_CreateSoundBuffer (dsoundsink->pDS, &descSecondary, &tmpBuffer, NULL); if (FAILED (hRes)) { GST_INFO_OBJECT (dsoundsink, "AC3 passthrough not supported " "(IDirectSound_CreateSoundBuffer returned: %s)\n", DXGetErrorString9 (hRes)); tmp = gst_caps_new_empty_simple ("audio/x-ac3"); tmp2 = gst_caps_subtract (caps, tmp); gst_caps_unref (tmp); gst_caps_unref (caps); caps = tmp2; tmp = gst_caps_new_empty_simple ("audio/x-dts"); tmp2 = gst_caps_subtract (caps, tmp); gst_caps_unref (tmp); gst_caps_unref (caps); caps = tmp2; } else { GST_INFO_OBJECT (dsoundsink, "AC3 passthrough supported"); hRes = IDirectSoundBuffer_Release (tmpBuffer); if (FAILED (hRes)) { GST_DEBUG_OBJECT (dsoundsink, "(IDirectSoundBuffer_Release returned: %s)\n", DXGetErrorString9 (hRes)); } } #else tmp = gst_caps_new_empty_simple ("audio/x-ac3"); tmp2 = gst_caps_subtract (caps, tmp); gst_caps_unref (tmp); gst_caps_unref (caps); caps = tmp2; tmp = gst_caps_new_empty_simple ("audio/x-dts"); tmp2 = gst_caps_subtract (caps, tmp); gst_caps_unref (tmp); gst_caps_unref (caps); caps = tmp2; #endif return caps; }
static int DirectSound_start_audio_stream(int stereo) { HRESULT hr; DSBUFFERDESC dsbd; LPDIRECTSOUNDBUFFER primary_buffer; WAVEFORMATEX wfx; VOID *area1,*area2; DWORD len_area1,len_area2; is_stereo = stereo; stereo_factor = (is_stereo ? 2 : 1); /* determine the number of samples per frame */ samples_per_frame = (double)Machine->sample_rate / (double)Machine->drv->frames_per_second; /* compute how many samples to generate this frame */ samples_left_over = samples_per_frame; samples_this_frame = (UINT32)samples_left_over + EXTRA_SAMPLES; samples_left_over -= (double)samples_this_frame; hr = IDirectSound_SetCooperativeLevel(ds, MAME32App.m_hWnd, DSSCL_PRIORITY); if (FAILED(hr)) ErrorMsg("Unable to set priority cooperative level for sound: %s",DirectXDecodeError(hr)); memset(&dsbd,0,sizeof(dsbd)); dsbd.dwSize = sizeof(dsbd); dsbd.dwFlags = DSBCAPS_PRIMARYBUFFER; hr = IDirectSound_CreateSoundBuffer(ds,&dsbd,&primary_buffer,NULL); if (FAILED(hr)) { ErrorMsg("Unable to create primary sound buffer: %s",DirectXDecodeError(hr)); return 1; } memset(&wfx,0,sizeof(wfx)); wfx.wFormatTag = WAVE_FORMAT_PCM; wfx.nChannels = (stereo != 0) ? 2 : 1; wfx.nSamplesPerSec = Machine->sample_rate; wfx.wBitsPerSample = 16; wfx.nBlockAlign = wfx.wBitsPerSample / 8 * wfx.nChannels; wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign; hr = IDirectSoundBuffer_SetFormat(primary_buffer,&wfx); if (FAILED(hr)) { ErrorMsg("Unable to set format of primary sound buffer: %s",DirectXDecodeError(hr)); IDirectSoundBuffer_Release(primary_buffer); return 1; } IDirectSoundBuffer_Play(primary_buffer,0,0,DSBPLAY_LOOPING); IDirectSoundBuffer_Release(primary_buffer); hr = IDirectSound_SetCooperativeLevel(ds,MAME32App.m_hWnd,DSSCL_NORMAL); if (FAILED(hr)) ErrorMsg("Unable to set normal cooperative level for sound: %s",DirectXDecodeError(hr)); wfx.nChannels = stereo_factor; dsb = NULL; memset(&dsbd,0,sizeof(dsbd)); dsbd.dwSize = sizeof(dsbd); dsbd.dwFlags = DSBCAPS_GETCURRENTPOSITION2 // Always a good idea | DSBCAPS_CTRLPAN | DSBCAPS_CTRLVOLUME | DSBCAPS_GLOBALFOCUS; // Allows background playing buffer_length = Machine->sample_rate*sizeof(INT16)*stereo_factor*BUFFER_SIZE_MILLIS/1000; // sound pukes if it's not aligned to 16 byte length buffer_length = (buffer_length + 15) & ~15; dsbd.dwBufferBytes = buffer_length; dsbd.lpwfxFormat = &wfx; hr = IDirectSound_CreateSoundBuffer(ds,&dsbd,&dsb,NULL); if (FAILED(hr)) { ErrorMsg("Unable to create secondary sound buffer: %s",DirectXDecodeError(hr)); dsb = NULL; return 0; } // clear it out, because we start playing it instantly hr = IDirectSoundBuffer_Lock(dsb,0,buffer_length,&area1,&len_area1,&area2,&len_area2,0); if (FAILED(hr)) { ErrorMsg("Unable to lock secondary sound buffer: %s",DirectXDecodeError(hr)); } else { memset(area1,0,len_area1); memset(area2,0,len_area2); hr = IDirectSoundBuffer_Unlock(dsb,area1,len_area1,area2,len_area2); if (FAILED(hr)) ErrorMsg("Unable to unlock secondary sound buffer: %s",DirectXDecodeError(hr)); } hr = IDirectSoundBuffer_Play(dsb,0,0,DSBPLAY_LOOPING); if (FAILED(hr)) ErrorMsg("Unable to play secondary sound buffer: %s",DirectXDecodeError(hr)); voice_pos = 0; return samples_this_frame; }
static BOOL WINAPI dsenum_callback(LPGUID lpGuid, LPCSTR lpcstrDescription, LPCSTR lpcstrModule, LPVOID lpContext) { HRESULT rc; LPDIRECTSOUND dso=NULL; LPDIRECTSOUNDBUFFER primary=NULL,secondary=NULL; DSBUFFERDESC bufdesc; WAVEFORMATEX wfx; int ref; trace("*** Testing %s - %s ***\n",lpcstrDescription,lpcstrModule); driver_count++; rc=pDirectSoundCreate(lpGuid,&dso,NULL); ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||rc==E_FAIL, "DirectSoundCreate() failed: %08x\n",rc); if (rc!=DS_OK) { if (rc==DSERR_NODRIVER) trace(" No Driver\n"); else if (rc == DSERR_ALLOCATED) trace(" Already In Use\n"); else if (rc == E_FAIL) trace(" No Device\n"); goto EXIT; } /* We must call SetCooperativeLevel before calling CreateSoundBuffer */ /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */ rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY); ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel() failed: %08x\n", rc); if (rc!=DS_OK) goto EXIT; /* Testing 3D buffers */ primary=NULL; ZeroMemory(&bufdesc, sizeof(bufdesc)); bufdesc.dwSize=sizeof(bufdesc); bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_LOCHARDWARE|DSBCAPS_CTRL3D; rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL); ok((rc==DS_OK&&primary!=NULL) || broken(rc==DSERR_INVALIDPARAM), "IDirectSound_CreateSoundBuffer() failed to " "create a hardware 3D primary buffer: %08x\n",rc); if(rc==DSERR_INVALIDPARAM) { skip("broken driver\n"); goto EXIT; } if (rc==DS_OK&&primary!=NULL) { ZeroMemory(&wfx, sizeof(wfx)); wfx.wFormatTag=WAVE_FORMAT_PCM; wfx.nChannels=1; wfx.wBitsPerSample=16; wfx.nSamplesPerSec=44100; wfx.nBlockAlign=wfx.nChannels*wfx.wBitsPerSample/8; wfx.nAvgBytesPerSec=wfx.nSamplesPerSec*wfx.nBlockAlign; ZeroMemory(&bufdesc, sizeof(bufdesc)); bufdesc.dwSize=sizeof(bufdesc); bufdesc.dwFlags=DSBCAPS_CTRLDEFAULT|DSBCAPS_GETCURRENTPOSITION2; bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec; bufdesc.lpwfxFormat=&wfx; trace(" Testing a secondary buffer at %dx%dx%d\n", wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels); rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL); ok((rc==DS_OK && secondary!=NULL) || broken(rc == DSERR_CONTROLUNAVAIL), /* vmware drivers on w2k */ "IDirectSound_CreateSoundBuffer() failed to create a secondary buffer: %08x\n",rc); if (rc==DS_OK&&secondary!=NULL) { IKsPropertySet * pPropertySet=NULL; rc=IDirectSoundBuffer_QueryInterface(secondary, &IID_IKsPropertySet, (void **)&pPropertySet); /* it's not an error for this to fail */ if(rc==DS_OK) { ULONG ulTypeSupport; trace(" Supports property sets\n"); /* it's not an error for these to fail */ rc=IKsPropertySet_QuerySupport(pPropertySet, &DSPROPSETID_VoiceManager, 0,&ulTypeSupport); if((rc==DS_OK)&&(ulTypeSupport&(KSPROPERTY_SUPPORT_GET| KSPROPERTY_SUPPORT_SET))) trace(" DSPROPSETID_VoiceManager supported\n"); else trace(" DSPROPSETID_VoiceManager not supported\n"); rc=IKsPropertySet_QuerySupport(pPropertySet, &DSPROPSETID_EAX20_ListenerProperties,0,&ulTypeSupport); if((rc==DS_OK)&&(ulTypeSupport&(KSPROPERTY_SUPPORT_GET| KSPROPERTY_SUPPORT_SET))) trace(" DSPROPSETID_EAX20_ListenerProperties " "supported\n"); else trace(" DSPROPSETID_EAX20_ListenerProperties not " "supported\n"); rc=IKsPropertySet_QuerySupport(pPropertySet, &DSPROPSETID_EAX20_BufferProperties,0,&ulTypeSupport); if((rc==DS_OK)&&(ulTypeSupport&(KSPROPERTY_SUPPORT_GET| KSPROPERTY_SUPPORT_SET))) trace(" DSPROPSETID_EAX20_BufferProperties supported\n"); else trace(" DSPROPSETID_EAX20_BufferProperties not " "supported\n"); rc=IKsPropertySet_QuerySupport(pPropertySet, &DSPROPSETID_I3DL2_ListenerProperties,0,&ulTypeSupport); if((rc==DS_OK)&&(ulTypeSupport&(KSPROPERTY_SUPPORT_GET| KSPROPERTY_SUPPORT_SET))) trace(" DSPROPSETID_I3DL2_ListenerProperties " "supported\n"); else trace(" DSPROPSETID_I3DL2_ListenerProperties not " "supported\n"); rc=IKsPropertySet_QuerySupport(pPropertySet, &DSPROPSETID_I3DL2_BufferProperties,0,&ulTypeSupport); if((rc==DS_OK)&&(ulTypeSupport&(KSPROPERTY_SUPPORT_GET| KSPROPERTY_SUPPORT_SET))) trace(" DSPROPSETID_I3DL2_BufferProperties supported\n"); else trace(" DSPROPSETID_I3DL2_BufferProperties not " "supported\n"); rc=IKsPropertySet_QuerySupport(pPropertySet, &DSPROPSETID_ZOOMFX_BufferProperties,0,&ulTypeSupport); if((rc==DS_OK)&&(ulTypeSupport&(KSPROPERTY_SUPPORT_GET| KSPROPERTY_SUPPORT_SET))) trace(" DSPROPSETID_ZOOMFX_BufferProperties " "supported\n"); else trace(" DSPROPSETID_ZOOMFX_BufferProperties not " "supported\n"); ref=IKsPropertySet_Release(pPropertySet); /* try a few common ones */ ok(ref==0,"IKsPropertySet_Release() secondary has %d " "references, should have 0\n",ref); } else trace(" Doesn't support property sets\n"); ref=IDirectSoundBuffer_Release(secondary); ok(ref==0,"IDirectSoundBuffer_Release() secondary has %d " "references, should have 0\n",ref); } ref=IDirectSoundBuffer_Release(primary); ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, " "should have 0\n",ref); } EXIT: if (dso!=NULL) { ref=IDirectSound_Release(dso); ok(ref==0,"IDirectSound_Release() has %d references, should have 0\n", ref); } return TRUE; }
static ALCboolean DSoundResetPlayback(ALCdevice *device) { DSoundData *pData = (DSoundData*)device->ExtraData; DSBUFFERDESC DSBDescription; WAVEFORMATEXTENSIBLE OutputType; DWORD frameSize = 0; ALenum format = 0; DWORD speakers; HRESULT hr; memset(&OutputType, 0, sizeof(OutputType)); hr = IDirectSound_GetSpeakerConfig(pData->lpDS, &speakers); if(SUCCEEDED(hr) && ConfigValueExists(NULL, "format")) { if(aluChannelsFromFormat(device->Format) == 1) speakers = DSSPEAKER_COMBINED(DSSPEAKER_MONO, 0); else if(aluChannelsFromFormat(device->Format) == 2) speakers = DSSPEAKER_COMBINED(DSSPEAKER_STEREO, 0); else if(aluChannelsFromFormat(device->Format) == 4) speakers = DSSPEAKER_COMBINED(DSSPEAKER_QUAD, 0); else if(aluChannelsFromFormat(device->Format) == 6) speakers = DSSPEAKER_COMBINED(DSSPEAKER_5POINT1, 0); else if(aluChannelsFromFormat(device->Format) == 8) speakers = DSSPEAKER_COMBINED(DSSPEAKER_7POINT1, 0); else { AL_PRINT("Unknown format: 0x%x\n", device->Format); return ALC_FALSE; } } if(SUCCEEDED(hr)) { speakers = DSSPEAKER_CONFIG(speakers); if(speakers == DSSPEAKER_MONO) { if(aluBytesFromFormat(device->Format) == 1) format = AL_FORMAT_MONO8; else if(aluBytesFromFormat(device->Format) == 2) format = AL_FORMAT_MONO16; else if(aluBytesFromFormat(device->Format) == 4) format = AL_FORMAT_MONO_FLOAT32; OutputType.dwChannelMask = SPEAKER_FRONT_CENTER; } else if(speakers == DSSPEAKER_STEREO) { if(aluBytesFromFormat(device->Format) == 1) format = AL_FORMAT_STEREO8; else if(aluBytesFromFormat(device->Format) == 2) format = AL_FORMAT_STEREO16; else if(aluBytesFromFormat(device->Format) == 4) format = AL_FORMAT_STEREO_FLOAT32; OutputType.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT; } else if(speakers == DSSPEAKER_QUAD) { if(aluBytesFromFormat(device->Format) == 1) format = AL_FORMAT_QUAD8; else if(aluBytesFromFormat(device->Format) == 2) format = AL_FORMAT_QUAD16; else if(aluBytesFromFormat(device->Format) == 4) format = AL_FORMAT_QUAD32; OutputType.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT; } else if(speakers == DSSPEAKER_5POINT1) { if(aluBytesFromFormat(device->Format) == 1) format = AL_FORMAT_51CHN8; else if(aluBytesFromFormat(device->Format) == 2) format = AL_FORMAT_51CHN16; else if(aluBytesFromFormat(device->Format) == 4) format = AL_FORMAT_51CHN32; OutputType.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT; } else if(speakers == DSSPEAKER_7POINT1) { if(aluBytesFromFormat(device->Format) == 1) format = AL_FORMAT_71CHN8; else if(aluBytesFromFormat(device->Format) == 2) format = AL_FORMAT_71CHN16; else if(aluBytesFromFormat(device->Format) == 4) format = AL_FORMAT_71CHN32; OutputType.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT | SPEAKER_SIDE_LEFT | SPEAKER_SIDE_RIGHT; } else format = device->Format; frameSize = aluFrameSizeFromFormat(format); OutputType.Format.wFormatTag = WAVE_FORMAT_PCM; OutputType.Format.nChannels = aluChannelsFromFormat(format); OutputType.Format.wBitsPerSample = aluBytesFromFormat(format) * 8; OutputType.Format.nBlockAlign = OutputType.Format.nChannels*OutputType.Format.wBitsPerSample/8; OutputType.Format.nSamplesPerSec = device->Frequency; OutputType.Format.nAvgBytesPerSec = OutputType.Format.nSamplesPerSec*OutputType.Format.nBlockAlign; OutputType.Format.cbSize = 0; } if(OutputType.Format.nChannels > 2 || OutputType.Format.wBitsPerSample > 16) { OutputType.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; OutputType.Samples.wValidBitsPerSample = OutputType.Format.wBitsPerSample; OutputType.Format.cbSize = 22; if(OutputType.Format.wBitsPerSample == 32) OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT; else OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; } else { if(SUCCEEDED(hr)) { memset(&DSBDescription,0,sizeof(DSBUFFERDESC)); DSBDescription.dwSize=sizeof(DSBUFFERDESC); DSBDescription.dwFlags=DSBCAPS_PRIMARYBUFFER; hr = IDirectSound_CreateSoundBuffer(pData->lpDS, &DSBDescription, &pData->DSpbuffer, NULL); } if(SUCCEEDED(hr)) hr = IDirectSoundBuffer_SetFormat(pData->DSpbuffer,&OutputType.Format); } if(SUCCEEDED(hr)) { memset(&DSBDescription,0,sizeof(DSBUFFERDESC)); DSBDescription.dwSize=sizeof(DSBUFFERDESC); DSBDescription.dwFlags=DSBCAPS_GLOBALFOCUS|DSBCAPS_GETCURRENTPOSITION2; DSBDescription.dwBufferBytes=device->UpdateSize * device->NumUpdates * frameSize; DSBDescription.lpwfxFormat=&OutputType.Format; hr = IDirectSound_CreateSoundBuffer(pData->lpDS, &DSBDescription, &pData->DSsbuffer, NULL); } if(SUCCEEDED(hr)) hr = IDirectSoundBuffer_Play(pData->DSsbuffer, 0, 0, DSBPLAY_LOOPING); if(SUCCEEDED(hr)) { device->Format = format; SetDefaultWFXChannelOrder(device); pData->thread = StartThread(DSoundProc, device); if(!pData->thread) hr = E_FAIL; } if(FAILED(hr)) { if (pData->DSsbuffer) IDirectSoundBuffer_Release(pData->DSsbuffer); pData->DSsbuffer = NULL; if (pData->DSpbuffer) IDirectSoundBuffer_Release(pData->DSpbuffer); pData->DSpbuffer = NULL; return ALC_FALSE; } return ALC_TRUE; }
static int dsound_create_buffers(void) { HRESULT result; void *buffer; DWORD locked; // create a buffer desc for the primary buffer primary_desc.dwSize = sizeof(primary_desc); primary_desc.dwFlags = DSBCAPS_PRIMARYBUFFER | DSBCAPS_GETCURRENTPOSITION2; primary_desc.lpwfxFormat = NULL; // create the primary buffer result = IDirectSound_CreateSoundBuffer(dsound, &primary_desc, &primary_buffer, NULL); if (result != DS_OK) { fprintf(stderr, "Error creating primary buffer: %08x\n", (UINT32)result); goto cant_create_primary; } // attempt to set the primary format result = IDirectSoundBuffer_SetFormat(primary_buffer, &stream_format); if (result != DS_OK) { fprintf(stderr, "Error setting primary format: %08x\n", (UINT32)result); goto cant_set_primary_format; } // get the primary format result = IDirectSoundBuffer_GetFormat(primary_buffer, &primary_format, sizeof(primary_format), NULL); if (result != DS_OK) { fprintf(stderr, "Error getting primary format: %08x\n", (UINT32)result); goto cant_get_primary_format; } if (verbose) fprintf(stderr, "Primary buffer: %d Hz, %d bits, %d channels\n", (int)primary_format.nSamplesPerSec, (int)primary_format.wBitsPerSample, (int)primary_format.nChannels); // create a buffer desc for the stream buffer stream_desc.dwSize = sizeof(stream_desc); stream_desc.dwFlags = DSBCAPS_CTRLVOLUME | DSBCAPS_GLOBALFOCUS | DSBCAPS_GETCURRENTPOSITION2; stream_desc.dwBufferBytes = stream_buffer_size; stream_desc.lpwfxFormat = &stream_format; // create the stream buffer result = IDirectSound_CreateSoundBuffer(dsound, &stream_desc, &stream_buffer, NULL); if (result != DS_OK) { fprintf(stderr, "Error creating DirectSound buffer: %08x\n", (UINT32)result); goto cant_create_buffer; } // lock the buffer result = IDirectSoundBuffer_Lock(stream_buffer, 0, stream_buffer_size, &buffer, &locked, NULL, NULL, 0); if (result != DS_OK) { fprintf(stderr, "Error locking stream buffer: %08x\n", (UINT32)result); goto cant_lock_buffer; } // clear the buffer and unlock it memset(buffer, 0, locked); IDirectSoundBuffer_Unlock(stream_buffer, buffer, locked, NULL, 0); return 0; // error handling cant_lock_buffer: IDirectSoundBuffer_Release(stream_buffer); cant_create_buffer: stream_buffer = NULL; cant_get_primary_format: cant_set_primary_format: IDirectSoundBuffer_Release(primary_buffer); cant_create_primary: primary_buffer = NULL; return 0; }
/* ==================== SndSys_Shutdown Stop the sound card, delete "snd_renderbuffer" and free its other resources ==================== */ void SndSys_Shutdown (void) { #ifdef SUPPORTDIRECTX if (pDSBuf) { IDirectSoundBuffer_Stop(pDSBuf); IDirectSoundBuffer_Release(pDSBuf); } // only release primary buffer if it's not also the mixing buffer we just released if (pDSPBuf && (pDSBuf != pDSPBuf)) { IDirectSoundBuffer_Release(pDSPBuf); } if (pDS) { IDirectSound_SetCooperativeLevel (pDS, mainwindow, DSSCL_NORMAL); IDirectSound_Release(pDS); } #endif if (hWaveOut) { waveOutReset (hWaveOut); if (lpWaveHdr) { unsigned int i; for (i=0 ; i< WAV_BUFFERS ; i++) waveOutUnprepareHeader (hWaveOut, lpWaveHdr+i, sizeof(WAVEHDR)); } waveOutClose (hWaveOut); if (hWaveHdr) { GlobalUnlock(hWaveHdr); GlobalFree(hWaveHdr); } if (hData) { GlobalUnlock(hData); GlobalFree(hData); } } if (snd_renderbuffer != NULL) { Mem_Free(snd_renderbuffer); snd_renderbuffer = NULL; } #ifdef SUPPORTDIRECTX pDS = NULL; pDSBuf = NULL; pDSPBuf = NULL; dsound_init = false; #endif hWaveOut = 0; hData = 0; hWaveHdr = 0; lpData = NULL; lpWaveHdr = NULL; wav_init = false; }
static HRESULT test_primary8(LPGUID lpGuid) { HRESULT rc; LPDIRECTSOUND8 dso=NULL; LPDIRECTSOUNDBUFFER primary=NULL,second=NULL,third=NULL; LPDIRECTSOUNDBUFFER8 pb8 = NULL; DSBUFFERDESC bufdesc; DSCAPS dscaps; WAVEFORMATEX wfx; int ref; /* Create the DirectSound object */ rc=pDirectSoundCreate8(lpGuid,&dso,NULL); ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED, "DirectSoundCreate8() failed: %08x\n",rc); if (rc!=DS_OK) return rc; /* Get the device capabilities */ ZeroMemory(&dscaps, sizeof(dscaps)); dscaps.dwSize=sizeof(dscaps); rc=IDirectSound8_GetCaps(dso,&dscaps); ok(rc==DS_OK,"IDirectSound8_GetCaps() failed: %08x\n",rc); if (rc!=DS_OK) goto EXIT; /* DSOUND: Error: Invalid buffer description pointer */ rc=IDirectSound8_CreateSoundBuffer(dso,0,0,NULL); ok(rc==DSERR_INVALIDPARAM, "IDirectSound8_CreateSoundBuffer should have returned " "DSERR_INVALIDPARAM, returned: %08x\n",rc); /* DSOUND: Error: Invalid buffer description pointer */ rc=IDirectSound8_CreateSoundBuffer(dso,0,&primary,NULL); ok(rc==DSERR_INVALIDPARAM && primary==0, "IDirectSound8_CreateSoundBuffer() should have returned " "DSERR_INVALIDPARAM, returned: rc=%08x,dsbo=%p\n", rc,primary); ZeroMemory(&bufdesc, sizeof(bufdesc)); bufdesc.dwSize = sizeof(DSBUFFERDESC); /* DSOUND: Error: Invalid dsound buffer interface pointer */ rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,0,NULL); ok(rc==DSERR_INVALIDPARAM && primary==0, "IDirectSound8_CreateSoundBuffer() should have failed: rc=%08x," "dsbo=%p\n",rc,primary); ZeroMemory(&bufdesc, sizeof(bufdesc)); /* DSOUND: Error: Invalid size */ /* DSOUND: Error: Invalid buffer description */ rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&primary,NULL); ok(rc==DSERR_INVALIDPARAM && primary==0, "IDirectSound8_CreateSoundBuffer() should have failed: rc=%08x," "primary=%p\n",rc,primary); /* We must call SetCooperativeLevel before calling CreateSoundBuffer */ /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */ rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY); ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel() failed: %08x\n", rc); if (rc!=DS_OK) goto EXIT; /* Testing the primary buffer */ primary=NULL; ZeroMemory(&bufdesc, sizeof(bufdesc)); bufdesc.dwSize=sizeof(bufdesc); bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRLVOLUME; bufdesc.lpwfxFormat = &wfx; init_format(&wfx,WAVE_FORMAT_PCM,11025,8,2); rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&primary,NULL); ok(rc==DSERR_INVALIDPARAM,"IDirectSound8_CreateSoundBuffer() should have " "returned DSERR_INVALIDPARAM, returned: %08x\n", rc); if (rc==DS_OK && primary!=NULL) IDirectSoundBuffer_Release(primary); primary=NULL; ZeroMemory(&bufdesc, sizeof(bufdesc)); bufdesc.dwSize=sizeof(bufdesc); bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRLVOLUME; rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&primary,NULL); ok((rc==DS_OK && primary!=NULL) || (rc==DSERR_CONTROLUNAVAIL), "IDirectSound8_CreateSoundBuffer() failed to create a primary buffer: " "%08x\n",rc); if (rc==DSERR_CONTROLUNAVAIL) trace(" No Primary\n"); else if (rc==DS_OK && primary!=NULL) { LONG vol; /* Try to create a second primary buffer */ /* DSOUND: Error: The primary buffer already exists. * Any changes made to the buffer description will be ignored. */ rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&second,NULL); ok(rc==DS_OK && second==primary, "IDirectSound8_CreateSoundBuffer() should have returned original " "primary buffer: %08x\n",rc); ref=IDirectSoundBuffer_Release(second); ok(ref==1,"IDirectSoundBuffer_Release() primary has %d references, " "should have 1\n",ref); /* Try to duplicate a primary buffer */ /* DSOUND: Error: Can't duplicate primary buffers */ rc=IDirectSound8_DuplicateSoundBuffer(dso,primary,&third); /* rc=0x88780032 */ ok(rc!=DS_OK,"IDirectSound8_DuplicateSoundBuffer() primary buffer " "should have failed %08x\n",rc); /* Primary buffers don't have an IDirectSoundBuffer8 */ rc = IDirectSoundBuffer_QueryInterface(primary, &IID_IDirectSoundBuffer8, (LPVOID*)&pb8); ok(FAILED(rc), "Primary buffer does have an IDirectSoundBuffer8: %08x\n", rc); rc=IDirectSoundBuffer_GetVolume(primary,&vol); ok(rc==DS_OK,"IDirectSoundBuffer_GetVolume() failed: %08x\n", rc); if (winetest_interactive) { trace("Playing a 5 seconds reference tone at the current volume.\n"); if (rc==DS_OK) trace("(the current volume is %d according to DirectSound)\n", vol); trace("All subsequent tones should be identical to this one.\n"); trace("Listen for stutter, changes in pitch, volume, etc.\n"); } test_buffer8(dso,&primary,1,FALSE,0,FALSE,0,winetest_interactive && !(dscaps.dwFlags & DSCAPS_EMULDRIVER),5.0,0,0,0,0); ref=IDirectSoundBuffer_Release(primary); ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, " "should have 0\n",ref); } /* Set the CooperativeLevel back to normal */ /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */ rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL); ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel() failed: %08x\n", rc); EXIT: ref=IDirectSound8_Release(dso); ok(ref==0,"IDirectSound8_Release() has %d references, should have 0\n",ref); if (ref!=0) return DSERR_GENERIC; return rc; }
/** * Creates a DirectSound buffer of the required format. * * This function creates the buffer we'll use to play audio. * In DirectSound there are two kinds of buffers: * - the primary buffer: which is the actual buffer that the soundcard plays * - the secondary buffer(s): these buffers are the one actually used by * applications and DirectSound takes care of mixing them into the primary. * * Once you create a secondary buffer, you cannot change its format anymore so * you have to release the current one and create another. */ static HRESULT CreateDSBuffer( vlc_object_t *obj, aout_stream_sys_t *sys, int i_format, int i_channels, int i_nb_channels, int i_rate, bool b_probe ) { WAVEFORMATEXTENSIBLE waveformat; DSBUFFERDESC dsbdesc; HRESULT hr; /* First set the sound buffer format */ waveformat.dwChannelMask = 0; for( unsigned i = 0; pi_vlc_chan_order_wg4[i]; i++ ) if( i_channels & pi_vlc_chan_order_wg4[i] ) waveformat.dwChannelMask |= pi_channels_in[i]; switch( i_format ) { case VLC_CODEC_SPDIFL: i_nb_channels = 2; /* To prevent channel re-ordering */ waveformat.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT; waveformat.Format.wBitsPerSample = 16; waveformat.Samples.wValidBitsPerSample = waveformat.Format.wBitsPerSample; waveformat.Format.wFormatTag = WAVE_FORMAT_DOLBY_AC3_SPDIF; waveformat.SubFormat = _KSDATAFORMAT_SUBTYPE_DOLBY_AC3_SPDIF; break; case VLC_CODEC_FL32: waveformat.Format.wBitsPerSample = sizeof(float) * 8; waveformat.Samples.wValidBitsPerSample = waveformat.Format.wBitsPerSample; waveformat.Format.wFormatTag = WAVE_FORMAT_IEEE_FLOAT; waveformat.SubFormat = _KSDATAFORMAT_SUBTYPE_IEEE_FLOAT; break; case VLC_CODEC_S16N: waveformat.Format.wBitsPerSample = 16; waveformat.Samples.wValidBitsPerSample = waveformat.Format.wBitsPerSample; waveformat.Format.wFormatTag = WAVE_FORMAT_PCM; waveformat.SubFormat = _KSDATAFORMAT_SUBTYPE_PCM; break; } waveformat.Format.nChannels = i_nb_channels; waveformat.Format.nSamplesPerSec = i_rate; waveformat.Format.nBlockAlign = waveformat.Format.wBitsPerSample / 8 * i_nb_channels; waveformat.Format.nAvgBytesPerSec = waveformat.Format.nSamplesPerSec * waveformat.Format.nBlockAlign; sys->i_bytes_per_sample = waveformat.Format.nBlockAlign; sys->format = i_format; /* Then fill in the direct sound descriptor */ memset(&dsbdesc, 0, sizeof(DSBUFFERDESC)); dsbdesc.dwSize = sizeof(DSBUFFERDESC); dsbdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 /* Better position accuracy */ | DSBCAPS_GLOBALFOCUS /* Allows background playing */ | DSBCAPS_CTRLVOLUME /* Allows volume control */ | DSBCAPS_CTRLPOSITIONNOTIFY; /* Allow position notifications */ /* Only use the new WAVE_FORMAT_EXTENSIBLE format for multichannel audio */ if( i_nb_channels <= 2 ) { waveformat.Format.cbSize = 0; } else { waveformat.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; waveformat.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX); /* Needed for 5.1 on emu101k */ dsbdesc.dwFlags |= DSBCAPS_LOCHARDWARE; } dsbdesc.dwBufferBytes = DS_BUF_SIZE; /* buffer size */ dsbdesc.lpwfxFormat = (WAVEFORMATEX *)&waveformat; /* CreateSoundBuffer doesn't allow volume control for non-PCM buffers */ if ( i_format == VLC_CODEC_SPDIFL ) dsbdesc.dwFlags &= ~DSBCAPS_CTRLVOLUME; hr = IDirectSound_CreateSoundBuffer( sys->p_dsobject, &dsbdesc, &sys->p_dsbuffer, NULL ); if( FAILED(hr) ) { if( !(dsbdesc.dwFlags & DSBCAPS_LOCHARDWARE) ) return hr; /* Try without DSBCAPS_LOCHARDWARE */ dsbdesc.dwFlags &= ~DSBCAPS_LOCHARDWARE; hr = IDirectSound_CreateSoundBuffer( sys->p_dsobject, &dsbdesc, &sys->p_dsbuffer, NULL ); if( FAILED(hr) ) return hr; if( !b_probe ) msg_Dbg( obj, "couldn't use hardware sound buffer" ); } /* Stop here if we were just probing */ if( b_probe ) { IDirectSoundBuffer_Release( sys->p_dsbuffer ); sys->p_dsbuffer = NULL; return DS_OK; } sys->i_rate = i_rate; sys->i_channel_mask = waveformat.dwChannelMask; sys->chans_to_reorder = aout_CheckChannelReorder( pi_channels_in, pi_channels_out, waveformat.dwChannelMask, sys->chan_table ); if( sys->chans_to_reorder ) msg_Dbg( obj, "channel reordering needed" ); hr = IDirectSoundBuffer_QueryInterface( sys->p_dsbuffer, &IID_IDirectSoundNotify, (void **) &sys->p_notify ); if( hr != DS_OK ) { msg_Err( obj, "Couldn't query IDirectSoundNotify" ); sys->p_notify = NULL; } FillBuffer( obj, sys, NULL ); return DS_OK; }
static HRESULT test_secondary8(LPGUID lpGuid) { HRESULT rc; LPDIRECTSOUND8 dso=NULL; LPDIRECTSOUNDBUFFER primary=NULL,secondary=NULL; DSBUFFERDESC bufdesc; DSCAPS dscaps; WAVEFORMATEX wfx, wfx1; DWORD f; int ref; /* Create the DirectSound object */ rc=pDirectSoundCreate8(lpGuid,&dso,NULL); ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED, "DirectSoundCreate8() failed: %08x\n",rc); if (rc!=DS_OK) return rc; /* Get the device capabilities */ ZeroMemory(&dscaps, sizeof(dscaps)); dscaps.dwSize=sizeof(dscaps); rc=IDirectSound8_GetCaps(dso,&dscaps); ok(rc==DS_OK,"IDirectSound8_GetCaps() failed: %08x\n",rc); if (rc!=DS_OK) goto EXIT; /* We must call SetCooperativeLevel before creating primary buffer */ /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */ rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY); ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel() failed: %08x\n", rc); if (rc!=DS_OK) goto EXIT; ZeroMemory(&bufdesc, sizeof(bufdesc)); bufdesc.dwSize=sizeof(bufdesc); bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER; rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&primary,NULL); ok(rc==DS_OK && primary!=NULL, "IDirectSound8_CreateSoundBuffer() failed to create a primary buffer " "%08x\n",rc); if (rc==DS_OK && primary!=NULL) { rc=IDirectSoundBuffer_GetFormat(primary,&wfx1,sizeof(wfx1),NULL); ok(rc==DS_OK,"IDirectSoundBuffer8_Getformat() failed: %08x\n", rc); if (rc!=DS_OK) goto EXIT1; for (f=0;f<NB_FORMATS;f++) { WAVEFORMATEXTENSIBLE wfxe; init_format(&wfx,WAVE_FORMAT_PCM,formats[f][0],formats[f][1], formats[f][2]); secondary=NULL; ZeroMemory(&bufdesc, sizeof(bufdesc)); bufdesc.dwSize=sizeof(bufdesc); bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2; bufdesc.dwBufferBytes=align(wfx.nAvgBytesPerSec*BUFFER_LEN/1000, wfx.nBlockAlign); rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL); ok(rc==DSERR_INVALIDPARAM,"IDirectSound8_CreateSoundBuffer() " "should have returned DSERR_INVALIDPARAM, returned: %08x\n", rc); if (rc==DS_OK && secondary!=NULL) IDirectSoundBuffer_Release(secondary); secondary=NULL; ZeroMemory(&bufdesc, sizeof(bufdesc)); bufdesc.dwSize=sizeof(bufdesc); bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2; bufdesc.dwBufferBytes=align(wfx.nAvgBytesPerSec*BUFFER_LEN/1000, wfx.nBlockAlign); bufdesc.lpwfxFormat=&wfx; rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL); if (wfx.wBitsPerSample != 8 && wfx.wBitsPerSample != 16) ok(((rc == DSERR_CONTROLUNAVAIL || rc == DSERR_INVALIDCALL || rc == DSERR_INVALIDPARAM /* 2003 */) && !secondary) || rc == DS_OK, /* driver dependent? */ "IDirectSound_CreateSoundBuffer() " "should have returned (DSERR_CONTROLUNAVAIL or DSERR_INVALIDCALL) " "and NULL, returned: %08x %p\n", rc, secondary); else ok(rc==DS_OK && secondary!=NULL, "IDirectSound_CreateSoundBuffer() failed to create a secondary " "buffer %08x\n",rc); if (secondary) IDirectSoundBuffer_Release(secondary); secondary = NULL; bufdesc.lpwfxFormat=(WAVEFORMATEX*)&wfxe; wfxe.Format = wfx; wfxe.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; wfxe.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; wfxe.Format.cbSize = 1; wfxe.Samples.wValidBitsPerSample = wfx.wBitsPerSample; wfxe.dwChannelMask = (wfx.nChannels == 1 ? KSAUDIO_SPEAKER_MONO : KSAUDIO_SPEAKER_STEREO); rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL); ok(rc==DSERR_INVALIDPARAM && !secondary, "IDirectSound_CreateSoundBuffer() returned: %08x %p\n", rc, secondary); if (secondary) { IDirectSoundBuffer_Release(secondary); secondary=NULL; } wfxe.Format.cbSize = sizeof(wfxe) - sizeof(wfx) + 1; rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL); ok(((rc==DSERR_CONTROLUNAVAIL || DSERR_INVALIDCALL /* 2003 */) && !secondary) || rc==DS_OK /* driver dependent? */, "IDirectSound_CreateSoundBuffer() returned: %08x %p\n", rc, secondary); if (secondary) { IDirectSoundBuffer_Release(secondary); secondary=NULL; } wfxe.Format.cbSize = sizeof(wfxe) - sizeof(wfx); wfxe.SubFormat = GUID_NULL; rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL); ok((rc==DSERR_INVALIDPARAM || rc==DSERR_INVALIDCALL) && !secondary, "IDirectSound_CreateSoundBuffer() returned: %08x %p\n", rc, secondary); if (secondary) { IDirectSoundBuffer_Release(secondary); secondary=NULL; } wfxe.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; ++wfxe.Samples.wValidBitsPerSample; rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL); ok(rc==DSERR_INVALIDPARAM && !secondary, "IDirectSound_CreateSoundBuffer() returned: %08x %p\n", rc, secondary); if (secondary) { IDirectSoundBuffer_Release(secondary); secondary=NULL; } --wfxe.Samples.wValidBitsPerSample; wfxe.Samples.wValidBitsPerSample = 0; rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL); ok(rc==DS_OK && secondary, "IDirectSound_CreateSoundBuffer() returned: %08x %p\n", rc, secondary); if (secondary) { IDirectSoundBuffer_Release(secondary); secondary=NULL; } wfxe.Samples.wValidBitsPerSample = wfxe.Format.wBitsPerSample; rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL); ok(rc==DS_OK && secondary!=NULL, "IDirectSound_CreateSoundBuffer() failed to create a secondary " "buffer %08x\n",rc); if (rc==DS_OK && secondary!=NULL) { if (winetest_interactive) { trace(" Testing a secondary buffer at %dx%dx%d " "with a primary buffer at %dx%dx%d\n", wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels, wfx1.nSamplesPerSec,wfx1.wBitsPerSample,wfx1.nChannels); } test_buffer8(dso,&secondary,0,FALSE,0,FALSE,0, winetest_interactive,1.0,0,NULL,0,0); ref=IDirectSoundBuffer_Release(secondary); ok(ref==0,"IDirectSoundBuffer_Release() has %d references, " "should have 0\n",ref); } } EXIT1: ref=IDirectSoundBuffer_Release(primary); ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, " "should have 0\n",ref); } /* Set the CooperativeLevel back to normal */ /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */ rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL); ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel() failed: %08x\n", rc); EXIT: ref=IDirectSound8_Release(dso); ok(ref==0,"IDirectSound8_Release() has %d references, should have 0\n",ref); if (ref!=0) return DSERR_GENERIC; return rc; }
static HRESULT WINAPI DSoundRender_InputPin_ReceiveConnection(IPin * iface, IPin * pReceivePin, const AM_MEDIA_TYPE * pmt) { InputPin *This = (InputPin *)iface; PIN_DIRECTION pindirReceive; DSoundRenderImpl *DSImpl; HRESULT hr = S_OK; TRACE("(%p)->(%p, %p)\n", This, pReceivePin, pmt); dump_AM_MEDIA_TYPE(pmt); EnterCriticalSection(This->pin.pCritSec); { DSImpl = (DSoundRenderImpl*)This->pin.pinInfo.pFilter; DSImpl->rtLastStop = -1; if (This->pin.pConnectedTo) hr = VFW_E_ALREADY_CONNECTED; if (SUCCEEDED(hr) && This->pin.fnQueryAccept(This->pin.pUserData, pmt) != S_OK) hr = VFW_E_TYPE_NOT_ACCEPTED; if (SUCCEEDED(hr)) { IPin_QueryDirection(pReceivePin, &pindirReceive); if (pindirReceive != PINDIR_OUTPUT) { ERR("Can't connect from non-output pin\n"); hr = VFW_E_INVALID_DIRECTION; } } if (SUCCEEDED(hr)) { WAVEFORMATEX *format; DSBUFFERDESC buf_desc; TRACE("MajorType %s\n", debugstr_guid(&pmt->majortype)); TRACE("SubType %s\n", debugstr_guid(&pmt->subtype)); TRACE("Format %s\n", debugstr_guid(&pmt->formattype)); TRACE("Size %d\n", pmt->cbFormat); format = (WAVEFORMATEX*)pmt->pbFormat; DSImpl->buf_size = format->nAvgBytesPerSec; memset(&buf_desc,0,sizeof(DSBUFFERDESC)); buf_desc.dwSize = sizeof(DSBUFFERDESC); buf_desc.dwFlags = DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLPAN | DSBCAPS_CTRLFREQUENCY | DSBCAPS_GETCURRENTPOSITION2; buf_desc.dwBufferBytes = DSImpl->buf_size; buf_desc.lpwfxFormat = format; hr = IDirectSound_CreateSoundBuffer(DSImpl->dsound, &buf_desc, &DSImpl->dsbuffer, NULL); if (FAILED(hr)) ERR("Can't create sound buffer (%x)\n", hr); } if (SUCCEEDED(hr)) { hr = IDirectSoundBuffer_SetVolume(DSImpl->dsbuffer, DSImpl->volume); if (FAILED(hr)) ERR("Can't set volume to %ld (%x)\n", DSImpl->volume, hr); hr = IDirectSoundBuffer_SetPan(DSImpl->dsbuffer, DSImpl->pan); if (FAILED(hr)) ERR("Can't set pan to %ld (%x)\n", DSImpl->pan, hr); DSImpl->write_pos = 0; hr = S_OK; } if (SUCCEEDED(hr)) { CopyMediaType(&This->pin.mtCurrent, pmt); This->pin.pConnectedTo = pReceivePin; IPin_AddRef(pReceivePin); } else if (hr != VFW_E_ALREADY_CONNECTED) { if (DSImpl->dsbuffer) IDirectSoundBuffer_Release(DSImpl->dsbuffer); DSImpl->dsbuffer = NULL; } } LeaveCriticalSection(This->pin.pCritSec); return hr; }
static ALCboolean DSoundResetPlayback(ALCdevice *device) { DSoundPlaybackData *data = (DSoundPlaybackData*)device->ExtraData; DSBUFFERDESC DSBDescription; WAVEFORMATEXTENSIBLE OutputType; DWORD speakers; HRESULT hr; memset(&OutputType, 0, sizeof(OutputType)); if(data->DSnotify) IDirectSoundNotify_Release(data->DSnotify); data->DSnotify = NULL; if(data->DSsbuffer) IDirectSoundBuffer_Release(data->DSsbuffer); data->DSsbuffer = NULL; if(data->DSpbuffer != NULL) IDirectSoundBuffer_Release(data->DSpbuffer); data->DSpbuffer = NULL; switch(device->FmtType) { case DevFmtByte: device->FmtType = DevFmtUByte; break; case DevFmtFloat: if((device->Flags&DEVICE_SAMPLE_TYPE_REQUEST)) break; /* fall-through */ case DevFmtUShort: device->FmtType = DevFmtShort; break; case DevFmtUInt: device->FmtType = DevFmtInt; break; case DevFmtUByte: case DevFmtShort: case DevFmtInt: break; } hr = IDirectSound_GetSpeakerConfig(data->DS, &speakers); if(SUCCEEDED(hr)) { if(!(device->Flags&DEVICE_CHANNELS_REQUEST)) { speakers = DSSPEAKER_CONFIG(speakers); if(speakers == DSSPEAKER_MONO) device->FmtChans = DevFmtMono; else if(speakers == DSSPEAKER_STEREO || speakers == DSSPEAKER_HEADPHONE) device->FmtChans = DevFmtStereo; else if(speakers == DSSPEAKER_QUAD) device->FmtChans = DevFmtQuad; else if(speakers == DSSPEAKER_5POINT1) device->FmtChans = DevFmtX51; else if(speakers == DSSPEAKER_7POINT1) device->FmtChans = DevFmtX71; else ERR("Unknown system speaker config: 0x%lx\n", speakers); } switch(device->FmtChans) { case DevFmtMono: OutputType.dwChannelMask = SPEAKER_FRONT_CENTER; break; case DevFmtStereo: OutputType.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT; break; case DevFmtQuad: OutputType.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT; break; case DevFmtX51: OutputType.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT; break; case DevFmtX51Side: OutputType.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_SIDE_LEFT | SPEAKER_SIDE_RIGHT; break; case DevFmtX61: OutputType.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_CENTER | SPEAKER_SIDE_LEFT | SPEAKER_SIDE_RIGHT; break; case DevFmtX71: OutputType.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT | SPEAKER_SIDE_LEFT | SPEAKER_SIDE_RIGHT; break; } retry_open: hr = S_OK; OutputType.Format.wFormatTag = WAVE_FORMAT_PCM; OutputType.Format.nChannels = ChannelsFromDevFmt(device->FmtChans); OutputType.Format.wBitsPerSample = BytesFromDevFmt(device->FmtType) * 8; OutputType.Format.nBlockAlign = OutputType.Format.nChannels*OutputType.Format.wBitsPerSample/8; OutputType.Format.nSamplesPerSec = device->Frequency; OutputType.Format.nAvgBytesPerSec = OutputType.Format.nSamplesPerSec*OutputType.Format.nBlockAlign; OutputType.Format.cbSize = 0; } if(OutputType.Format.nChannels > 2 || device->FmtType == DevFmtFloat) { OutputType.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; OutputType.Samples.wValidBitsPerSample = OutputType.Format.wBitsPerSample; OutputType.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX); if(device->FmtType == DevFmtFloat) OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT; else OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; if(data->DSpbuffer) IDirectSoundBuffer_Release(data->DSpbuffer); data->DSpbuffer = NULL; } else { if(SUCCEEDED(hr)) { memset(&DSBDescription,0,sizeof(DSBUFFERDESC)); DSBDescription.dwSize=sizeof(DSBUFFERDESC); DSBDescription.dwFlags=DSBCAPS_PRIMARYBUFFER; hr = IDirectSound_CreateSoundBuffer(data->DS, &DSBDescription, &data->DSpbuffer, NULL); } if(SUCCEEDED(hr)) hr = IDirectSoundBuffer_SetFormat(data->DSpbuffer,&OutputType.Format); } if(SUCCEEDED(hr)) { if(device->NumUpdates > MAX_UPDATES) { device->UpdateSize = (device->UpdateSize*device->NumUpdates + MAX_UPDATES-1) / MAX_UPDATES; device->NumUpdates = MAX_UPDATES; } memset(&DSBDescription,0,sizeof(DSBUFFERDESC)); DSBDescription.dwSize=sizeof(DSBUFFERDESC); DSBDescription.dwFlags=DSBCAPS_CTRLPOSITIONNOTIFY|DSBCAPS_GETCURRENTPOSITION2|DSBCAPS_GLOBALFOCUS; DSBDescription.dwBufferBytes=device->UpdateSize * device->NumUpdates * OutputType.Format.nBlockAlign; DSBDescription.lpwfxFormat=&OutputType.Format; hr = IDirectSound_CreateSoundBuffer(data->DS, &DSBDescription, &data->DSsbuffer, NULL); if(FAILED(hr) && device->FmtType == DevFmtFloat) { device->FmtType = DevFmtShort; goto retry_open; } } if(SUCCEEDED(hr)) { hr = IDirectSoundBuffer_QueryInterface(data->DSsbuffer, &IID_IDirectSoundNotify, (LPVOID *)&data->DSnotify); if(SUCCEEDED(hr)) { DSBPOSITIONNOTIFY notifies[MAX_UPDATES]; ALuint i; for(i = 0;i < device->NumUpdates;++i) { notifies[i].dwOffset = i * device->UpdateSize * OutputType.Format.nBlockAlign; notifies[i].hEventNotify = data->NotifyEvent; } if(IDirectSoundNotify_SetNotificationPositions(data->DSnotify, device->NumUpdates, notifies) != DS_OK) hr = E_FAIL; } } if(FAILED(hr)) { if(data->DSnotify != NULL) IDirectSoundNotify_Release(data->DSnotify); data->DSnotify = NULL; if(data->DSsbuffer != NULL) IDirectSoundBuffer_Release(data->DSsbuffer); data->DSsbuffer = NULL; if(data->DSpbuffer != NULL) IDirectSoundBuffer_Release(data->DSpbuffer); data->DSpbuffer = NULL; return ALC_FALSE; } ResetEvent(data->NotifyEvent); SetDefaultWFXChannelOrder(device); return ALC_TRUE; }
static ALCboolean DSoundOpenPlayback(ALCdevice *device, const ALCchar *deviceName) { DSBUFFERDESC DSBDescription; DSoundData *pData = NULL; WAVEFORMATEXTENSIBLE OutputType; DWORD frameSize = 0; LPGUID guid = NULL; DWORD speakers; HRESULT hr; if(deviceName) { int i; for(i = 0;DeviceList[i].name;i++) { if(strcmp(deviceName, DeviceList[i].name) == 0) { device->szDeviceName = DeviceList[i].name; if(i > 0) guid = &DeviceList[i].guid; break; } } if(!DeviceList[i].name) return ALC_FALSE; } else device->szDeviceName = DeviceList[0].name; memset(&OutputType, 0, sizeof(OutputType)); //Initialise requested device pData = calloc(1, sizeof(DSoundData)); if(!pData) { SetALCError(ALC_OUT_OF_MEMORY); return ALC_FALSE; } //DirectSound Init code hr = DirectSoundCreate(guid, &pData->lpDS, NULL); if(SUCCEEDED(hr)) hr = IDirectSound_SetCooperativeLevel(pData->lpDS, GetForegroundWindow(), DSSCL_PRIORITY); if(SUCCEEDED(hr)) hr = IDirectSound_GetSpeakerConfig(pData->lpDS, &speakers); if(SUCCEEDED(hr)) { speakers = DSSPEAKER_CONFIG(speakers); if(speakers == DSSPEAKER_MONO) { if(aluBytesFromFormat(device->Format) == 1) device->Format = AL_FORMAT_MONO8; else device->Format = AL_FORMAT_MONO16; } else if(speakers == DSSPEAKER_STEREO) { if(aluBytesFromFormat(device->Format) == 1) device->Format = AL_FORMAT_STEREO8; else device->Format = AL_FORMAT_STEREO16; } else if(speakers == DSSPEAKER_QUAD) { if(aluBytesFromFormat(device->Format) == 1) device->Format = AL_FORMAT_QUAD8; else device->Format = AL_FORMAT_QUAD16; OutputType.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT; } else if(speakers == DSSPEAKER_5POINT1) { if(aluBytesFromFormat(device->Format) == 1) device->Format = AL_FORMAT_51CHN8; else device->Format = AL_FORMAT_51CHN16; OutputType.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT; } else if(speakers == DSSPEAKER_7POINT1) { if(aluBytesFromFormat(device->Format) == 1) device->Format = AL_FORMAT_71CHN8; else device->Format = AL_FORMAT_71CHN16; OutputType.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT | SPEAKER_SIDE_LEFT | SPEAKER_SIDE_RIGHT; } frameSize = aluBytesFromFormat(device->Format) * aluChannelsFromFormat(device->Format); OutputType.Format.wFormatTag = WAVE_FORMAT_PCM; OutputType.Format.nChannels = aluChannelsFromFormat(device->Format); OutputType.Format.wBitsPerSample = aluBytesFromFormat(device->Format) * 8; OutputType.Format.nBlockAlign = OutputType.Format.nChannels*OutputType.Format.wBitsPerSample/8; OutputType.Format.nSamplesPerSec = device->Frequency; OutputType.Format.nAvgBytesPerSec = OutputType.Format.nSamplesPerSec*OutputType.Format.nBlockAlign; OutputType.Format.cbSize = 0; device->UpdateSize /= DS_FRAGS; } if(OutputType.Format.nChannels > 2) { OutputType.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; OutputType.Samples.wValidBitsPerSample = OutputType.Format.wBitsPerSample; OutputType.Format.cbSize = 22; OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; } else { if(SUCCEEDED(hr)) { memset(&DSBDescription,0,sizeof(DSBUFFERDESC)); DSBDescription.dwSize=sizeof(DSBUFFERDESC); DSBDescription.dwFlags=DSBCAPS_PRIMARYBUFFER; hr = IDirectSound_CreateSoundBuffer(pData->lpDS, &DSBDescription, &pData->DSpbuffer, NULL); } if(SUCCEEDED(hr)) hr = IDirectSoundBuffer_SetFormat(pData->DSpbuffer,&OutputType.Format); } if(SUCCEEDED(hr)) { memset(&DSBDescription,0,sizeof(DSBUFFERDESC)); DSBDescription.dwSize=sizeof(DSBUFFERDESC); DSBDescription.dwFlags=DSBCAPS_GLOBALFOCUS|DSBCAPS_GETCURRENTPOSITION2; DSBDescription.dwBufferBytes=device->UpdateSize * DS_FRAGS * frameSize; DSBDescription.lpwfxFormat=&OutputType.Format; hr = IDirectSound_CreateSoundBuffer(pData->lpDS, &DSBDescription, &pData->DSsbuffer, NULL); } if(SUCCEEDED(hr)) hr = IDirectSoundBuffer_Play(pData->DSsbuffer, 0, 0, DSBPLAY_LOOPING); device->ExtraData = pData; pData->thread = StartThread(DSoundProc, device); if(!pData->thread) hr = E_FAIL; if(FAILED(hr)) { if (pData->DSsbuffer) IDirectSoundBuffer_Release(pData->DSsbuffer); if (pData->DSpbuffer) IDirectSoundBuffer_Release(pData->DSpbuffer); if (pData->lpDS) IDirectSound_Release(pData->lpDS); free(pData); return ALC_FALSE; } return ALC_TRUE; }