How can I smooth out my looped sound

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By MisterAcoustic

Hello - I’m attempting to loop a sound when a key is pressed, and stop it when the key is released. Works well - with one exception. When the audio is looping, it doesn’t make a smooth transition to the next iteration of the loop. This is not a problem with the sound - it’s quite constant, and should loop smoothly.

I use code similar to what’s shown in the FPS Tutorial Part 6 in the docs. There is a function handling the ‘finished’

audio_node.connect("finished", self, "sound_finished")

and

func sound_finished():
	if should_loop:
		audio_node.play(0.3)
	else:
		audio_node.stop()
		queue_free()

Note that I do use a value in the .play function - the sound does have a slight difference at the beginning that I want to avoid when it loops. I’ve changed the value, but there are always artifacts when the sound loops.

When the sound loops, sometimes it seems to work perfectly (the sound is two seconds long). Other times, I get slight hesitations, popping or crackling at the loop transition point.

How can I get a smooth loop?

:bust_in_silhouette: Reply From: Zylann

So if I understand correctly, you have a single sound with 0.3 seconds of samples to play only the first time, and a following section of samples until the end where it should loop?

First of all, you won’t get a smooth loop by just triggering play again from code that runs at a different rate than the audio thread. Audio runs at 44100 Hz, _process and signals barely react at 60 Hz, the result will be out of sync.
Secondly, if you were able to loop the sound at exactly 0.3 seconds in this way, you would need to make sure at sample level that the exact sample at 0.3 has the same value as the last sample of the sound. The greater the difference, the greater the chance of causing a “click”.

Something you can try first, which I never tested yet, is to make your sound loop in the import settings, and change Loop Begin to not be zero. Instead, set it to the sample index that matches 0.3 seconds (unfortunately Godot doesnt do the conversion for you, probably because floats would not be precise?). If my guess is correct, Godot will then play the sound and loop the section from 0.3 seconds onwards.

If that does not work, what I can suggest is either code a much elaborated playing behavior where you use two players at once to simulate a short cross-fade of volume between loops, in the attempt of smoothing out the repetition.
A variant of this would be to split your sound in two, and make the second one loop in the import settings. Make the first part fade out, and a bit before it ends, start the loop one with a fade too so both will cross-fade.

Zylann - thanks for your answer, and all the great work you do for godot.

I had not originally imported the sound with loop enabled. I did that, and took out my manual re-starting of the sound, and it sounds great! (the sound is almost white noise, so the loop point wouldn’t make any difference - I only thought it was a little different at the beginning, but I was wrong).

It took me a long time to find the Loop Begin/Loop End settings (even though I didn’t need them) - I’m new at this, and the inspector doesn’t appear if you only select the sound in the FileSystem tree - you have to double-click.

MisterAcoustic | 2020-05-15 17:19