godot-docs
godot-docs copied to clipboard
There's no doc about playing a lot of audios at same time.
Your Godot version: 3.2.4 RC1
Issue description: Altought the docs talk about how WAV file format can play thousands of it without any performance issue, the docs doesnt says how this can be archieved, I finally manage to found a tutorial from a user who did it right, but that is not begginer friendly and I couldnt understand it well too.
Maybe there's a better approach? In any case this should be documented, playing a lot of sounds in a little space of time is not simple!
Source Content
https://www.youtube.com/watch?v=DsAIrA9UE4E https://www.youtube.com/watch?v=3CFWlQzMthY
Source Code
extends Node
var dic : Dictionary = {}
func play_sfx(audio_clip : AudioStream, priority : int = 0):
for child in $sfx.get_children():
if child.playing == false:
child.stream = audio_clip
child.play()
dic[child.name] = priority
break
if child.get_index() == $sfx.get_child_count() - 1:
var priority_player = check_priority_and_find_oldest(dic, priority) #finds player with same/lowest priority and oldest player
if priority_player != null:
$sfx.get_node(priority_player).stream = audio_clip
$sfx.get_node(priority_player).play()
else:
print("priority player is null")
pass
#playes at most 3 sounds at the same time, in a lot of cases bad, because you get less sound feedback.
#execept when you want to restrict the amount of sounds, for example crashes/destructions/debris
func check_priority(_dic : Dictionary, _priority):
var prio_list : Array = []
for key in _dic:
if _priority > _dic[key]:
prio_list.append(key)#append key(sfx_player.name) to the array
#get the lowest priority from prio_list
var last_prio = null
for key in prio_list:
if last_prio == null:
last_prio = key
continue
if _dic[key] < _dic[last_prio]:
last_prio = key
return last_prio
pass
#playes new sounds all the time, bad if you have important sound, wich you liked to play
func find_oldest_player():
var last_child = null
for child in $sfx.get_children():
if last_child == null:
last_child = child
continue
#find player wich played the longest
if child.get_playback_position() > last_child.get_playback_position():
last_child = child
return last_child.name
pass
#good for all types of situations, important sound get played most of the time and sounds doesn't get get
#swallowed up most of the time
func check_priority_and_find_oldest(_dic, _priority): #1,3,1 == 1
var prio_list : Array = []
for key in _dic:
if _priority >= _dic[key]:
prio_list.append(key) #append key(sfx_player.name) with same/lower priority to an array
#find oldest
if prio_list.empty():
return null
var oldest_player = prio_list[0]
for i in range(1, prio_list.size() -1):
if $sfx.get_node(oldest_player).get_playback_position() < $sfx.get_node(prio_list[i]).get_playback_position():
oldest_player = prio_list[i]
return oldest_player
pass
###### Here is a little coding challenge #######
#func lowest_priority_and_oldest(_dic, _priority):
#make prio_list
#append same/lower priority to prio_list
#get the lowest priority
#get all player with the same lowest priority
#if there is more then 1 player
#get the oldest player from the lowest priority players
func play_music(music_clip : AudioStream):
$music/music_player.stream = music_clip
$music/music_player.play()
pass
Here's what I use: https://github.com/Calinou/escape-space/blob/c151b264c622fcd823a2c43855b2a6f2d8bbe68f/autoload/sound.gd
To be fair, I think this should be solved at the core level by readding polyphony support.
@Calinou This one lets me play a lot of audios in short time? Also makes sense to be a core issue, in all my projects I had problem with audio! but until there a doc to at least give a north to people out there!
This one lets me play a lot of audios in short time?
Yes :slightly_smiling_face:
thank you very much!
@Calinou made a C# version of it, worked flawlessly thank you again!
using Godot;
using System;
public static class OSTManager
{
public static void PlaySFX(Node target, AudioStream stream, Vector2 position, float pitchScale = 1.0f) {
AudioStreamPlayer2D sfx = new AudioStreamPlayer2D();
target.GetTree().CurrentScene.AddChild(sfx);
if (position != null) sfx.GlobalPosition = position;
sfx.Stream = stream;
sfx.VolumeDb = 0;
sfx.PitchScale = pitchScale;
sfx.Play();
sfx.Connect("finished",sfx,"queue_free");
}
public static void PlaySFXPitched(Node target, AudioStream stream, Vector2 position) {
RandomNumberGenerator rng = new RandomNumberGenerator();
PlaySFX(target,stream,position,rng.RandfRange(.9f,1.7f));
}
}
4.0alpha has built-in polyphony support, but it can't be backported to 3.x since it relies on different AudioServer internals. I suppose this still needs to be documented on the manual page that mentions playing sounds in general.
https://github.com/Calinou/escape-space/blob/c151b264c622fcd823a2c43855b2a6f2d8bbe68f/autoload/sound.gd is short enough to include inline on the page, but we could also link to a maintained add-on in the asset library.
yeah thats the perfect solution!