Skip to content

AudioServer::get_output_latency() and audio "output latency" setting are inaccurate #38215

Open
@benjarmstrong

Description

@benjarmstrong

Godot version: 4.0, 3.X (possibly 2.X, haven't checked)
OS/device including version: All
Issue description:
AudioServer::init() contains this line of code:
buffer_size = 1024; //hardcoded for now
As a result mixing is always performed at this fixed buffer size. This is problematic because it enforces a minimum of 1024 frames of audio delay. At the default engine settings (15 MS audio output latency and 44100Hz mix rate) this is approximately 23 MS (1000 * 1024 / 44100).

On a related note I believe this would adversely affect the performance of the audio server when the audio driver is running at any buffer size that isn't 1024, since audio callbacks need to remain relatively predictable in their performance to remain avoid buffer underruns and remain glitch-free. For example at a driver buffer length of 256:

  • AudioDriver outputs 256 frames; AudioServer mixes 1024 frames and gives 256 to AudioDriver
  • AudioDriver outputs 256 from last remaining AudioServer mix frames
  • AudioDriver outputs 256 from last remaining AudioServer mix frames
  • AudioDriver outputs 256 from last remaining AudioServer mix frames
  • AudioDriver outputs 256 frames; AudioServer mixes 1024 frames and gives 256 to AudioDriver
  • AudioDriver outputs 256 from last remaining AudioServer mix frames
  • AudioDriver outputs 256 from last remaining AudioServer mix frames
  • AudioDriver outputs 256 from last remaining AudioServer mix frames
  • etc.

As a result glitches are much more likely on the frames that mixing occurs rather than the frames being distributed evenly among every driver output.

Steps to reproduce:
Testing inaccuracies in audio delay can be difficult for small values but be easily observed at larger values. The issue can be observed easily by changing a line of code in AudioServer::init() from
buffer_size = 1024; //hardcoded for now
to
buffer_size = 44100; //hardcoded for now
and compiling. At a mix rate of 44100 (the default) there will be about 1 second of audio output latency. Likewise this number can be lowered and latency is reduced. AudioServer::get_output_latency() will return the same value in all cases (unless the audio driver configuration has changed).

Minimal reproduction project:
Follow the steps to reproduce, create a new project and add this script to an AudioStreamPlayer:
extends AudioStreamPlayer func _ready(): print("Output latency = ", AudioServer.get_output_latency()) func _input(event): if event.is_action_pressed("ui_accept"): playing = true
Run the project and the delay can be audibly observed by pressing space.

Potential fix:
Rather than hardcoding a buffer size of 1024, this could be implemented as a virtual AudioDriver::get_buffer_size() method to inform the audio server on how big to make the buffers. This would also keep the driver and server in sync potentially leading to better performance, but would require changes to audio drivers to implement it. A fallback mixing buffer size of 1024 could be implemented for the AudioServer in the event that the active driver doesn't implement this method, allowing it to be introduced incrementally to audio drivers.

I currently require low latency audio for a project I'm working on and will most likely be implementing this in the near future. I'll update this issue with a PR when I'm done.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions