Virtual machine audio setup – or how to get pulse audio working

In this post, I compare several options of how to get the sound output from an KVM virtual machine guest, back into the host. I will compare spice server, pulse audio and a hardware solution.

The Host runs an Asus Xonar DGX 5.1 PCIE sound card.

In any case – harmonize sample rates of host and guest system

A common issue with sound passthrough between guest and host is lagging or chopped up sound playback. In order to fix this make sure the host and the guest use the same default playback sample rate.

Setting default sample rate in Linux

open /etc/libvirt/qemu.conf via

sudo nano /etc/libvirt/qemu.conf

and uncomment the line

user = "example"

replace your username with example

open /etc/pulse/daemon.conf

and find/add/uncomment the lines and set these values:

default-sample-rate = 44100
alternate-sample-rate = 48000

afterwards restart the pulse audio service via

pulseaudio -k or reboot.

Setting default sample rate in Windows

Set the frequency of your windows sound to 44100 Hz

Set sample rate for default audio device in windows 10
Set sample rate for default audio device in windows 10

Option 1 – use Spice Server

(+) Easy to set up
(+) Very good for first setup of the VM OS.
(-) Needs VM window open in order to work
(-) a little more delay than direct pulse audio version
(-) Adds an extra display to the VM.

This one is pretty straight forward, open the info page of the VM on virt-manager and add a spice server.

Add spice server via virtmanager GUI
Add spice server via virt-manager GUI

Adding the spice server adds actually several devices to the VM config, one for example is a display.

In order to hear sound, I have to open the VM while it is running (I hope the sentence make sense 🙂 ). Basically it is double clicking on the running VM in the virt-manager list.

Open VM spice server window while VM is running
Open VM spice server window while VM is running

Option 2 – use Pulse Audio

(+) Less sound delay than the spice server version
(+) Less overhead once running
(+) Nicer Integration
(-) Complicated to get it working
(-) Lots of users complain about bad sound quality

Pulse Audio with QEMU 4.2 (and above)

Edit the virtual machine config via
virsh edit <your vm name>

e.g. virsh edit windows10

Make sure the very first line of the file does read:

<domain type='kvm' xmlns:qemu='http://libvirt.org/schemas/domain/qemu/1.0'>

Instead of

<domain type='kvm'>

Check at the bottom of your config if a line <qemu:commandline> exists. If yes make sure to add these options:

  <qemu:arg value='-device'/>
  <qemu:arg value='ich9-intel-hda,bus=pcie.0,addr=0x1b'/>
  <qemu:arg value='-device'/>
  <qemu:arg value='hda-micro,audiodev=hda'/>
  <qemu:arg value='-audiodev'/>
  <qemu:arg value='pa,id=hda,server=unix:/run/user/1000/pulse/native'/>
</qemu:commandline>

In case <qemu:commandline> is missing, find the line which ends with </devices>
and add the following block afterwards:

<qemu:commandline>
  <qemu:arg value='-device'/>
  <qemu:arg value='ich9-intel-hda,bus=pcie.0,addr=0x1b'/>
  <qemu:arg value='-device'/>
  <qemu:arg value='hda-micro,audiodev=hda'/>
  <qemu:arg value='-audiodev'/>
  <qemu:arg value='pa,id=hda,server=unix:/run/user/1000/pulse/native'/>
</qemu:commandline>

The 1000 in

server=unix:/run/user/1000/pulse/native

represents your user-id, 1000 is the default (one user) Id.

Attention!

Make sure <devices> and <qemu:commandline> have the same indent.

Remark!

The <qemu:commandline> part can hold further options, simply append the sound options if others were already present.

Open the apparmor libvirt abstractions file via

sudo nano /etc/apparmor.d/abstractions/libvirt-qemu

Append the following lines

