72 lines
1.9 KiB
GDScript
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))
|