This repository has been archived on 2022-01-09. You can view files and clone it, but cannot push or open issues/pull-requests.
liblast/Audio/SoundPlayer.gd

103 lines
2.8 KiB
GDScript

extends Node3D
# 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