mmdevapi performance analysis

Joerg-Cyril.Hoehle at Joerg-Cyril.Hoehle at
Wed Sep 28 03:29:03 CDT 2011


While the 3D guys work on performance improvements, we audio guys kill it.
Luckily gfx data is shuffled around in MB/s, audio only in hundred kB/s, so
hopefully it doesn't weight that much.

Let's have a look at how data wanders around with dsound, winmm and mmdevapi.

waveOutWrite with mmdevapi:
  copy to mmdevapi ALSA/OSS buffer
    copy some in case of mmdevapi buffer wrap around
    write buffer to ALSA/OSS

waveOutWrite old driver model:
    write header to ALSA/OSS

waveOutWrite involving MSACM with mmdevapi:
 convert PCM to MSACM, writing to new buffer
  copy to mmdevapi ALSA/OSS buffer
    copy some in case of buffer wrap around
    write to ALSA/OSS
Here, if msacm/waveform.c had the courage to delay conversion until
GetBuffer time, some copying could be avoided as msacm would write
directly into mmdevapi's buffer.

Being overly protective ("I should convert before GetBuffer because
afterwards I might not have enough time") ends up wasting CPU cycles,
hence paradoxically increasing the probability of being late thus
causing underruns.

The cause for the impedance mismatch between winmm and mmdevapi is
what I call "owner inversion". The app supplies winmm with a pointer to its data
buffers. As mmdevapi does the same, some transfer is needed between both.
Arguably, mmdevapi is not the best target for winmm in Wine...

DSOUND_WaveQueue newest "reimplement rendering on mmdevapi" in 1.3.30:
 write to dsound secondary buffer
 mix secondary to primary buffer
  copy to mmdevapi buffer
    copy some more in case of mmdevapi buffer wrap around
    write buffer to ALSA/OSS
It looks like the new code misses the opportunity to equate device
buffer with primary buffer.  Instead we've got a cascade of buffers.

Why is dsound's primary (mixing target) not mmdevapi's buffer?

What's the goal? Ideally,
1. ALSA's mmdevdrv Get/ReleaseBuffer use snd_pcm_mmap_begin/commit,
   avoiding copying from mmdevapi to ALSA;
2. mmdevapi's buffer becomes DSound's primary,
   avoiding copying from dsound to mmdevapi.
   This applies even to CoreAudio where there's not really an mmdevapi buffer.

The result: DSound's mixer talks straight with the HW.
This should be no surprise.  mmdevapi's shared mode mixer
probably has roots in dsound's.

BTW, what prevents equating dsound's secondary buffers with mmdevapi's
shared mode streams and let the underlying device perform the mixing?

 Jörg Höhle

More information about the wine-devel mailing list