diff --git a/dlls/dsound/dsound.c b/dlls/dsound/dsound.c index 66c9d911e06..c5c6e8a5c30 100644 --- a/dlls/dsound/dsound.c +++ b/dlls/dsound/dsound.c @@ -23,6 +23,7 @@ #include #include #include +#include #define COBJMACROS #define NONAMELESSSTRUCT @@ -585,6 +586,31 @@ HRESULT WINAPI DirectSoundCreate8( return hr; } +void DSOUND_ParseSpeakerConfig(DirectSoundDevice *device) +{ + switch (DSSPEAKER_CONFIG(device->speaker_config)) { + case DSSPEAKER_MONO: + device->speaker_angles[0] = M_PI/180.0f * 0.0f; + device->speaker_num[0] = 0; + device->num_speakers = 1; + device->lfe_channel = -1; + break; + + case DSSPEAKER_STEREO: + case DSSPEAKER_HEADPHONE: + device->speaker_angles[0] = M_PI/180.0f * -90.0f; + device->speaker_angles[1] = M_PI/180.0f * 90.0f; + device->speaker_num[0] = 0; /* Left */ + device->speaker_num[1] = 1; /* Right */ + device->num_speakers = 2; + device->lfe_channel = -1; + break; + + default: + WARN("unknown speaker_config %u\n", device->speaker_config); + } +} + /******************************************************************************* * DirectSoundDevice */ @@ -605,6 +631,8 @@ static HRESULT DirectSoundDevice_Create(DirectSoundDevice ** ppDevice) device->state = STATE_STOPPED; device->speaker_config = DSSPEAKER_COMBINED(DSSPEAKER_STEREO, DSSPEAKER_GEOMETRY_WIDE); + DSOUND_ParseSpeakerConfig(device); + /* 3D listener initial parameters */ device->ds3dl.dwSize = sizeof(DS3DLISTENER); device->ds3dl.vPosition.x = 0.0; diff --git a/dlls/dsound/dsound_private.h b/dlls/dsound/dsound_private.h index 66af81a0261..5320d30e8b6 100644 --- a/dlls/dsound/dsound_private.h +++ b/dlls/dsound/dsound_private.h @@ -78,6 +78,10 @@ struct DirectSoundDevice CRITICAL_SECTION mixlock; IDirectSoundBufferImpl *primary; DWORD speaker_config; + float speaker_angles[DS_MAX_CHANNELS]; + int speaker_num[DS_MAX_CHANNELS]; + int num_speakers; + int lfe_channel; float *mix_buffer, *tmp_buffer; DWORD tmp_buffer_len, mix_buffer_len; @@ -199,6 +203,7 @@ HRESULT IKsPrivatePropertySetImpl_Create(REFIID riid, void **ppv) DECLSPEC_HIDDE HRESULT DSOUND_Create(REFIID riid, void **ppv) DECLSPEC_HIDDEN; HRESULT DSOUND_Create8(REFIID riid, void **ppv) DECLSPEC_HIDDEN; HRESULT IDirectSoundImpl_Create(IUnknown *outer_unk, REFIID riid, void **ppv, BOOL has_ds8) DECLSPEC_HIDDEN; +void DSOUND_ParseSpeakerConfig(DirectSoundDevice *device) DECLSPEC_HIDDEN; /* primary.c */ diff --git a/dlls/dsound/primary.c b/dlls/dsound/primary.c index ea4559cb87d..86ebba821ad 100644 --- a/dlls/dsound/primary.c +++ b/dlls/dsound/primary.c @@ -58,6 +58,21 @@ static DWORD DSOUND_fraglen(DirectSoundDevice *device) return ret; } +static DWORD speaker_config_to_channel_mask(DWORD speaker_config) +{ + switch (DSSPEAKER_CONFIG(speaker_config)) { + case DSSPEAKER_MONO: + return SPEAKER_FRONT_LEFT; + + case DSSPEAKER_STEREO: + case DSSPEAKER_HEADPHONE: + return SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT; + } + + WARN("unknown speaker_config %u\n", speaker_config); + return SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT; +} + static HRESULT DSOUND_WaveFormat(DirectSoundDevice *device, IAudioClient *client, BOOL forcewave, WAVEFORMATEX **wfx) { @@ -72,15 +87,11 @@ static HRESULT DSOUND_WaveFormat(DirectSoundDevice *device, IAudioClient *client 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; + if (mixwfe->Format.nChannels > device->num_speakers) { + mixwfe->Format.nChannels = device->num_speakers; mixwfe->Format.nBlockAlign = mixwfe->Format.nChannels * mixwfe->Format.wBitsPerSample / 8; mixwfe->Format.nAvgBytesPerSec = mixwfe->Format.nSamplesPerSec * mixwfe->Format.nBlockAlign; - mixwfe->dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT; + mixwfe->dwChannelMask = speaker_config_to_channel_mask(device->speaker_config); } if (!IsEqualGUID(&mixwfe->SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)) { @@ -226,6 +237,8 @@ HRESULT DSOUND_ReopenDevice(DirectSoundDevice *device, BOOL forcewave) device->speaker_config = DSOUND_FindSpeakerConfig(device->mmdevice); + DSOUND_ParseSpeakerConfig(device); + hres = DSOUND_WaveFormat(device, device->client, forcewave, &wfx); if (FAILED(hres)) { IAudioClient_Release(device->client);