stick-the-quick/audio/AudioFader.gd

74 lines
2.3 KiB
GDScript

class_name AudioFader extends Node
## Controls an AudioStreamPlayer and allows for fading and crossfading.
## Audio fade-out target.
const AUDIO_FADE_MIN_VOLUME: float = -20.0
## Default audio transition time.
const DEFAULT_AUDIO_FADE: float = 1.0
## Audio bus.
@export var bus: StringName
## Current AudioStreamPlayer.
var player: AudioStreamPlayer = null
## Current TweenChannel.
var tween_channel: TweenChannel = null
## Creates an initial AudioStreamPlayer child and TweenChannel.
func _ready() -> void:
_create_members()
## Creates an AudioStreamPlayer child and TweenChannel.
func _create_members() -> void:
player = AudioStreamPlayer.new()
add_child(player)
tween_channel = TweenChannel.make_replacing()
## Fades in the current audio player.
func fade_in(stream: AudioStream, fade: float = DEFAULT_AUDIO_FADE) -> void:
await fade_out()
player.volume_db = AUDIO_FADE_MIN_VOLUME
player.stream = stream
player.play()
var tween := await tween_channel.create_tween(player)
tween.tween_property(player, ^'volume_db', 0.0, fade)
await tween_channel.sync(tween)
## Fades out an arbitrary audio player on an arbitrary tween channel.
static func _fade_out_foreign(
p_player: AudioStreamPlayer,
p_tween_channel: TweenChannel,
fade: float = DEFAULT_AUDIO_FADE
) -> void:
if p_player.volume_db > AUDIO_FADE_MIN_VOLUME:
var tween := await p_tween_channel.create_tween(p_player)
tween.tween_property(
p_player, ^'volume_db', AUDIO_FADE_MIN_VOLUME, fade
)
await p_tween_channel.sync(tween)
p_player.stop()
## Fades out the current audio player.
func fade_out(fade: float = DEFAULT_AUDIO_FADE) -> void:
await AudioFader._fade_out_foreign(player, tween_channel, fade)
## Plays audio without fading in.
func play(stream: AudioStream) -> void:
await player.fade_out()
player.volume_db = 0.0
player.stream = stream
player.play()
## Fades out old audio and fades in new audio at the same time.
func crossfade(stream: AudioStream, fade: float = DEFAULT_AUDIO_FADE) -> void:
var old_player := player
var old_tween_channel := tween_channel
var thunk := func() -> void:
await AudioFader._fade_out_foreign(old_player, old_tween_channel, fade)
old_player.queue_free()
_create_members()
await Wait.until(player.is_node_ready)
var task := Task.new(thunk)
await fade_in(stream, fade)
await task.sync()