I am trying to do audio panning in Godot using AudioEffectPanner
and when I update the pan
of it the volume levels are updated right away, resulting in an audible pop.
I am calculating the target pan value in _process()
, but even when smoothing it is quite noticeable.
I tried to move the smoothing to _physics_process()
, tried to update the Physics FPS
to a high value (200 FPS) but apparently it is only called more times before _process()
is called (tested with timestamps, got the calls in groups).
I tried to set up a Timer
as well as a last resort but it is also evaluated before the _process()
is called.
So any of the methods I tried result in updating at a maximum of 60 times per seconds (my display's update rate, it will vary on player's setups).
Is there a way in Godot to have a timer with greater resolution? Or even just having a separate thread in a loop of just updating the volume and sleeping? Maybe there is a method to update the AudioEffectPanner
and it will take care of smoothing it out?
(I am currently using Godot 3.5 and in the middle of a game jam, I will switch to 4.x for my next project.)
Timer
s only run on the engine's proccess cycles as you have seen. However with OS.delay_msec()
/OS.delay_usec()
you can make a thread that calls your function at faster intervals.
Note: this is likely still not 100% accurate to the desired time as it is still limited by the CPU. Additionally it will also deviate more the longer your processing function takes.
Sample Script:
extends Node
var thread: Thread
var quitting := false
func _ready() -> void:
thread = Thread.new()
thread.start(self, "thread_func", null, Thread.PRIORITY_HIGH)
func stop_thread() -> void:
# Setting quitting to true stops the thread,
# prevents a dead lock when cleaning up the thread
quitting = true
thread.wait_to_finish()
func do_thing() -> void:
print(OS.get_system_time_msecs())
func thread_func(args = null) -> void:
while not quitting:
OS.delay_usec(1000000/200)
do_thing()