http://bugs.winehq.org/show_bug.cgi?id=12651
--- Comment #10 from Raymond superquad.vortex2@gmail.com 2010-12-29 18:48:14 CST ---
(In reply to comment #2)
I'm running Starcraft here with full hardware acceleration, and I don't have any issues with sound quality. Perhaps this is hardware related...
My sound card: 04:07.0 Multimedia audio controller: Creative Labs SB Live! EMU10k1 (rev 07) Subsystem: Creative Labs SBLive! Player 5.1 Flags: bus master, medium devsel, latency 64, IRQ 19 I/O ports at e880 [size=32] Capabilities: [dc] Power Management version 1
(In reply to comment #0)
When starting Starcraft with any kind of sound DirectSound hardware acceleration enabled (Basic, Standard, Full (in winecfg)),
Basic mean it don't use hardware buffers even the sound cards have hardware buffer
The current implementation in winealsa.drv actually force all sound cards to mix software secondary buffers since dwMaxHwMixingAllBuffers, ... are zero
HRESULT DirectSoundDevice_GetCaps( DirectSoundDevice * device, LPDSCAPS lpDSCaps) {
... lpDSCaps->dwMaxContigFreeHwMemBytes = device->drvcaps.dwMaxContigFreeHwMemBytes;
if ( ds_emuldriver ) { lpDSCaps->dwMaxHwMixingAllBuffers = 0; lpDSCaps->dwMaxHwMixingStaticBuffers = 0; lpDSCaps->dwMaxHwMixingStreamingBuffers = 0; lpDSCaps->dwFreeHwMixingAllBuffers = 0; lpDSCaps->dwFreeHwMixingStaticBuffers = 0; lpDSCaps->dwFreeHwMixingStreamingBuffers= 0; lpDSCaps->dwMaxHw3DAllBuffers = 0; lpDSCaps->dwMaxHw3DStaticBuffers = 0; lpDSCaps->dwMaxHw3DStreamingBuffers = 0; lpDSCaps->dwFreeHw3DAllBuffers = 0; lpDSCaps->dwFreeHw3DStaticBuffers = 0; lpDSCaps->dwFreeHw3DStreamingBuffers = 0; }
/* driver doesn't have these */ lpDSCaps->dwUnlockTransferRateHwBuffers = 4096; /* But we have none... */ lpDSCaps->dwPlayCpuOverheadSwBuffers = 1; /* 1% */
return DS_OK; }
Need to change those parameters to non-zero when wine can open alsa playback device multiple time (e.g. "front" device of emu10k1 )
static int ALSA_AddPlaybackDevice(snd_ctl_t *ctl, snd_pcm_t *pcm, const char *pcmname, int isdefault) { WINE_WAVEDEV wwo; int rc;
memset(&wwo, '\0', sizeof(wwo));
rc = ALSA_AddCommonDevice(ctl, pcm, pcmname, &wwo); if (rc) return(rc);
MultiByteToWideChar(CP_UNIXCP, 0, wwo.ds_desc.szDesc, -1, wwo.outcaps.szPname, sizeof(wwo.outcaps.szPname)/sizeof(WCHAR)); wwo.outcaps.szPname[sizeof(wwo.outcaps.szPname)/sizeof(WCHAR) - 1] = '\0';
wwo.outcaps.wMid = MM_CREATIVE; wwo.outcaps.wPid = MM_CREATIVE_SBP16_WAVEOUT; wwo.outcaps.vDriverVersion = 0x0100;
rc = ALSA_ComputeCaps(ctl, pcm, &wwo.outcaps.wChannels, &wwo.ds_caps, &wwo.outcaps.dwFormats, &wwo.outcaps.dwSupport); if (rc) { WARN("Error calculating device caps for pcm [%s]\n", wwo.pcmname); ALSA_FreeDevice(&wwo); return(rc); }
{ snd_pcm_t *multipcm; /* alsa device which allow multiple open , this mean it is already support mixing (e.g. hw with multiple subdevices , pulse, dmix, or jack ) however dmix and jack is almost useless since dsoutput.c disable resampling unless dsound application request same rate as dmix or jack server */ if ( snd_pcm_open(&multipcm,pcmname, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK) == 0 ) { TRACE("Mixing buffers available\n"); wwo.ds_caps.dwMaxHwMixingAllBuffers = 16; wwo.ds_caps.dwMaxHwMixingStaticBuffers = 16; wwo.ds_caps.dwMaxHwMixingStreamingBuffers = 16; wwo.ds_caps.dwFreeHwMixingAllBuffers = 16; wwo.ds_caps.dwFreeHwMixingStaticBuffers = 16; wwo.ds_caps.dwFreeHwMixingStreamingBuffers = 16;
if (( wwo.ds_caps.dwFlags & DSCAPS_PRIMARYMONO ) == DSCAPS_PRIMARYMONO ) { wwo.ds_caps.dwFlags |= DSCAPS_SECONDARYMONO; /* 3D buffer mean sound card can pan mono to left and right so it must support both mono and stereo 1) mono only device cannot support 3D buffer 2) stereo only device - wine must playback mono 3D sound by stereo and perform software pan to left and right so "plug" or "route" plugin cannot be used */ if (( wwo.ds_caps.dwFlags & DSCAPS_PRIMARYSTEREO ) == DSCAPS_PRIMARYSTEREO ) { wwo.ds_caps.dwFlags |= DSCAPS_SECONDARYSTEREO; TRACE("3D buffers available\n"); wwo.ds_caps.dwMaxHw3DAllBuffers = 16; wwo.ds_caps.dwMaxHw3DStaticBuffers = 16; wwo.ds_caps.dwMaxHw3DStreamingBuffers = 16; wwo.ds_caps.dwFreeHw3DAllBuffers = 16; wwo.ds_caps.dwFreeHw3DStaticBuffers = 16; wwo.ds_caps.dwFreeHw3DStreamingBuffers = 16; } } snd_pcm_close(multipcm); } }
rc = ALSA_AddDeviceToArray(&wwo, &WOutDev, &ALSA_WodNumDevs, &ALSA_WodNumMallocedDevs, isdefault); if (rc) ALSA_FreeDevice(&wwo); return (rc); }
The above change should emulate the correct behaviour and dxdiag will try to play sound with hardware buffer in hardware acceleration mode but only play sound with software secondary buffer in emulation mode
However you still need to implement hardware secondary buffer support in winealsa.drv by disable the mixing of software secondary buffers and use snd_pcm_open() to open "front" device of your snd-emu10k1 multiple times since the current implementation return DSERR_UNSUPPORTED
static HRESULT WINAPI IDsDriverImpl_CreateSoundBuffer(PIDSDRIVER iface, LPWAVEFORMATEX pwfx, DWORD dwFlags, DWORD dwCardAddress, LPDWORD pdwcbBufferSize, LPBYTE *ppbBuffer, LPVOID *ppvObj) { IDsDriverImpl *This = impl_from_IDsDriver(iface); IDsDriverBufferImpl** ippdsdb = (IDsDriverBufferImpl**)ppvObj; HRESULT err;
TRACE("(%p,%p,%x,%x)\n",iface,pwfx,dwFlags,dwCardAddress); /* we only support primary buffers... for now */ if (!(dwFlags & DSBCAPS_PRIMARYBUFFER)) return DSERR_UNSUPPORTED; if (This->primary) return DSERR_ALLOCATED;