Files
Ransom-s-wake/src/alarm_player.gd
T

72 lines
1.9 KiB
GDScript

class_name AlarmPlayer
extends AudioStreamPlayer
var _last_severity := 0
var _repeat_timer := 0.0
func update_alerts(delta: float, alerts: Array[int]) -> void:
var severity := 0
for alert in alerts:
severity = maxi(severity, alert)
_repeat_timer = maxf(0.0, _repeat_timer - delta)
if severity > _last_severity:
_play_alarm(severity)
_repeat_timer = _repeat_delay(severity)
elif severity >= SurvivalModel.AlertLevel.RETURN and _repeat_timer <= 0.0:
_play_alarm(severity)
_repeat_timer = _repeat_delay(severity)
_last_severity = severity
func reset() -> void:
_last_severity = 0
_repeat_timer = 0.0
stop()
func _repeat_delay(severity: int) -> float:
match severity:
SurvivalModel.AlertLevel.EMPTY:
return 0.75
SurvivalModel.AlertLevel.CRITICAL:
return 1.25
SurvivalModel.AlertLevel.RETURN:
return 2.5
SurvivalModel.AlertLevel.CAUTION:
return 5.0
_:
return 999.0
func _play_alarm(severity: int) -> void:
if severity <= SurvivalModel.AlertLevel.NORMAL:
return
var generator := AudioStreamGenerator.new()
generator.mix_rate = 22050.0
generator.buffer_length = 0.45
stream = generator
play()
var playback := get_stream_playback() as AudioStreamGeneratorPlayback
if playback == null:
return
var frequency := 520.0 + float(severity) * 110.0
var duration := 0.35
var frame_count := int(generator.mix_rate * duration)
var pulse_count := 1 if severity == SurvivalModel.AlertLevel.CAUTION else 2
if severity >= SurvivalModel.AlertLevel.CRITICAL:
pulse_count = 3
for frame_index in frame_count:
var time := float(frame_index) / generator.mix_rate
var phase_in_pulse := fmod(time * float(pulse_count), duration) / duration
var gate := 1.0 if phase_in_pulse < 0.62 else 0.0
var envelope := minf(time * 30.0, 1.0) * minf((duration - time) * 30.0, 1.0)
var sample := sin(TAU * frequency * time) * 0.16 * gate * envelope
playback.push_frame(Vector2(sample, sample))