103 lines
2.8 KiB
GDScript
103 lines
2.8 KiB
GDScript
extends Spatial
|
|
|
|
# This Scene is meant for playing back sound groups. For simple, singular sound effects use stock Godot nodes, this is meant to play a random sound among a group with variations.
|
|
|
|
const SFX_dir = "res://Assets/SFX/" # all sound clips must reside somewhere in this directory
|
|
|
|
onready var player = $AudioStreamPlayer3D # playback backend
|
|
|
|
export(String, FILE, "*-01.wav") var SoundClip = SFX_dir + "Test-01.wav"
|
|
export(bool) var AutoPlay = false
|
|
export(float) var MinimumRandomDistance = 0.35 # gives optimal playback repetition for sound clip groups of different sizes.
|
|
export(bool) var PlayUntilEnd = false # determines if the play() function is allowed to sop a previously started sound
|
|
export(float) var MinDelay = 0 # determines how many seconds must pass before the sound can be triggered again
|
|
export(float) var PitchScale = 1
|
|
export(float) var RandomizePitch = 0
|
|
var min_distance = 0 # this determines how ofte na sound is allowed to play (any Nth time) this is calculated automatically based on maximum_repetition
|
|
var clips = [] # holds loaded sound stream resources
|
|
var recently_played = [] # holds indexes of recently played
|
|
var ready = true # used as a semaphor for MinDelay
|
|
|
|
|
|
# Called when the node enters the scene tree for the first time.
|
|
func _ready():
|
|
var files = []
|
|
var dir = Directory.new()
|
|
dir.open(SFX_dir)
|
|
dir.list_dir_begin()
|
|
|
|
#print("SoundClip: ", SoundClip)
|
|
var group = SoundClip.left(SoundClip.find_last('-')).right(SoundClip.find_last('/') + 1)
|
|
#print("group: ", group)
|
|
|
|
while true:
|
|
var file = dir.get_next()
|
|
#print(file)
|
|
if file == "":
|
|
break
|
|
elif not file.begins_with(".") and file.begins_with(group) and file.ends_with(".wav"):
|
|
files.append(file)
|
|
|
|
dir.list_dir_end()
|
|
|
|
#print(files)
|
|
|
|
for f in files:
|
|
clips.append(load(SFX_dir + f))
|
|
|
|
min_distance = floor(len(clips) * MinimumRandomDistance)
|
|
|
|
#print ("Clips: ", len(clips))
|
|
#print ("min_distance: ", min_distance)
|
|
|
|
if AutoPlay:
|
|
play()
|
|
|
|
func pick_random():
|
|
return randi() % len(clips)
|
|
|
|
sync func play():
|
|
|
|
if PlayUntilEnd:
|
|
if player.playing:
|
|
return 1
|
|
|
|
if MinDelay > 0:
|
|
if not ready:
|
|
return 2
|
|
|
|
var i = pick_random()
|
|
|
|
while recently_played.has(i):
|
|
i = pick_random()
|
|
|
|
#print("i: ", i)
|
|
|
|
recently_played.append(i)
|
|
|
|
if len(recently_played) > min_distance:
|
|
recently_played.remove(0)
|
|
|
|
#print("recently played: ", recently_played)
|
|
|
|
player.stream = clips[i]
|
|
|
|
if RandomizePitch != 0:
|
|
player.pitch_scale = PitchScale + rand_range(-RandomizePitch /2, RandomizePitch/2)
|
|
else:
|
|
player.pitch_scale = PitchScale
|
|
|
|
player.play()
|
|
|
|
ready = false
|
|
|
|
yield(get_tree().create_timer(MinDelay), "timeout")
|
|
|
|
ready = true
|
|
|
|
# TODO implement final randomization algorithm
|
|
|
|
# Called every frame. 'delta' is the elapsed time since the previous frame.
|
|
#func _process(delta):
|
|
# pass
|