/etc/pulse/client.conf.d/ r,
/etc/pulse/client.conf.d/* r,
/run/user/1000/pulse/native rw,
/home/your-username/.config/pulse/* r,
/home/your-username/.config/pulse/cookie k,

Replace your-username with your username.

→ reboot your system.

Settings in Virt-manager

Make sure no further audio devices are added by virt-manager – remove all audio devices from the virtual hardware details bar (left side in VM info view).

Troubleshooting

If you have no sound at all, run pax11publish and check if a server with name /run/user/1000/pulse/native is available.

Pulse Audio with QEMU 4.1 (and below)

Edit the virtual machine config via
virsh edit <your vm name>

e.g. virsh edit windows10

Make sure the very first line of the file does read:

<domain type='kvm' xmlns:qemu='http://libvirt.org/schemas/domain/qemu/1.0'>

instead of

<domain type='kvm'>

Check at the bottom of your config if a line <qemu:commandline> exists. If yes make sure to add these options:

  <qemu:env name='QEMU_AUDIO_DRV' value='pa'/>
  <qemu:env name='QEMU_PA_SAMPLES' value='8192'/>
  <qemu:env name='QEMU_AUDIO_TIMER_PERIOD' value='99'/>
  <qemu:env name='QEMU_PA_SERVER' value='/run/user/1000/pulse/native'/>

In case <qemu:commandline> is missing, find the line which ends with </devices>
and add the following block afterwards:

<qemu:commandline>
  <qemu:env name='QEMU_AUDIO_DRV' value='pa'/>
  <qemu:env name='QEMU_PA_SAMPLES' value='8192'/>
  <qemu:env name='QEMU_AUDIO_TIMER_PERIOD' value='99'/>
  <qemu:env name='QEMU_PA_SERVER' value='/run/user/1000/pulse/native'/>
</qemu:commandline>

The 1000 in /run/user/1000/pulse/native represents your user-id. 1000 is the default (one user) user id.

Attention!

After adding the enlightments, I had no internet on one Windows 10 guest (also not every time).

After some digging, I found a reddit post with the proposed “solution” to change the model type of the network bridge interface in the libvirt config from “virtio” to “virtio-net-pci”.

Remark!

Lorem Ipsum!

Extract from my config file

   </devices>
   <qemu:commandline>
     <qemu:arg value='-cpu'/>
     <qemu:arg value='host,hv_time,kvm=off,hv_vendor_id=null'/>
     <qemu:env name='QEMU_AUDIO_DRV' value='pa'/>
     <qemu:env name='QEMU_PA_SAMPLES' value='8192'/>
     <qemu:env name='QEMU_AUDIO_TIMER_PERIOD' value='99'/>
     <qemu:env name='QEMU_PA_SERVER' value='/run/user/1000/pulse/native'/>
   </qemu:commandline>
</domain>

[collapse]

Settings in Virt-manager

As said before, add a sound “ich6” device to your VM.

Attention!

Do not use 6ch/9ch audio devices in Windows 10 1903 virtual machines. It creates awful stuttering and performance loss. Use ac97 audio devices instead.

Troubleshooting

If the sound distortions occur, make sure host and guest run at the same sample rate. You can also play around with QEMU_PA_SAMPLES and QEMU_AUDIO_TIMER_PERIOD values (see the reddit post(s) from the sources for further information).

Option 3 – use Hardware

(+) Very easy
(-) Costs money
I haven’t tried this, but it should be easily possible to add a USB sound card to the guest and run the output back into your host sound card via a real audio wire (connecting guest line-out with host line-in).

Updates:

  • 2020.06.24 …. added information for QEMU version 4.2
  • 2018.02.17 …. initial creation

Sources:

The glorious arch-wiki

Users spheeniks reddit post

Reddit post for audio problem with QEMU 4.2 and bigger

7 Comment

  1. […] After some nights without sleep, I wrote an separate article on that matter. […]

  2. Kevinesan Pillay says: Reply

    Cheers mate, worked like a charm!

    1. Mathias Hueber says: Reply

      glad it helps 🙂

  3. […] Pulseaudio passthrough […]

  4. dz0rg says: Reply

    Thank you for this tutorial, I finally understood why sometimes I had the sound of my VM with my headphones.

  5. voider1 says: Reply

    I’m having a problem where when I use Discord and play a game, the mic stops working and sometimes the audio too, and I have to rejoin the call. Any idea how to fix this?

    1. Mathias Hueber says: Reply

      Do you use discord on the host, or on the guest?
      I use discord on the host with occasional app crashes, but I don’t think they are VFIO related.

Leave a Reply