[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[vfio-users] Random find for the day ... audio workaround.



I'd think this was off topic, but it seems to get mentioned every few days and I accidentally fixed it to the greater extent by randomly doing something else. The way the bug turned up it was bloody obvious and so here's a workaround that ought to work for most, that should be reasonably robust, takes no patching and no HDMI switching and is the first bug I've ever seen actively commit suicide.

The crackling seems to come from two sources so obvious they are in my syslog - when the regular poll triggers too early or too late and the alsa driver attempts to read data but finds nothing or alternatively when it loses some data out of the beginning of the buffer. Ticks tend to queue up and not arrive sometimes as the context switch is not real time and as the real data events have spin locks which jam up the fast timekeeping poll and processes are all migrating cores because they're delayed. Reducing jitter or increasing ticks will only reduce problem magnitude whilst making it more frequent. The trick is to use a much longer tick and to center it properly on alsa's own hyperactive polling tick. For example .. using my 4.6 kernel:

First we need our clock tick which is blessedly easy to find if you look in /proc. It can be many different things usually based on your sample frequency and so you should look there if my generic 44.1khz setting below doesn't fit.

more /proc/asound/timers
G0: system timer : 3333.333us (10000000 ticks)
P0-0-0: PCM playback 0-0-0 : SLAVE

I have a 3333.333us tick so it ticks roughly 300 times (1e06/3333.333) a second which means when I randomly picked a tick rate of 50 to try and see if alsa was giving me interrupt problems I found I had well behaved audio despite my interrupt problems. I used the QEMU settings as below .. passing through intel audio with a mixed mic/headphone codec (or whatever else you prefer). If you use my settings it should just work .... but you may need to check the clock you use is reliable:

export QEMU_AUDIO_DRV=alsa QEMU_ALSA_DAC_SIZE_IN_USEC=0 QEMU_ALSA_DAC_BUFFER_SIZE=1024 QEMU_ALSA_DAC_PERIOD_SIZE=256
export QEMU_ALSA_ADC_SIZE_IN_USEC=0 QEMU_ALSA_ADC_BUFFER_SIZE=1024 QEMU_ALSA_ADC_PERIOD_SIZE=256
export QEMU_AUDIO_DAC_FIXED_SETTINGS=1
export QEMU_AUDIO_DAC_FIXED_FREQ=44100 QEMU_AUDIO_DAC_FIXED_FMT=S16 QEMU_AUDIO_ADC_FIXED_FREQ=44100 QEMU_AUDIO_ADC_FIXED_FMT=S16
export QEMU_AUDIO_DAC_TRY_POLL=1 QEMU_AUDIO_ADC_TRY_POLL=1
export QEMU_AUDIO_TIMER_PERIOD=50


This works because qemu is sampling a sampling process so some zero or lost data are inevitable when sampling across boundaries and this gets more likely the faster you sample plus it probably starts to distorts alsa's own time keeping given it tends to run at very high priority on the same data and is pushing the errors in my syslog. The best solution is to use a much slower tick and a longer buffer so that alsa can catch up when necessary or have a syslog tantrum with enough data buffered to get over it. It's still a balancing act as the tick should be longer so as to minimise the risk it will fall off either side but not so long it makes for an unacceptable delay between cause and sound effect. Without centring it will likely crackle but a centred ratio of 6 is 100% flawless for me over 20 boots with sound in linux etc. etc. and should be reasonably robust if your CPU does fast context switching or you turn your local polling rate down from 1000 to 300 or 250. Importantly it should be much more reliable .. burns a lot less CPU and introduces a delay that will affect only those young enough to have "reaction times." (you do get warned about it in the log though)

It could be turned into a patch - but I wasn't going to spoil the purity of the experience by looking at actual code and as this mail represents the sum total of what I know about alsa and it's a cowboy solution it should be tested on varying hardware before being bolted onto qemu. You'll notice that it is mostly derived from one empirical sample point and prior experience of the youthful folly of trying to learn practical DSP from a maths book.

[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]