Return to Level1Techs.com

QEMU Native JACK Audio Support

Over the last few days, I have been working on a jack audiodev for Qemu which I have just submitted upstream. In my testing, this fixes all stuttering/desync audio issues with all emulated Qemu audio devices in Windows and Linux.

As QEMU has introduced a new method of specifying the audiodev it’s now very simple to use this.

For example, an Intel HDA ICH9 device:

  -audiodev jack,id=ad0 \
  -device ich9-intel-hda \
  -device hda-duplex,audiodev=ad0

The audio dev accepts some additional parameters:

parameter type default description
server-name string “default” The JACK server instance to connect to
client-name string the VM’s name The client name to use in JACK. This will have “out-” or “in-” prepended to it automatically based on the audio direction.
connect-ports regex If specified, automatically connect to ports matching the supplied regular expression
start-server boolean false Set to true to autostart a jack instance if one is not present.
exact-name boolean false Use the exact client name requested otherwise JACK generates a unique one, if needed.

For example:

  -audiodev jack,id=ad0,in.client-name=Windows,out.client-name=Windows

Note, for best performance the jack client thread needs realtime priority and will attempt to obtain it if possible, however, the QEMU -runas can interfere with this. The requirements to make this work has been left as an exercise to the user (personally I just run Qemu as root :stuck_out_tongue: )

Enjoy and have fun :smiley:

EDIT: Updated link to version 4 of the patch. Just cosmetic code changes, documentation changes, and parameters have gone from using underscores (_) to hyphens (-) as per the QEMU standard practice.

EDIT: New version 5 patch, adds the ability to auto-connect to ports based on a regular expression match, as well as recovery if the jack server is restarted.

EDIT: New version 6 patch, fixes incorrect transport logic, audio stop no longer stops the JACK transport.

NOTE: QEMU has an internal resampler that we need to use, it is enabled by default but it’s designed to only handle sample rates up to 65.35kHz, do not expect this to work well at anything higher. This is not a limitation of this JACK audio dev, but QEMU itself. As such jackd can not run at anything that exceeds this limit either. That said, the virtual audio devices are only 16-bit anyway, so if you are trying to get professional audio quality from QEMU then you need to go a different route (audio vfio passthrough) for now (I intend to correct this :slight_smile: )

7 Likes

Is there any recommended environment variable? Like setting up buffer size etc?

QEMU sound configuration via environment variables is deprecated as of Qemu 4.1.

Buffer sizes for Jack are configured at launch time on the Jackd server, not in the client. I am running a 128 buffer size with 2 periods. Note that this is very hardware dependent and you may have to play with the buffer size to find something suitable for your system.

There are heaps of guides on how to setup the jack server, so I will not go into it here, just do a little research :slight_smile:

I’m not getting any of the -audiodev parameters to work, namely:

qemu-system-x86_64: -audiodev jack,id=sound0,start-server=true: Parameter 'start-server' is unexpected

Am I missing something?

Please be sure you’re using version 4 of the patch, it has been linked above. RedHat’s convention is to use hyphens instead of underscores and this had to be adjusted which the latest version of the patch does, and what this information above references.

I’ve double confirmed I’m using the correct version. It extends to all parameters - none are recognized.

For reference, I’m building this against the 5.0.0 upstream release.

I am very sorry, I forgot that the settings are specified per in/out, ie.

-audiodev jack,id=sound0,out.start-server=true,in.start-server=true

1 Like

My VM setup fully migrated over to using JACK now. With the latest version of the patch (v5) it now supports auto connection to ports based on a regular expression match. It also watches for new port registrations and connects to them when they become available so that the load order doesn’t matter. And finally, it will recover if the audio server (jackd) is restarted, which neither PA or ALSA can do.

1 Like

Link to patch updated.

I just realized there is another very cool usage of this which I am now using also. I wanted to bring the Windows audio from my VM into my Linux VM as a seperate stream for recording and mixing. So I added another hda device to my Linux VM and set it to connect directly to the Windows output.

On the sufrace this seems obvious, but because JACK is configured to use shared memory, this means that this audio data is being shared directly between the two VMs via shared buffers. The latency of doing this should be far better then any DAC loopback type device could ever be.

Edit: actually thinking more, one could add another virtual audio device to the Windows guest as the non-default device, then tell your program to use it as the output device, avoiding windows ever mixing in audio from other sources, like system events/sounds, etc. This would ensure a clean recording no matter what is going on with the system.

2 Likes