Commit f648c9b2 authored by David Reid's avatar David Reid

Get playback working on Windows 98 with the DirectSound backend.

This change adds a fallback for when setting the format of the primary
buffer fails. I have observed this happening with floating point
formats so I've forced the use of integer PCM formats in the fallback
case. I've also restricted it to 44100 because when I tried 4800 on
my Windows 98 machine it resulted in incorrect output.
parent 0887aab9
...@@ -24308,6 +24308,8 @@ static ma_result ma_device_init__dsound(ma_device* pDevice, const ma_device_conf ...@@ -24308,6 +24308,8 @@ static ma_result ma_device_init__dsound(ma_device* pDevice, const ma_device_conf
ma_uint32 periodSizeInFrames; ma_uint32 periodSizeInFrames;
ma_uint32 periodCount; ma_uint32 periodCount;
MA_DSBUFFERDESC descDS; MA_DSBUFFERDESC descDS;
WORD nativeChannelCount;
DWORD nativeChannelMask = 0;
result = ma_config_to_WAVEFORMATEXTENSIBLE(pDescriptorPlayback->format, pDescriptorPlayback->channels, pDescriptorPlayback->sampleRate, pDescriptorPlayback->channelMap, &wf); result = ma_config_to_WAVEFORMATEXTENSIBLE(pDescriptorPlayback->format, pDescriptorPlayback->channels, pDescriptorPlayback->sampleRate, pDescriptorPlayback->channelMap, &wf);
if (result != MA_SUCCESS) { if (result != MA_SUCCESS) {
...@@ -24341,21 +24343,25 @@ static ma_result ma_device_init__dsound(ma_device* pDevice, const ma_device_conf ...@@ -24341,21 +24343,25 @@ static ma_result ma_device_init__dsound(ma_device* pDevice, const ma_device_conf
return ma_result_from_HRESULT(hr); return ma_result_from_HRESULT(hr);
} }
if (pDescriptorPlayback->channels == 0) { if ((caps.dwFlags & MA_DSCAPS_PRIMARYSTEREO) != 0) {
if ((caps.dwFlags & MA_DSCAPS_PRIMARYSTEREO) != 0) { DWORD speakerConfig;
DWORD speakerConfig;
/* It supports at least stereo, but could support more. */ /* It supports at least stereo, but could support more. */
wf.Format.nChannels = 2; nativeChannelCount = 2;
/* Look at the speaker configuration to get a better idea on the channel count. */ /* Look at the speaker configuration to get a better idea on the channel count. */
if (SUCCEEDED(ma_IDirectSound_GetSpeakerConfig((ma_IDirectSound*)pDevice->dsound.pPlayback, &speakerConfig))) { if (SUCCEEDED(ma_IDirectSound_GetSpeakerConfig((ma_IDirectSound*)pDevice->dsound.pPlayback, &speakerConfig))) {
ma_get_channels_from_speaker_config__dsound(speakerConfig, &wf.Format.nChannels, &wf.dwChannelMask); ma_get_channels_from_speaker_config__dsound(speakerConfig, &nativeChannelCount, &nativeChannelMask);
}
} else {
/* It does not support stereo, which means we are stuck with mono. */
wf.Format.nChannels = 1;
} }
} else {
/* It does not support stereo, which means we are stuck with mono. */
nativeChannelCount = 1;
nativeChannelMask = 0x00000001;
}
if (pDescriptorPlayback->channels == 0) {
wf.Format.nChannels = nativeChannelCount;
wf.dwChannelMask = nativeChannelMask;
} }
if (pDescriptorPlayback->sampleRate == 0) { if (pDescriptorPlayback->sampleRate == 0) {
...@@ -24377,11 +24383,28 @@ static ma_result ma_device_init__dsound(ma_device* pDevice, const ma_device_conf ...@@ -24377,11 +24383,28 @@ static ma_result ma_device_init__dsound(ma_device* pDevice, const ma_device_conf
supported format. To determine whether this has happened, an application can call the GetFormat method for the primary buffer supported format. To determine whether this has happened, an application can call the GetFormat method for the primary buffer
and compare the result with the format that was requested with the SetFormat method. and compare the result with the format that was requested with the SetFormat method.
*/ */
hr = ma_IDirectSoundBuffer_SetFormat((ma_IDirectSoundBuffer*)pDevice->dsound.pPlaybackPrimaryBuffer, (WAVEFORMATEX*)&wf); hr = ma_IDirectSoundBuffer_SetFormat((ma_IDirectSoundBuffer*)pDevice->dsound.pPlaybackPrimaryBuffer, &wf.Format);
if (FAILED(hr)) { if (FAILED(hr)) {
ma_device_uninit__dsound(pDevice); /*
ma_log_post(ma_device_get_log(pDevice), MA_LOG_LEVEL_ERROR, "[DirectSound] Failed to set format of playback device's primary buffer."); If setting of the format failed we'll try again with some fallback settings. On Windows 98 I have
return ma_result_from_HRESULT(hr); observed that IEEE_FLOAT does not work. We'll therefore enforce PCM. I also had issues where a
sample rate of 48000 did not work correctly. Not sure if it was a driver issue or not, but will
use 44100 for the sample rate.
*/
wf.Format.cbSize = sizeof(wf.Format);
wf.Format.wFormatTag = WAVE_FORMAT_PCM;
wf.Format.wBitsPerSample = 16;
wf.Format.nChannels = nativeChannelCount;
wf.Format.nSamplesPerSec = 44100;
wf.Format.nBlockAlign = wf.Format.nChannels * (wf.Format.wBitsPerSample / 8);
wf.Format.nAvgBytesPerSec = wf.Format.nSamplesPerSec * wf.Format.nBlockAlign;
hr = ma_IDirectSoundBuffer_SetFormat((ma_IDirectSoundBuffer*)pDevice->dsound.pPlaybackPrimaryBuffer, &wf.Format);
if (FAILED(hr)) {
ma_device_uninit__dsound(pDevice);
ma_log_post(ma_device_get_log(pDevice), MA_LOG_LEVEL_ERROR, "[DirectSound] Failed to set format of playback device's primary buffer.");
return ma_result_from_HRESULT(hr);
}
} }
/* Get the _actual_ properties of the buffer. */ /* Get the _actual_ properties of the buffer. */
...@@ -24428,7 +24451,7 @@ static ma_result ma_device_init__dsound(ma_device* pDevice, const ma_device_conf ...@@ -24428,7 +24451,7 @@ static ma_result ma_device_init__dsound(ma_device* pDevice, const ma_device_conf
descDS.dwSize = sizeof(descDS); descDS.dwSize = sizeof(descDS);
descDS.dwFlags = MA_DSBCAPS_CTRLPOSITIONNOTIFY | MA_DSBCAPS_GLOBALFOCUS | MA_DSBCAPS_GETCURRENTPOSITION2; descDS.dwFlags = MA_DSBCAPS_CTRLPOSITIONNOTIFY | MA_DSBCAPS_GLOBALFOCUS | MA_DSBCAPS_GETCURRENTPOSITION2;
descDS.dwBufferBytes = periodSizeInFrames * periodCount * ma_get_bytes_per_frame(pDescriptorPlayback->format, pDescriptorPlayback->channels); descDS.dwBufferBytes = periodSizeInFrames * periodCount * ma_get_bytes_per_frame(pDescriptorPlayback->format, pDescriptorPlayback->channels);
descDS.lpwfxFormat = (WAVEFORMATEX*)&wf; descDS.lpwfxFormat = &pActualFormat->Format;
hr = ma_IDirectSound_CreateSoundBuffer((ma_IDirectSound*)pDevice->dsound.pPlayback, &descDS, (ma_IDirectSoundBuffer**)&pDevice->dsound.pPlaybackBuffer, NULL); hr = ma_IDirectSound_CreateSoundBuffer((ma_IDirectSound*)pDevice->dsound.pPlayback, &descDS, (ma_IDirectSoundBuffer**)&pDevice->dsound.pPlaybackBuffer, NULL);
if (FAILED(hr)) { if (FAILED(hr)) {
ma_device_uninit__dsound(pDevice); ma_device_uninit__dsound(pDevice);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment