Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct
How to minimise audio output latency?
ThomH last edited by
I'm porting an emulator to Qt. So I have programmatically-generated audio, and I want only a limited amount of forward buffering.
As a first attempt I tried push audio, grabbing a
QIODeviceand writing to it as and when data is available. I am testing under macOS and have called
setBufferSizewith a small number before calling start (though I'm suspicious that it doesn't work; see below), but latency is still noticeably dreadful. I had the idea that maybe I'm allowing too much audio to become buffered during initial startup, but there's no obvious way to determine how much data is currently buffered so there's no way to compensate for that at runtime.
So I switched to implementing my own
QIODeviceand using the
QAudioOutputpull interface. I figured that gives me sufficient control to avoid over-buffering. But then the interface appears to act illogically. In my specific case, I call
setBufferSizewith a value of
1024. I then start the output. I query
bufferSize()and get a value of
2048. Fine, not great, but fine. Except that the buffer size appears to have no bearing on the
QIODevicecalls — the
QAudioOutputalways requests buffers in 16384-byte chunks despite the buffer size being 2048.
I guess this cuts to the documentation offering no definition for what the buffer size actually means, but I definitely can't come up with any meaningful interpretation in which a buffer which advertises itself as being 2048 bytes would then attempt to read data in 16384-byte chunks.
As an aside, my machine's output rate is 48,000 Hz and as a result that's the output rate I'm requesting (via
QAudioDeviceInfo::defaultOutputDevice().preferredFormat(), but manually verified as being 48,000 on my particular machine). Given that I'm requesting 16-bit audio, 1/6th of a second's latency could well be what I'm hearing, though it feels a lot longer.
- what does the buffer size actually mean, given that a value of 2048 is reported by an audio output that pulls data in 16384-byte chunks?
- is there something I'm supposed to do other than call
setBufferSizeto request the lowest latency that Qt can provide?
As an aside, the native macOS version of this app works without disturbance with buffers as small as 512 bytes. So I don't think that either my machine or my OS is causing a problem.
Also, I'm aware that using some other library for the relatively specialised purpose of low-latency audio wouldn't necessarily be a bad idea, but I also want a working pure-Qt build, that does the best that Qt can do.
Bonnie last edited by Bonnie
Hello, I've just looked into that problem not long time ago.
The key point is, when opening the io device, remember to add
OpenMode, or it will always ask at least 16384 bytes, which is hardcoded in
#ifndef QIODEVICE_BUFFERSIZE #define QIODEVICE_BUFFERSIZE 16384 #endif
ThomH last edited by
That seems to make the QAudioOutput act much closer to what I'd expect given its
bufferSize(); it still announces a size of 2048 but now seems primarily to read in 1024-byte increments.
It's a shame that there isn't an exact meaning of buffer size — empirically on macOS I guess it's a ring buffer that is filled half at a time — but I guess if I take it to be 'the maximum amount that may be read at a time' then I have more than enough information to obtain that minimum available latency, and provide the absolute best plain-Qt experience that I can.
Pablo J. Rogina last edited by
@ThomH could your issue be called as solved? Thanks.