135 lines
4.1 KiB
GDScript
135 lines
4.1 KiB
GDScript
extends Node
|
|
|
|
## AudioManager Singleton
|
|
## Zentrale Audio-Analyse für alle Lichteffekte
|
|
## Verhindert mehrfache Spectrum-Analyzer-Aufrufe pro Frame
|
|
|
|
# Frequenzbereiche
|
|
const BASS_RANGE = Vector2(20, 250)
|
|
const MID_RANGE = Vector2(250, 2000)
|
|
const HIGH_RANGE = Vector2(2000, 20000)
|
|
|
|
# Interner State
|
|
var audio_player: AudioStreamPlayer3D
|
|
var audio_spectrum: AudioEffectSpectrumAnalyzerInstance
|
|
var is_setup: bool = false
|
|
|
|
# Cache für Magnitude-Werte (wird einmal pro Frame berechnet)
|
|
var _magnitude_cache: Array[float] = [0.0, 0.0, 0.0, 0.0] # [Bass, Mid, High, All]
|
|
var _last_frame: int = -1
|
|
|
|
func _ready():
|
|
print("AudioManager: Singleton initialisiert")
|
|
|
|
## Setup mit AudioStreamPlayer3D
|
|
func setup(player: AudioStreamPlayer3D) -> bool:
|
|
if is_setup and audio_player == player:
|
|
return true # Bereits korrekt eingerichtet
|
|
|
|
audio_player = player
|
|
|
|
if not audio_player:
|
|
push_error("AudioManager: Kein AudioStreamPlayer3D übergeben!")
|
|
return false
|
|
|
|
# Setup Spectrum Analyzer
|
|
var bus_index = AudioServer.get_bus_index(audio_player.bus)
|
|
var has_spectrum = false
|
|
|
|
# Prüfe, ob bereits ein Spectrum Analyzer vorhanden ist
|
|
for i in range(AudioServer.get_bus_effect_count(bus_index)):
|
|
if AudioServer.get_bus_effect(bus_index, i) is AudioEffectSpectrumAnalyzer:
|
|
has_spectrum = true
|
|
break
|
|
|
|
# Falls nicht, füge einen hinzu
|
|
if not has_spectrum:
|
|
var spectrum = AudioEffectSpectrumAnalyzer.new()
|
|
AudioServer.add_bus_effect(bus_index, spectrum)
|
|
print("AudioManager: Spectrum Analyzer hinzugefügt zu Bus '%s'" % audio_player.bus)
|
|
|
|
# Hole die Instanz
|
|
for i in range(AudioServer.get_bus_effect_count(bus_index)):
|
|
var effect = AudioServer.get_bus_effect(bus_index, i)
|
|
if effect is AudioEffectSpectrumAnalyzer:
|
|
audio_spectrum = AudioServer.get_bus_effect_instance(bus_index, i)
|
|
break
|
|
|
|
if not audio_spectrum:
|
|
push_error("AudioManager: Konnte Spectrum Analyzer Instanz nicht holen!")
|
|
return false
|
|
|
|
is_setup = true
|
|
print("AudioManager: Erfolgreich eingerichtet mit Bus '%s'" % audio_player.bus)
|
|
return true
|
|
|
|
## Prüft, ob Audio gerade abgespielt wird
|
|
func is_playing() -> bool:
|
|
return is_setup and audio_player and audio_player.playing
|
|
|
|
## Gibt ROHE Magnitude für Frequenzbereich zurück (ohne Verarbeitung)
|
|
## freq_range: 0=Bass, 1=Mitten, 2=Höhen, 3=Alle
|
|
func get_raw_magnitude(freq_range: int) -> float:
|
|
if not is_setup or not audio_spectrum:
|
|
return 0.0
|
|
|
|
_update_cache_if_needed()
|
|
return _magnitude_cache[clamp(freq_range, 0, 3)]
|
|
|
|
## Optional: Gibt Magnitude mit Standard-Verarbeitung zurück
|
|
func get_magnitude(freq_range: int, sensitivity: float = 1.0) -> float:
|
|
var raw = get_raw_magnitude(freq_range)
|
|
return clamp(raw * sensitivity, 0.0, 1.0)
|
|
|
|
## Interner Cache-Update (nur einmal pro Frame)
|
|
func _update_cache_if_needed():
|
|
var current_frame = Engine.get_process_frames()
|
|
|
|
# Bereits in diesem Frame berechnet?
|
|
if _last_frame == current_frame:
|
|
return
|
|
|
|
_last_frame = current_frame
|
|
|
|
# Berechne alle Frequenzbereiche
|
|
if not audio_player.playing:
|
|
_magnitude_cache = [0.0, 0.0, 0.0, 0.0]
|
|
return
|
|
|
|
_magnitude_cache[0] = _get_magnitude_for_range(BASS_RANGE) # Bass
|
|
_magnitude_cache[1] = _get_magnitude_for_range(MID_RANGE) # Mitten
|
|
_magnitude_cache[2] = _get_magnitude_for_range(HIGH_RANGE) # Höhen
|
|
_magnitude_cache[3] = (_magnitude_cache[0] + _magnitude_cache[1] + _magnitude_cache[2]) / 3.0 # Alle
|
|
|
|
## Berechnet Magnitude für einen Frequenzbereich
|
|
func _get_magnitude_for_range(freq_range: Vector2) -> float:
|
|
if not audio_spectrum:
|
|
return 0.0
|
|
|
|
var from_hz = freq_range.x
|
|
var to_hz = freq_range.y
|
|
var magnitude_sum = 0.0
|
|
var sample_count = 0
|
|
|
|
# Sample alle 100Hz im Bereich
|
|
for hz in range(int(from_hz), int(to_hz), 100):
|
|
var magnitude = audio_spectrum.get_magnitude_for_frequency_range(hz, hz + 100)
|
|
magnitude_sum += magnitude.length()
|
|
sample_count += 1
|
|
|
|
if sample_count > 0:
|
|
return magnitude_sum / sample_count
|
|
return 0.0
|
|
|
|
## Debug-Info
|
|
func get_debug_info() -> Dictionary:
|
|
return {
|
|
"is_setup": is_setup,
|
|
"is_playing": is_playing(),
|
|
"bass": _magnitude_cache[0],
|
|
"mid": _magnitude_cache[1],
|
|
"high": _magnitude_cache[2],
|
|
"all": _magnitude_cache[3],
|
|
"frame": _last_frame
|
|
}
|