From 4d454498c8f4cf6593d4afe405fb602ebb0e2722 Mon Sep 17 00:00:00 2001 From: Donny Yang Date: Sat, 14 Jul 2012 16:40:07 +1000 Subject: dsound: Add detection of output format and upmixing from mono to any number of channels --- dlls/dsound/dsound.c | 19 +++++++++++++++++++ dlls/dsound/dsound_convert.c | 8 +++++--- dlls/dsound/dsound_private.h | 2 +- dlls/dsound/mixer.c | 7 +++---- dlls/dsound/primary.c | 28 ++++++++++++++++++++++++++++ 5 files changed, 56 insertions(+), 8 deletions(-) diff --git a/dlls/dsound/dsound.c b/dlls/dsound/dsound.c index e401725..7d75760 100644 --- a/dlls/dsound/dsound.c +++ b/dlls/dsound/dsound.c @@ -1382,6 +1382,7 @@ HRESULT DirectSoundDevice_Initialize(DirectSoundDevice ** ppDevice, LPCGUID lpcG GUID devGUID; DirectSoundDevice *device; IMMDevice *mmdevice; + WAVEFORMATEX *pwfx; TRACE("(%p,%s)\n",ppDevice,debugstr_guid(lpcGUID)); @@ -1492,6 +1493,24 @@ HRESULT DirectSoundDevice_Initialize(DirectSoundDevice ** ppDevice, LPCGUID lpcG } else WARN("DSOUND_PrimaryCreate failed: %08x\n", hr); + hr = IAudioClient_GetMixFormat(device->client, &pwfx); + if(FAILED(hr)){ + WARN("IAudioClient_GetMixFormat failed: %08x; Falling back to default output format\n", hr); + }else{ + DWORD oldPriolevel = device->priolevel; + device->priolevel = DSSCL_WRITEPRIMARY; + hr = primarybuffer_SetFormat(device, pwfx); + device->priolevel = oldPriolevel; + CoTaskMemFree(pwfx); + if(FAILED(hr)){ + HeapFree(GetProcessHeap(), 0, device); + LeaveCriticalSection(&DSOUND_renderers_lock); + IMMDevice_Release(mmdevice); + WARN("primarybuffer_SetFormat failed: %08x\n", hr); + return hr; + } + } + *ppDevice = device; list_add_tail(&DSOUND_renderers, &device->entry); diff --git a/dlls/dsound/dsound_convert.c b/dlls/dsound/dsound_convert.c index d3d686a..a8c929c 100644 --- a/dlls/dsound/dsound_convert.c +++ b/dlls/dsound/dsound_convert.c @@ -159,10 +159,12 @@ void putieee32(const IDirectSoundBufferImpl *dsb, DWORD pos, DWORD channel, floa *fbuf = value; } -void put_mono2stereo(const IDirectSoundBufferImpl *dsb, DWORD pos, DWORD channel, float value) +void put_mono(const IDirectSoundBufferImpl *dsb, DWORD pos, DWORD channel, float value) { - dsb->put_aux(dsb, pos, 0, value); - dsb->put_aux(dsb, pos, 1, value); + /* XXX: Is this how Windows does this? */ + DWORD c; + for (c = 0; c < dsb->device->pwfx->nChannels; ++c) + dsb->put_aux(dsb, pos, c, value); } void mixieee32(float *src, float *dst, unsigned samples) diff --git a/dlls/dsound/dsound_private.h b/dlls/dsound/dsound_private.h index 1cf6daa..68f6242 100644 --- a/dlls/dsound/dsound_private.h +++ b/dlls/dsound/dsound_private.h @@ -202,7 +202,7 @@ struct IDirectSoundBufferImpl }; float get_mono(const IDirectSoundBufferImpl *dsb, DWORD pos, DWORD channel) DECLSPEC_HIDDEN; -void put_mono2stereo(const IDirectSoundBufferImpl *dsb, DWORD pos, DWORD channel, float value) DECLSPEC_HIDDEN; +void put_mono(const IDirectSoundBufferImpl *dsb, DWORD pos, DWORD channel, float value) DECLSPEC_HIDDEN; HRESULT IDirectSoundBufferImpl_Create( DirectSoundDevice *device, diff --git a/dlls/dsound/mixer.c b/dlls/dsound/mixer.c index 13eb03d..547c666 100644 --- a/dlls/dsound/mixer.c +++ b/dlls/dsound/mixer.c @@ -157,7 +157,7 @@ void DSOUND_RecalcFormat(IDirectSoundBufferImpl *dsb) else if (ichannels == 1) { dsb->mix_channels = 1; - dsb->put = put_mono2stereo; + dsb->put = put_mono; } else if (ochannels == 1) { @@ -166,9 +166,8 @@ void DSOUND_RecalcFormat(IDirectSoundBufferImpl *dsb) } else { - if (ichannels > 2) - FIXME("Conversion from %u to %u channels is not implemented, falling back to stereo\n", ichannels, ochannels); - dsb->mix_channels = 2; + FIXME("Conversion from %u to %u channels is not implemented, falling back to %u channels\n", ichannels, ochannels, ochannels); + dsb->mix_channels = ochannels; } } diff --git a/dlls/dsound/primary.c b/dlls/dsound/primary.c index cfe674e..9fd1ff2 100644 --- a/dlls/dsound/primary.c +++ b/dlls/dsound/primary.c @@ -484,6 +484,34 @@ HRESULT primarybuffer_SetFormat(DirectSoundDevice *device, LPCWAVEFORMATEX passe goto done; opened: + switch(device->pwfx->nChannels){ + case 0: + device->speaker_config = DSSPEAKER_DIRECTOUT; + break; + case 1: + device->speaker_config = DSSPEAKER_MONO; + break; + case 2: + case 3: + device->speaker_config = DSSPEAKER_COMBINED(DSSPEAKER_STEREO, DSSPEAKER_GEOMETRY_WIDE); + break; + case 4: + case 5: + device->speaker_config = DSSPEAKER_QUAD; + break; + case 6: + case 7: + device->speaker_config = DSSPEAKER_5POINT1_SURROUND; + break; + case 8: + device->speaker_config = DSSPEAKER_7POINT1_SURROUND; + break; + default: + FIXME("Unknown speaker configuration: %u\n", device->pwfx->nChannels); + device->speaker_config = DSSPEAKER_DIRECTOUT; + break; + } + err = DSOUND_PrimaryOpen(device); if (err != DS_OK) { WARN("DSOUND_PrimaryOpen failed\n"); -- 1.7.9.5