[Bug 12651] Bad sound quality in Starcraft when running with hardware acceleration

wine-bugs at winehq.org wine-bugs at winehq.org
Wed Dec 29 18:48:15 CST 2010


http://bugs.winehq.org/show_bug.cgi?id=12651

--- Comment #10 from Raymond <superquad.vortex2 at 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;

-- 
Configure bugmail: http://bugs.winehq.org/userprefs.cgi?tab=email
Do not reply to this email, post in Bugzilla using the
above URL to reply.
------- You are receiving this mail because: -------
You are watching all bug changes.



More information about the wine-bugs mailing list