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
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.
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.
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 viavirsh 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 viavirsh 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.
</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>
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:
Reddit post for audio problem with QEMU 4.2 and bigger
AMD Ryzen based passthrough setup between (X)Ubuntu 16.04 and Windows 10 - www.MathiasHueber.com
[…] After some nights without sleep, I wrote an separate article on that matter. […]
Kevinesan Pillay
Cheers mate, worked like a charm!
Mathias Hueber
glad it helps 🙂
Passthrough Nvidia to Linux VM – Oren Bell
[…] Pulseaudio passthrough […]
dz0rg
Thank you for this tutorial, I finally understood why sometimes I had the sound of my VM with my headphones.
voider1
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?
Mathias Hueber
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.
Vlad
Hi Mathias,
I just wanted to thank you for your tutorial, it helped so much setting up my passthrough setup so I can finally make the switch to Linux full time. That’s it, you rock 🙂
Mathias Hueber
Thank you for the kind words, means a lot. The whole idea is to pave the way for people to switch to Linux.
Guten Rutsch :)!
Jonathan Rubnstein
Hey! I think you should add in /etc/libvirt/qemu.conf to uncomment nographics_allow_host_audio=1, if the audio still doesn’t work.
txirrindulari
Thank you so much. This works for me.
Add /etc/libvirt/qemu.conf to uncomment nographics_allow_host_audio=1
Then let the graphics console opened in the virtual machine manager as if you were using graphics outoput from the virtual machine running. As soon as you close it audio is lost again. Keep it open.
上手 Linux 原生的虚拟机工具 QEMU/KVM | 水景一页
[…] 关于声音配置,这里有较为详细的说明。但是实际上,随着 QEMU 4.2 的发布,这个声音的的配置就简单多了。可以参考 Archlinux 上的说明来操作。 […]
Carrie
I was having trouble getting my VM’s audio to work with PulseAudio (following the Arch wiki guide), but this did the trick! Thanks!
Andrej Podzimek
Your pulseaudio method appears to be rather complex. I’ve found a oneliner modification to the XML generated by default by virt-manager (at least for my FreeBSD VM and ArchLinux host) that gets pulseaudio working.
So, my very first configuration used to be:
This^^^ was not necessarily for “4.1 and below”; it actually worked until 5.2.x and the legacy support for these environment variables got ultimately dropped in 6.0. Which brought me to your blogpost. 😉
For the record, your solution worked fine for me. It gave me audio on FreeBSD in KDE:
However, this^^^ low-level configuration does *not* resemble the audio devices configured by default by virt-manager, which is quite confusing, because it doesn’t appear in the left configuration bar in virt-manager etc.
So ultimately my solution was to create a “default” ICH9 audio card in virt-manager, which translates into something like this:
Now this^^^ won’t work by default, presumably, because sound goes to nowhere. But it suffices to replace the element with this:
There. That makes audio work. One can (presumably) set the ID to something else (instead of the default), say 7, and then set inside . But with just one sound card the default is the shortest option.
Here’s the trick in /etc/pulse/default.pa:
load-module module-native-protocol-unix auth-group=kvm socket=/tmp/pulse-socket-for-freebsd-on-kvm
The last bit of the puzzle is that my qemu runs under the kvm group.
Andrej Podzimek
Gah. Something is wrong with CSS or whatnot on this page. My XML snippets are escaped correctly in thes sources, but hidden from sight.
Anyway, here’s my response: https://pastebin.com/UUU4XGrr
Mathias Hueber
Thank you Andrej, I will give this a try and update the article.
Sorry for the code snipped inconvenience, I think that is a WordPress security measure. I have to check it well 🙂
Well, thank
jbernardo
Thanks! I was going crazy trying to get sound out of my passthrough windows 10 VM (another thing you helped a lot with) and option 2 worked quite well, after removing the ich9 device I had added to the VM config by mistake… 🙂
Francisco
Thanks a lot. Thanks to this post i could finally make my Windows 10 VM work with sound.
My config:
Core i5-4570 / Mother ASUS H87-PRO
Debian 12.1
QEMU 7.2
Libvirt 9.0
pulseaudio 16.1
Win 10 xml:
For some reason i had to omit the field bus. Instead of:
i needed to write this line:
Qemu always show a message saying that it could not find the Bus “xxx”, where xxx is the bus. I tried pcie.0, pcie.1, pcie, pci, PCI, and none worked. Omitting the field works fine.
Dejan
Thanks a lot for this! It worked perfectly for me on my Window$ VM in Kubuntu. Have been trying to resolve this for a while but not worked. Except your instructions.