Getting audio to work properly in your Windows VM is one of the biggest challenges for VFIO enthusiasts, regardless of experience level. Over time, a wide variety of workarounds became popular, like passing through an audio interface, or using a usb sound card. Unfortunately, audio equipment can be costly, and doesn’t offer a seamless experience. This article will show you how to get the most out of your audio setup using nothing but software and the equipment you already own.

Read also: Handsfree Monitor Switching With DDCUtil

About Linux audio

Here’s a basic overview of the way most linux distros handle sound: At the base of the stack there’s the Advanced Linux Sound Architecture – also known as ALSA. Since 2002, it has most commonly provided the interface for audio device drivers: it supports a huge list of sound cards. If your distro plays sound out of the box, you are probably running ALSA.

On top of that we usually have PulseAudio, a sound server which comes pre-installed with most Linux distros. Using it allows for easy switching between multiple devices and regulating volume system-wide as well as per-device and each application individually.

In general, there is no pressing reason to use a sound server since most applications (including QEMU) work with ALSA alone. With interactive media like games in mind this potentially good practice as you shorten the processing pipeline by one instance and potentially reduce latency. However, some packages like the Gnome desktop environment or Discord depend on PulseAudio in order to function properly, so there’s no reason to get rid of pulse if things are working for you. We will provide you with configuration samples for both use cases.

Patching QEMU

UPDATE: as of qemu 4.0, patching is no longer needed. Please check below for qemu arguments.

In late 2017, the reddit user Spheenik provided a patch for QEMU which dramatically improves its audio backend. Thanks to his work it is now possible to have well-functioning playback and recording inside guest operating systems.

On Arch Linux a pre-patched version of QEMU is available in the AUR, but for other distributions, please check Spheenik’s Reddit post for build instructions.

Configuring VM Audio over PulseAudio

The instructions in this section will attach your VM to PulseAudio. They are recommended for most users.

Make sure your user has been added to the “libvirt”group by issuing sudo gpasswd -a *user* libvirt. Replace *user* with your own user name.
Open /etc/libvirt/qemu.conf in an editor and look for #user =. Uncomment the line and add your user name here as well.

Configuring VM Audio over ALSA

The instructions in this section will attach your VM to ALSA directly. They are recommended to more advanced users who want lower latency but also need to run applications depending on PulseAudio.

If you have been using PulseAudio on your system so far, you need to disconnect it from ALSA. On Arch, Uninstall the pulseaudio-alsa package and remove /etc/asound.conf as well as ~/.asoundrc.
Now PulseAudio needs to be configured to use ALSA‘s dmix device which prevents it from claiming your hardware exclusively. Open /etc/pulse/default.pa in an editor and uncomment the lines which load backend drivers, then add device parameters as follows:

load-module module-alsa-sink device=dmix
load-module module-alsa-source device=dsnoop

Also find and comment lines which load autodetect modules.

# load-module module-udev-detect
# load-module module-detect

Reboot.

Guest configuration

Add the ich9 audio device to your VM, remove any other virtual audio devices.

Open your VM’s XML configuration file in your favorite editor, most commonly done with a command like:
sudo EDITOR=nano virsh edit *vm_name*
Edit your XML as follows:

### XML for ALSA
<domain type='kvm' xmlns:qemu='http://libvirt.org/schemas/domain/qemu/1.0'>
  ...
  <qemu:commandline>
    <qemu:env name='QEMU_AUDIO_DRV' value='alsa'/>
    <qemu:env name='QEMU_AUDIO_DAC_FIXED_FREQ' value='48000'/>
    <qemu:env name='QEMU_AUDIO_DAC_TRY_POLL' value='0'/>
    <qemu:env name='QEMU_AUDIO_ADC_FIXED_FREQ' value='48000'/>
    <qemu:env name='QEMU_AUDIO_ADC_TRY_POLL' value='0'/>
    <qemu:env name='QEMU_AUDIO_TIMER_PERIOD' value='1000'/>
    <qemu:env name='QEMU_ALSA_DAC_BUFFER_SIZE' value='2048'/>
    <qemu:env name='QEMU_ALSA_DAC_PERIOD_SIZE' value='1024'/>
  </qemu:commandline>
</domain>


### XML for PA
<domain type='kvm' xmlns:qemu='http://libvirt.org/schemas/domain/qemu/1.0'>
  ...
  <qemu:commandline>
    <qemu:env name='QEMU_AUDIO_DRV' value='pa'/>
    <qemu:env name='QEMU_AUDIO_DAC_FIXED_FREQ' value='48000'/>
    <qemu:env name='QEMU_AUDIO_DAC_TRY_POLL' value='0'/>
    <qemu:env name='QEMU_AUDIO_ADC_FIXED_FREQ' value='48000'/>
    <qemu:env name='QEMU_AUDIO_ADC_TRY_POLL' value='0'/>
    <qemu:env name='QEMU_AUDIO_TIMER_PERIOD' value='1000'/>
    <qemu:env name='QEMU_PA_SERVER' value='/run/user/1000/pulse/native'/>
  </qemu:commandline>
</domain>

Now, start up the VM with the revised xml, and enjoy your working virtualized audio.

UPDATE:  as of qemu 4.0,  Patching is no longer necessary. Follow the standard audio guide on the Arch Wiki instead. You need an additional qemu argument to make the passthrough functional:

<qemu:arg value='-audiodev'/>
<qemu:arg value='pa,id=pa1,server=/run/user/1000/pulse/native'/>

This will enable what the patch did previously.

 

Do you do prefer software or hardware solutions for your VM audio? Let us know about it in the comments and our official Discord server.


Images Via Pixabay