Yeah, that fixes the problem. This patch looks good to me now.
Andrew
On Fri, Nov 16, 2012 at 08:35:51PM +0100, Maarten Lankhorst wrote:
> I promised I would never touch it, but then I wanted to play skyrim
>
> V2: Limit channels to 2 in primary if not in writeprimary mode
> V3: Split off DSOUND_WaveFormat to its own function sooner.
> V4: Fix accidental revert of device->buflen increase. It was supposed to wait until rework in patch 3.
> ---
> diff --git a/dlls/dsound/dsound.c b/dlls/dsound/dsound.c
> index e5b0e3c..ac85ba2 100644
> --- a/dlls/dsound/dsound.c
> +++ b/dlls/dsound/dsound.c
> @@ -305,21 +305,36 @@ static HRESULT WINAPI IDirectSound8Impl_SetCooperativeLevel(IDirectSound8 *iface
> DWORD level)
> {
> IDirectSoundImpl *This = impl_from_IDirectSound8(iface);
> + DirectSoundDevice *device = This->device;
> + DWORD oldlevel;
> + HRESULT hr = S_OK;
>
> TRACE("(%p,%p,%s)\n", This, hwnd, dumpCooperativeLevel(level));
>
> - if (!This->device) {
> + if (!device) {
> WARN("not initialized\n");
> return DSERR_UNINITIALIZED;
> }
>
> if (level == DSSCL_PRIORITY || level == DSSCL_EXCLUSIVE) {
> WARN("level=%s not fully supported\n",
> - level == DSSCL_PRIORITY ? "DSSCL_PRIORITY" : "DSSCL_EXCLUSIVE");
> + level==DSSCL_PRIORITY ? "DSSCL_PRIORITY" : "DSSCL_EXCLUSIVE");
> }
>
> - This->device->priolevel = level;
> - return DS_OK;
> + RtlAcquireResourceExclusive(&device->buffer_list_lock, TRUE);
> + EnterCriticalSection(&device->mixlock);
> + oldlevel = device->priolevel;
> + device->priolevel = level;
> + if ((level == DSSCL_WRITEPRIMARY) != (oldlevel == DSSCL_WRITEPRIMARY)) {
> + hr = DSOUND_ReopenDevice(device, level == DSSCL_WRITEPRIMARY);
> + if (FAILED(hr))
> + device->priolevel = oldlevel;
> + else
> + DSOUND_PrimaryOpen(device);
> + }
> + LeaveCriticalSection(&device->mixlock);
> + RtlReleaseResource(&device->buffer_list_lock);
> + return hr;
> }
>
> static HRESULT WINAPI IDirectSound8Impl_Compact(IDirectSound8 *iface)
> @@ -612,20 +627,24 @@ static HRESULT DirectSoundDevice_Create(DirectSoundDevice ** ppDevice)
> device->guid = GUID_NULL;
>
> /* Set default wave format (may need it for waveOutOpen) */
> - device->pwfx = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(WAVEFORMATEX));
> - if (device->pwfx == NULL) {
> + device->pwfx = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(WAVEFORMATEXTENSIBLE));
> + device->primary_pwfx = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(WAVEFORMATEXTENSIBLE));
> + if (!device->pwfx || !device->primary_pwfx) {
> WARN("out of memory\n");
> + HeapFree(GetProcessHeap(),0,device->primary_pwfx);
> + HeapFree(GetProcessHeap(),0,device->pwfx);
> HeapFree(GetProcessHeap(),0,device);
> return DSERR_OUTOFMEMORY;
> }
>
> device->pwfx->wFormatTag = WAVE_FORMAT_PCM;
> - device->pwfx->nSamplesPerSec = ds_default_sample_rate;
> - device->pwfx->wBitsPerSample = ds_default_bits_per_sample;
> + device->pwfx->nSamplesPerSec = 22050;
> + device->pwfx->wBitsPerSample = 8;
> device->pwfx->nChannels = 2;
> device->pwfx->nBlockAlign = device->pwfx->wBitsPerSample * device->pwfx->nChannels / 8;
> device->pwfx->nAvgBytesPerSec = device->pwfx->nSamplesPerSec * device->pwfx->nBlockAlign;
> device->pwfx->cbSize = 0;
> + memcpy(device->primary_pwfx, device->pwfx, sizeof(*device->pwfx));
>
> InitializeCriticalSection(&(device->mixlock));
> device->mixlock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": DirectSoundDevice.mixlock");
> diff --git a/dlls/dsound/dsound_main.c b/dlls/dsound/dsound_main.c
> index 3fded64..3c47423 100644
> --- a/dlls/dsound/dsound_main.c
> +++ b/dlls/dsound/dsound_main.c
> @@ -93,8 +93,6 @@ WCHAR wine_vxd_drv[] = { 'w','i','n','e','m','m','.','v','x','d', 0 };
> /* All default settings, you most likely don't want to touch these, see wiki on UsefulRegistryKeys */
> int ds_hel_buflen = 32768 * 2;
> int ds_snd_queue_max = 10;
> -int ds_default_sample_rate = 44100;
> -int ds_default_bits_per_sample = 16;
> static HINSTANCE instance;
>
> /*
> @@ -151,19 +149,11 @@ void setup_dsound_options(void)
> ds_snd_queue_max = atoi(buffer);
>
>
> - if (!get_config_key( hkey, appkey, "DefaultSampleRate", buffer, MAX_PATH ))
> - ds_default_sample_rate = atoi(buffer);
> -
> - if (!get_config_key( hkey, appkey, "DefaultBitsPerSample", buffer, MAX_PATH ))
> - ds_default_bits_per_sample = atoi(buffer);
> -
> if (appkey) RegCloseKey( appkey );
> if (hkey) RegCloseKey( hkey );
>
> TRACE("ds_hel_buflen = %d\n", ds_hel_buflen);
> TRACE("ds_snd_queue_max = %d\n", ds_snd_queue_max);
> - TRACE("ds_default_sample_rate = %d\n", ds_default_sample_rate);
> - TRACE("ds_default_bits_per_sample = %d\n", ds_default_bits_per_sample);
> }
>
> static const char * get_device_id(LPCGUID pGuid)
> diff --git a/dlls/dsound/dsound_private.h b/dlls/dsound/dsound_private.h
> index 247f229..62656a5 100644
> --- a/dlls/dsound/dsound_private.h
> +++ b/dlls/dsound/dsound_private.h
> @@ -32,9 +32,6 @@
>
> extern int ds_hel_buflen DECLSPEC_HIDDEN;
> extern int ds_snd_queue_max DECLSPEC_HIDDEN;
> -extern int ds_snd_shadow_maxsize DECLSPEC_HIDDEN;
> -extern int ds_default_sample_rate DECLSPEC_HIDDEN;
> -extern int ds_default_bits_per_sample DECLSPEC_HIDDEN;
>
> /*****************************************************************************
> * Predeclare the interface implementation structures
> @@ -72,8 +69,8 @@ struct DirectSoundDevice
> GUID guid;
> DSCAPS drvcaps;
> DWORD priolevel;
> - PWAVEFORMATEX pwfx;
> - UINT timerID, playing_offs_bytes, in_mmdev_bytes, prebuf, helfrags;
> + PWAVEFORMATEX pwfx, primary_pwfx;
> + UINT timerID, playing_offs_bytes, in_mmdev_bytes, prebuf;
> DWORD fraglen;
> LPBYTE buffer;
> DWORD writelead, buflen, state, playpos, mixpos;
> @@ -211,6 +208,7 @@ HRESULT DSOUND_PrimaryStop(DirectSoundDevice *device) DECLSPEC_HIDDEN;
> HRESULT DSOUND_PrimaryGetPosition(DirectSoundDevice *device, LPDWORD playpos, LPDWORD writepos) DECLSPEC_HIDDEN;
> LPWAVEFORMATEX DSOUND_CopyFormat(LPCWAVEFORMATEX wfex) DECLSPEC_HIDDEN;
> HRESULT DSOUND_ReopenDevice(DirectSoundDevice *device, BOOL forcewave) DECLSPEC_HIDDEN;
> +HRESULT DSOUND_PrimaryOpen(DirectSoundDevice *device) DECLSPEC_HIDDEN;
> HRESULT primarybuffer_create(DirectSoundDevice *device, IDirectSoundBufferImpl **ppdsb,
> const DSBUFFERDESC *dsbd) DECLSPEC_HIDDEN;
> void primarybuffer_destroy(IDirectSoundBufferImpl *This) DECLSPEC_HIDDEN;
> diff --git a/dlls/dsound/mixer.c b/dlls/dsound/mixer.c
> index 264d64d..84e029b 100644
> --- a/dlls/dsound/mixer.c
> +++ b/dlls/dsound/mixer.c
> @@ -112,6 +112,7 @@ void DSOUND_RecalcFormat(IDirectSoundBufferImpl *dsb)
> TRACE("(%p)\n",dsb);
>
> pwfxe = (WAVEFORMATEXTENSIBLE *) dsb->pwfx;
> + dsb->freqAdjust = (float)dsb->freq / dsb->device->pwfx->nSamplesPerSec;
>
> if ((pwfxe->Format.wFormatTag == WAVE_FORMAT_IEEE_FLOAT) || ((pwfxe->Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE)
> && (IsEqualGUID(&pwfxe->SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT))))
> diff --git a/dlls/dsound/primary.c b/dlls/dsound/primary.c
> index 8da12e2..bf76dec 100644
> --- a/dlls/dsound/primary.c
> +++ b/dlls/dsound/primary.c
> @@ -58,10 +58,99 @@ static DWORD DSOUND_fraglen(DirectSoundDevice *device)
> return ret;
> }
>
> +static HRESULT DSOUND_WaveFormat(DirectSoundDevice *device, IAudioClient *client,
> + BOOL forcewave, WAVEFORMATEX **wfx)
> +{
> + WAVEFORMATEXTENSIBLE *retwfe = NULL;
> + WAVEFORMATEX *w;
> + HRESULT hr;
> +
> + if (!forcewave) {
> + WAVEFORMATEXTENSIBLE *mixwfe;
> + hr = IAudioClient_GetMixFormat(client, (WAVEFORMATEX**)&mixwfe);
> +
> + if (FAILED(hr))
> + return hr;
> +
> + if (mixwfe->Format.nChannels > 2) {
> + static int once;
> + if (!once++)
> + FIXME("Limiting channels to 2 due to lack of multichannel support\n");
> +
> + mixwfe->Format.nChannels = 2;
> + mixwfe->Format.nBlockAlign = mixwfe->Format.nChannels * mixwfe->Format.wBitsPerSample / 8;
> + mixwfe->Format.nAvgBytesPerSec = mixwfe->Format.nSamplesPerSec * mixwfe->Format.nBlockAlign;
> + }
> +
> + if (!IsEqualGUID(&mixwfe->SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)) {
> + WAVEFORMATEXTENSIBLE testwfe = *mixwfe;
> +
> + testwfe.SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
> + testwfe.Format.wBitsPerSample = 32;
> + testwfe.Format.nBlockAlign = testwfe.Format.nChannels * testwfe.Format.wBitsPerSample / 8;
> + testwfe.Format.nAvgBytesPerSec = testwfe.Format.nSamplesPerSec * testwfe.Format.nBlockAlign;
> + testwfe.Samples.wValidBitsPerSample = 0;
> +
> + if (FAILED(IAudioClient_IsFormatSupported(client, AUDCLNT_SHAREMODE_SHARED, &testwfe.Format, (WAVEFORMATEX**)&retwfe)))
> + w = DSOUND_CopyFormat(&mixwfe->Format);
> + else if (retwfe)
> + w = DSOUND_CopyFormat(&retwfe->Format);
> + else
> + w = DSOUND_CopyFormat(&testwfe.Format);
> + CoTaskMemFree(retwfe);
> + retwfe = NULL;
> + } else
> + w = DSOUND_CopyFormat(&mixwfe->Format);
> + CoTaskMemFree(mixwfe);
> + } else if (device->primary_pwfx->wFormatTag == WAVE_FORMAT_PCM ||
> + device->primary_pwfx->wFormatTag == WAVE_FORMAT_IEEE_FLOAT) {
> + WAVEFORMATEX *wi = device->primary_pwfx;
> + WAVEFORMATEXTENSIBLE *wfe;
> +
> + /* Convert to WAVEFORMATEXTENSIBLE */
> + w = HeapAlloc(GetProcessHeap(), 0, sizeof(WAVEFORMATEXTENSIBLE));
> + wfe = (WAVEFORMATEXTENSIBLE*)w;
> + if (!wfe)
> + return DSERR_OUTOFMEMORY;
> +
> + wfe->Format = *wi;
> + w->wFormatTag = WAVE_FORMAT_EXTENSIBLE;
> + w->cbSize = sizeof(*wfe) - sizeof(*w);
> + w->nBlockAlign = w->nChannels * w->wBitsPerSample / 8;
> + w->nAvgBytesPerSec = w->nSamplesPerSec * w->nBlockAlign;
> +
> + wfe->dwChannelMask = 0;
> + wfe->Samples.wValidBitsPerSample = 0;
> + if (wi->wFormatTag == WAVE_FORMAT_IEEE_FLOAT) {
> + w->wBitsPerSample = 32;
> + wfe->SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
> + } else
> + wfe->SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
> + } else
> + w = DSOUND_CopyFormat(device->primary_pwfx);
> +
> + if (!w)
> + return DSERR_OUTOFMEMORY;
> +
> + hr = IAudioClient_IsFormatSupported(client, AUDCLNT_SHAREMODE_SHARED, w, (WAVEFORMATEX**)&retwfe);
> + if (retwfe) {
> + memcpy(w, retwfe, sizeof(WAVEFORMATEX) + retwfe->Format.cbSize);
> + CoTaskMemFree(retwfe);
> + }
> + if (FAILED(hr)) {
> + WARN("IsFormatSupported failed: %08x\n", hr);
> + HeapFree(GetProcessHeap(), 0, w);
> + return hr;
> + }
> + *wfx = w;
> + return S_OK;
> +}
> +
> HRESULT DSOUND_ReopenDevice(DirectSoundDevice *device, BOOL forcewave)
> {
> UINT prebuf_frames;
> REFERENCE_TIME prebuf_rt;
> + WAVEFORMATEX *wfx = NULL;
> HRESULT hres;
>
> TRACE("(%p, %d)\n", device, forcewave);
> @@ -85,11 +174,20 @@ HRESULT DSOUND_ReopenDevice(DirectSoundDevice *device, BOOL forcewave)
>
> hres = IMMDevice_Activate(device->mmdevice, &IID_IAudioClient,
> CLSCTX_INPROC_SERVER, NULL, (void **)&device->client);
> - if(FAILED(hres)){
> + if(FAILED(hres)) {
> WARN("Activate failed: %08x\n", hres);
> return hres;
> }
>
> + hres = DSOUND_WaveFormat(device, device->client, forcewave, &wfx);
> + if (FAILED(hres)) {
> + IAudioClient_Release(device->client);
> + device->client = NULL;
> + return hres;
> + }
> + HeapFree(GetProcessHeap(), 0, device->pwfx);
> + device->pwfx = wfx;
> +
> prebuf_frames = device->prebuf * DSOUND_fraglen(device) / device->pwfx->nBlockAlign;
> prebuf_rt = (10000000 * (UINT64)prebuf_frames) / device->pwfx->nSamplesPerSec;
>
> @@ -139,9 +237,11 @@ HRESULT DSOUND_ReopenDevice(DirectSoundDevice *device, BOOL forcewave)
> return S_OK;
> }
>
> -static HRESULT DSOUND_PrimaryOpen(DirectSoundDevice *device)
> +HRESULT DSOUND_PrimaryOpen(DirectSoundDevice *device)
> {
> + IDirectSoundBufferImpl** dsb = device->buffers;
> LPBYTE newbuf;
> + DWORD i;
>
> TRACE("(%p)\n", device);
>
> @@ -157,9 +257,8 @@ static HRESULT DSOUND_PrimaryOpen(DirectSoundDevice *device)
> device->buflen -= device->buflen % device->pwfx->nBlockAlign;
> }
>
> - device->helfrags = device->buflen / device->fraglen;
> -
> - device->mix_buffer_len = ((device->prebuf * device->fraglen) / (device->pwfx->wBitsPerSample / 8)) * sizeof(float);
> + HeapFree(GetProcessHeap(), 0, device->mix_buffer);
> + device->mix_buffer_len = (device->buflen / (device->pwfx->wBitsPerSample / 8)) * sizeof(float);
> device->mix_buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, device->mix_buffer_len);
> if (!device->mix_buffer)
> return DSERR_OUTOFMEMORY;
> @@ -183,8 +282,8 @@ static HRESULT DSOUND_PrimaryOpen(DirectSoundDevice *device)
>
> device->buffer = newbuf;
>
> - TRACE("buflen: %u, fraglen: %u, helfrags: %u, mix_buffer_len: %u\n",
> - device->buflen, device->fraglen, device->helfrags, device->mix_buffer_len);
> + TRACE("buflen: %u, fraglen: %u, mix_buffer_len: %u\n",
> + device->buflen, device->fraglen, device->mix_buffer_len);
>
> if(device->pwfx->wFormatTag == WAVE_FORMAT_IEEE_FLOAT ||
> (device->pwfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
> @@ -196,8 +295,22 @@ static HRESULT DSOUND_PrimaryOpen(DirectSoundDevice *device)
>
> FillMemory(device->buffer, device->buflen, (device->pwfx->wBitsPerSample == 8) ? 128 : 0);
> FillMemory(device->mix_buffer, device->mix_buffer_len, 0);
> - device->playing_offs_bytes = device->in_mmdev_bytes = device->playpos = device->mixpos = 0;
> - return DS_OK;
> + device->playpos = 0;
> +
> + if (device->pwfx->wFormatTag == WAVE_FORMAT_IEEE_FLOAT ||
> + (device->pwfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
> + IsEqualGUID(&((WAVEFORMATEXTENSIBLE*)device->pwfx)->SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)))
> + device->normfunction = normfunctions[4];
> + else
> + device->normfunction = normfunctions[device->pwfx->wBitsPerSample/8 - 1];
> +
> + for (i = 0; i < device->nrofbuffers; i++) {
> + RtlAcquireResourceExclusive(&dsb[i]->lock, TRUE);
> + DSOUND_RecalcFormat(dsb[i]);
> + RtlReleaseResource(&dsb[i]->lock);
> + }
> +
> + return DS_OK;
> }
>
>
> @@ -249,6 +362,7 @@ HRESULT DSOUND_PrimaryDestroy(DirectSoundDevice *device)
> HeapFree(GetProcessHeap(), 0, device->primary);
> device->primary = NULL;
>
> + HeapFree(GetProcessHeap(),0,device->primary_pwfx);
> HeapFree(GetProcessHeap(),0,device->pwfx);
> device->pwfx=NULL;
>
> @@ -338,8 +452,7 @@ LPWAVEFORMATEX DSOUND_CopyFormat(LPCWAVEFORMATEX wfex)
>
> HRESULT primarybuffer_SetFormat(DirectSoundDevice *device, LPCWAVEFORMATEX passed_fmt)
> {
> - HRESULT err = DSERR_BUFFERLOST;
> - int i;
> + HRESULT err = S_OK;
> WAVEFORMATEX *old_fmt;
> WAVEFORMATEXTENSIBLE *fmtex, *passed_fmtex = (WAVEFORMATEXTENSIBLE*)passed_fmt;
> BOOL forced = (device->priolevel == DSSCL_WRITEPRIMARY);
> @@ -377,169 +490,68 @@ HRESULT primarybuffer_SetFormat(DirectSoundDevice *device, LPCWAVEFORMATEX passe
> RtlAcquireResourceExclusive(&(device->buffer_list_lock), TRUE);
> EnterCriticalSection(&(device->mixlock));
>
> - old_fmt = device->pwfx;
> - device->pwfx = DSOUND_CopyFormat(passed_fmt);
> - fmtex = (WAVEFORMATEXTENSIBLE *)device->pwfx;
> - if (device->pwfx == NULL) {
> - device->pwfx = old_fmt;
> - old_fmt = NULL;
> - err = DSERR_OUTOFMEMORY;
> - goto done;
> - }
> + if (device->priolevel == DSSCL_WRITEPRIMARY) {
> + old_fmt = device->primary_pwfx;
> + device->primary_pwfx = DSOUND_CopyFormat(passed_fmt);
> + fmtex = (WAVEFORMATEXTENSIBLE *)device->primary_pwfx;
> + if (device->primary_pwfx == NULL) {
> + err = DSERR_OUTOFMEMORY;
> + goto out;
> + }
>
> - if(device->pwfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE){
> - if(fmtex->Samples.wValidBitsPerSample == 0){
> + if (fmtex->Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
> + fmtex->Samples.wValidBitsPerSample == 0) {
> TRACE("Correcting 0 valid bits per sample\n");
> fmtex->Samples.wValidBitsPerSample = fmtex->Format.wBitsPerSample;
> }
> - }
> -
> - DSOUND_PrimaryClose(device);
> -
> - err = DSOUND_ReopenDevice(device, FALSE);
> - if(SUCCEEDED(err))
> - goto opened;
> -
> - /* requested format failed, so try others */
> - if(device->pwfx->wFormatTag == WAVE_FORMAT_IEEE_FLOAT){
> - device->pwfx->wFormatTag = WAVE_FORMAT_PCM;
> - device->pwfx->wBitsPerSample = 32;
> - device->pwfx->nAvgBytesPerSec = passed_fmt->nSamplesPerSec * device->pwfx->nBlockAlign;
> - device->pwfx->nBlockAlign = passed_fmt->nChannels * (device->pwfx->wBitsPerSample / 8);
> -
> - err = DSOUND_ReopenDevice(device, FALSE);
> - if(SUCCEEDED(err))
> - goto opened;
> - }
> -
> - if(device->pwfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
> - IsEqualGUID(&fmtex->SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)){
> - fmtex->SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
> - device->pwfx->wBitsPerSample = 32;
> - device->pwfx->nAvgBytesPerSec = passed_fmt->nSamplesPerSec * device->pwfx->nBlockAlign;
> - device->pwfx->nBlockAlign = passed_fmt->nChannels * (device->pwfx->wBitsPerSample / 8);
> -
> - err = DSOUND_ReopenDevice(device, FALSE);
> - if(SUCCEEDED(err))
> - goto opened;
> - }
>
> - device->pwfx->wBitsPerSample = 32;
> - device->pwfx->nAvgBytesPerSec = passed_fmt->nSamplesPerSec * device->pwfx->nBlockAlign;
> - device->pwfx->nBlockAlign = passed_fmt->nChannels * (device->pwfx->wBitsPerSample / 8);
> - if(device->pwfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE)
> - fmtex->Samples.wValidBitsPerSample = device->pwfx->wBitsPerSample;
> - err = DSOUND_ReopenDevice(device, FALSE);
> - if(SUCCEEDED(err))
> - goto opened;
> -
> - device->pwfx->wBitsPerSample = 16;
> - device->pwfx->nAvgBytesPerSec = passed_fmt->nSamplesPerSec * device->pwfx->nBlockAlign;
> - device->pwfx->nBlockAlign = passed_fmt->nChannels * (device->pwfx->wBitsPerSample / 8);
> - if(device->pwfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE)
> - fmtex->Samples.wValidBitsPerSample = device->pwfx->wBitsPerSample;
> - err = DSOUND_ReopenDevice(device, FALSE);
> - if(SUCCEEDED(err))
> - goto opened;
> -
> - device->pwfx->wBitsPerSample = 8;
> - device->pwfx->nAvgBytesPerSec = passed_fmt->nSamplesPerSec * device->pwfx->nBlockAlign;
> - device->pwfx->nBlockAlign = passed_fmt->nChannels * (device->pwfx->wBitsPerSample / 8);
> - if(device->pwfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE)
> - fmtex->Samples.wValidBitsPerSample = device->pwfx->wBitsPerSample;
> - err = DSOUND_ReopenDevice(device, FALSE);
> - if(SUCCEEDED(err))
> - goto opened;
> -
> - device->pwfx->nChannels = (passed_fmt->nChannels == 2) ? 1 : 2;
> - device->pwfx->wBitsPerSample = passed_fmt->wBitsPerSample;
> - device->pwfx->nAvgBytesPerSec = passed_fmt->nSamplesPerSec * device->pwfx->nBlockAlign;
> - device->pwfx->nBlockAlign = passed_fmt->nChannels * (device->pwfx->wBitsPerSample / 8);
> - if(device->pwfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE)
> - fmtex->Samples.wValidBitsPerSample = device->pwfx->wBitsPerSample;
> - err = DSOUND_ReopenDevice(device, FALSE);
> - if(SUCCEEDED(err))
> - goto opened;
> -
> - device->pwfx->wBitsPerSample = 32;
> - device->pwfx->nAvgBytesPerSec = passed_fmt->nSamplesPerSec * device->pwfx->nBlockAlign;
> - device->pwfx->nBlockAlign = passed_fmt->nChannels * (device->pwfx->wBitsPerSample / 8);
> - if(device->pwfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE)
> - fmtex->Samples.wValidBitsPerSample = device->pwfx->wBitsPerSample;
> - err = DSOUND_ReopenDevice(device, FALSE);
> - if(SUCCEEDED(err))
> - goto opened;
> -
> - device->pwfx->wBitsPerSample = 16;
> - device->pwfx->nAvgBytesPerSec = passed_fmt->nSamplesPerSec * device->pwfx->nBlockAlign;
> - device->pwfx->nBlockAlign = passed_fmt->nChannels * (device->pwfx->wBitsPerSample / 8);
> - if(device->pwfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE)
> - fmtex->Samples.wValidBitsPerSample = device->pwfx->wBitsPerSample;
> - err = DSOUND_ReopenDevice(device, FALSE);
> - if(SUCCEEDED(err))
> - goto opened;
> -
> - device->pwfx->wBitsPerSample = 8;
> - device->pwfx->nAvgBytesPerSec = passed_fmt->nSamplesPerSec * device->pwfx->nBlockAlign;
> - device->pwfx->nBlockAlign = passed_fmt->nChannels * (device->pwfx->wBitsPerSample / 8);
> - if(device->pwfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE)
> - fmtex->Samples.wValidBitsPerSample = device->pwfx->wBitsPerSample;
> - err = DSOUND_ReopenDevice(device, FALSE);
> - if(SUCCEEDED(err))
> - goto opened;
> -
> - WARN("No formats could be opened\n");
> - goto done;
> -
> -opened:
> - err = DSOUND_PrimaryOpen(device);
> - if (err != DS_OK) {
> - WARN("DSOUND_PrimaryOpen failed\n");
> - goto done;
> - }
> -
> - if (passed_fmt->nSamplesPerSec/100 != device->pwfx->nSamplesPerSec/100 && forced && device->buffer)
> - {
> DSOUND_PrimaryClose(device);
> - device->pwfx->nSamplesPerSec = passed_fmt->nSamplesPerSec;
> - err = DSOUND_ReopenDevice(device, TRUE);
> - if (FAILED(err))
> - WARN("DSOUND_ReopenDevice(2) failed: %08x\n", err);
> - else if (FAILED((err = DSOUND_PrimaryOpen(device))))
> - WARN("DSOUND_PrimaryOpen(2) failed: %08x\n", err);
> - }
> -
>
> - if(device->pwfx->wFormatTag == WAVE_FORMAT_IEEE_FLOAT ||
> - (device->pwfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
> - IsEqualGUID(&((WAVEFORMATEXTENSIBLE*)device->pwfx)->SubFormat,
> - &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)))
> - device->normfunction = normfunctions[4];
> - else
> - device->normfunction = normfunctions[device->pwfx->wBitsPerSample/8 - 1];
> -
> - if (old_fmt->nSamplesPerSec != device->pwfx->nSamplesPerSec ||
> - old_fmt->wBitsPerSample != device->pwfx->wBitsPerSample ||
> - old_fmt->nChannels != device->pwfx->nChannels) {
> - IDirectSoundBufferImpl** dsb = device->buffers;
> - for (i = 0; i < device->nrofbuffers; i++, dsb++) {
> - /* **** */
> - RtlAcquireResourceExclusive(&(*dsb)->lock, TRUE);
> + err = DSOUND_ReopenDevice(device, forced);
> + if (FAILED(err)) {
> + ERR("No formats could be opened\n");
> + goto done;
> + }
>
> - (*dsb)->freqAdjust = (*dsb)->freq / (float)device->pwfx->nSamplesPerSec;
> - DSOUND_RecalcFormat((*dsb));
> + err = DSOUND_PrimaryOpen(device);
> + if (err != DS_OK) {
> + ERR("DSOUND_PrimaryOpen failed\n");
> + goto done;
> + }
>
> - RtlReleaseResource(&(*dsb)->lock);
> - /* **** */
> +done:
> + if (err != DS_OK)
> + device->primary_pwfx = old_fmt;
> + else
> + HeapFree(GetProcessHeap(), 0, old_fmt);
> + } else if (passed_fmt->wFormatTag == WAVE_FORMAT_PCM ||
> + passed_fmt->wFormatTag == WAVE_FORMAT_IEEE_FLOAT) {
> + /* Fill in "real" values to primary_pwfx */
> + WAVEFORMATEX *fmt = device->primary_pwfx;
> +
> + *fmt = *device->pwfx;
> + fmtex = (void*)device->pwfx;
> +
> + if (IsEqualGUID(&fmtex->SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT) &&
> + passed_fmt->wFormatTag == WAVE_FORMAT_IEEE_FLOAT) {
> + fmt->wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
> + } else {
> + fmt->wFormatTag = WAVE_FORMAT_PCM;
> + fmt->wBitsPerSample = 16;
> }
> + fmt->nBlockAlign = fmt->nChannels * fmt->wBitsPerSample / 8;
> + fmt->nAvgBytesPerSec = fmt->nBlockAlign * fmt->nSamplesPerSec;
> + fmt->cbSize = 0;
> + } else {
> + device->primary_pwfx = HeapReAlloc(GetProcessHeap(), 0, device->primary_pwfx, sizeof(*fmtex));
> + memcpy(device->primary_pwfx, device->pwfx, sizeof(*fmtex));
> }
>
> -done:
> +out:
> LeaveCriticalSection(&(device->mixlock));
> RtlReleaseResource(&(device->buffer_list_lock));
> /* **** */
>
> - HeapFree(GetProcessHeap(), 0, old_fmt);
> return err;
> }
>
> @@ -834,11 +846,11 @@ static HRESULT WINAPI PrimaryBufferImpl_GetFormat(IDirectSoundBuffer *iface, WAV
> DirectSoundDevice *device = This->device;
> TRACE("(%p,%p,%d,%p)\n", iface, lpwf, wfsize, wfwritten);
>
> - size = sizeof(WAVEFORMATEX) + device->pwfx->cbSize;
> + size = sizeof(WAVEFORMATEX) + device->primary_pwfx->cbSize;
>
> if (lpwf) { /* NULL is valid */
> if (wfsize >= size) {
> - CopyMemory(lpwf,device->pwfx,size);
> + CopyMemory(lpwf,device->primary_pwfx,size);
> if (wfwritten)
> *wfwritten = size;
> } else {
> @@ -849,7 +861,7 @@ static HRESULT WINAPI PrimaryBufferImpl_GetFormat(IDirectSoundBuffer *iface, WAV
> }
> } else {
> if (wfwritten)
> - *wfwritten = sizeof(WAVEFORMATEX) + device->pwfx->cbSize;
> + *wfwritten = sizeof(WAVEFORMATEX) + device->primary_pwfx->cbSize;
> else {
> WARN("invalid parameter: wfwritten == NULL\n");
> return DSERR_INVALIDPARAM;
>
>
>