+141
-1
@@ -11,7 +11,7 @@ extends Node
|
||||
# Voice 2 · Bass · Sawtooth (boss2: +detuneter 2. Layer für Schwebung)
|
||||
# Voice 3 · Schlagzeug · Hi-Hat+Kick+Snare (normal/boss1) ·
|
||||
# Kick+Floor-Tom+Mid-Tom+Reverse-Whoosh (boss2)
|
||||
# Voice 4 · Phase-2-Layer · Triangle 1 Oktave über Melodie (nur boss2 Phase 2)
|
||||
# Voice 4 · BH-Bass · Sine Sub-Bass, proximity-driven, beat-pulsed
|
||||
# ═══════════════════════════════════════════════════════════════════════════
|
||||
|
||||
@export var volume_db: float = -8.0
|
||||
@@ -249,6 +249,16 @@ var _bass_phase := 0.0
|
||||
# Bass-Zweit-Oszillator (nur boss_mode=2, detunet für Schwebung)
|
||||
var _bass2_phase := 0.0
|
||||
|
||||
# Voice 4: BH Proximity Sub-Bass
|
||||
var _v4_freq: float = 0.0
|
||||
var _v4_freq_cur: float = 0.0
|
||||
var _v4_gain: float = 0.0
|
||||
var _v4_phase: float = 0.0
|
||||
var _v4_is_smbh: bool = false
|
||||
|
||||
# Music event stingers (short pitched overlays)
|
||||
var _stingers: Array = []
|
||||
|
||||
# Globaler Zustand
|
||||
var _section := 0
|
||||
var _chord := 0
|
||||
@@ -284,6 +294,7 @@ func play() -> void:
|
||||
_arp_step = 0; _arp_pos = 0; _arp_phase = 0.0
|
||||
_bass_chord = -1; _bass_phase = 0.0; _bass2_phase = 0.0
|
||||
_sample_g = 0; _section = 0; _chord = 0
|
||||
_v4_gain = 0.0; _v4_freq = 0.0; _v4_freq_cur = 0.0; _v4_phase = 0.0; _v4_is_smbh = false; _stingers.clear()
|
||||
_playing = true
|
||||
_player.play()
|
||||
_playback = _player.get_stream_playback()
|
||||
@@ -297,6 +308,7 @@ func play_boss() -> void:
|
||||
_arp_step = 0; _arp_pos = 0; _arp_phase = 0.0
|
||||
_bass_chord = -1; _bass_phase = 0.0; _bass2_phase = 0.0
|
||||
_sample_g = 0; _section = 3; _chord = 0
|
||||
_v4_gain = 0.0; _v4_freq = 0.0; _v4_freq_cur = 0.0; _v4_phase = 0.0; _v4_is_smbh = false; _stingers.clear()
|
||||
if not _playing:
|
||||
_playing = true
|
||||
_player.play()
|
||||
@@ -313,6 +325,7 @@ func play_boss_leviathan(phase: int = 1) -> void:
|
||||
_arp_step = 0; _arp_pos = 0; _arp_phase = 0.0
|
||||
_bass_chord = -1; _bass_phase = 0.0; _bass2_phase = 0.0
|
||||
_sample_g = 0; _section = 3; _chord = 0
|
||||
_v4_gain = 0.0; _v4_freq = 0.0; _v4_freq_cur = 0.0; _v4_phase = 0.0; _v4_is_smbh = false; _stingers.clear()
|
||||
if not _playing:
|
||||
_playing = true
|
||||
_player.play()
|
||||
@@ -336,6 +349,7 @@ func play_normal() -> void:
|
||||
_arp_step = 0; _arp_pos = 0; _arp_phase = 0.0
|
||||
_bass_chord = -1; _bass_phase = 0.0; _bass2_phase = 0.0
|
||||
_sample_g = 0
|
||||
_v4_gain = 0.0; _v4_freq = 0.0; _v4_freq_cur = 0.0; _v4_phase = 0.0; _v4_is_smbh = false; _stingers.clear()
|
||||
_load_mel()
|
||||
|
||||
func stop_music() -> void:
|
||||
@@ -353,6 +367,83 @@ func set_muted(muted: bool) -> void:
|
||||
if idx != -1:
|
||||
AudioServer.set_bus_mute(idx, muted)
|
||||
|
||||
func set_bh_proximity(proximity: float, size_factor: float, is_smbh: bool) -> void:
|
||||
_v4_is_smbh = is_smbh
|
||||
var sf := minf(size_factor * 0.12, 0.55)
|
||||
_v4_gain = clamp(proximity * sf, 0.0, 0.50)
|
||||
_v4_freq = _get_v4_freq()
|
||||
|
||||
func _get_v4_freq() -> float:
|
||||
var root_freq: float
|
||||
match _boss_mode:
|
||||
2: root_freq = FREQ.get(BOSS2_BASS.get(_chord, "E2"), FREQ["E2"])
|
||||
1: root_freq = FREQ.get(BOSS_BASS.get(_chord, "A2"), FREQ["A2"])
|
||||
_: root_freq = FREQ.get(BASS.get(_chord, "A3"), FREQ["A3"])
|
||||
var base := maxf(30.0, root_freq * 0.25)
|
||||
if _v4_is_smbh:
|
||||
return maxf(22.0, base * 0.5)
|
||||
return base
|
||||
|
||||
func play_music_event(event_name: String) -> void:
|
||||
var root_hz: float = _bass_freq if _bass_freq > 0.0 else FREQ["A3"]
|
||||
match event_name:
|
||||
"bh_pulse":
|
||||
_stingers.append({"type": "sine", "phase": 0.0,
|
||||
"freq": root_hz * 0.25, "freq_end": root_hz * 0.125,
|
||||
"gain": 0.20, "pos": 0, "total": int(1.2 * SAMPLE_RATE),
|
||||
"attack": int(0.05 * SAMPLE_RATE)})
|
||||
"neutron_beam":
|
||||
_stingers.append({"type": "noise", "phase": 0.0,
|
||||
"freq": 0.0, "freq_end": 0.0,
|
||||
"gain": 0.14, "pos": 0, "total": int(0.07 * SAMPLE_RATE)})
|
||||
_stingers.append({"type": "sine", "phase": 0.0,
|
||||
"freq": root_hz * 8.0, "freq_end": root_hz * 4.0,
|
||||
"gain": 0.10, "pos": 0, "total": int(0.10 * SAMPLE_RATE)})
|
||||
"white_hole_eject":
|
||||
var arp_table: Dictionary
|
||||
match _boss_mode:
|
||||
2: arp_table = BOSS2_ARP
|
||||
1: arp_table = BOSS_ARP
|
||||
_: arp_table = ARP
|
||||
var chord_notes: Array = arp_table.get(_chord, ["A4", "C5", "E5"])
|
||||
for i in 3:
|
||||
var note_str: String = chord_notes[i] if i < chord_notes.size() else "A4"
|
||||
var note_hz: float = FREQ.get(note_str, root_hz * 2.0)
|
||||
_stingers.append({"type": "triangle", "phase": 0.0,
|
||||
"freq": note_hz, "freq_end": note_hz,
|
||||
"gain": 0.10 - i * 0.025,
|
||||
"pos": -int(i * 0.09 * SAMPLE_RATE),
|
||||
"total": int(0.28 * SAMPLE_RATE)})
|
||||
"quasar_jet":
|
||||
var base_hz := root_hz * 2.0
|
||||
var scale_mult := [1.0, 1.122, 1.260, 1.498]
|
||||
for i in 4:
|
||||
var note_hz: float = base_hz * float(scale_mult[i])
|
||||
_stingers.append({"type": "sine", "phase": 0.0,
|
||||
"freq": note_hz, "freq_end": note_hz * 1.04,
|
||||
"gain": 0.08 + i * 0.01,
|
||||
"pos": -int(i * 0.11 * SAMPLE_RATE),
|
||||
"total": int(0.18 * SAMPLE_RATE)})
|
||||
"galaxy_consumed":
|
||||
var swell_freqs: Array[float] = [root_hz * 0.5, root_hz * 0.75, root_hz]
|
||||
for i in 3:
|
||||
_stingers.append({"type": "sine", "phase": 0.0,
|
||||
"freq": swell_freqs[i], "freq_end": swell_freqs[i],
|
||||
"gain": 0.18 - i * 0.04, "pos": 0,
|
||||
"total": int(1.6 * SAMPLE_RATE),
|
||||
"attack": int(0.5 * SAMPLE_RATE)})
|
||||
"planet_captured":
|
||||
_stingers.append({"type": "noise", "phase": 0.0,
|
||||
"freq": 0.0, "freq_end": 0.0,
|
||||
"gain": 0.20, "pos": 0, "total": int(0.10 * SAMPLE_RATE)})
|
||||
_stingers.append({"type": "sine", "phase": 0.0,
|
||||
"freq": root_hz * 2.0, "freq_end": root_hz * 0.5,
|
||||
"gain": 0.18, "pos": 0, "total": int(0.45 * SAMPLE_RATE)})
|
||||
"comet_pass":
|
||||
_stingers.append({"type": "sine", "phase": 0.0,
|
||||
"freq": root_hz * 14.0, "freq_end": root_hz * 7.0,
|
||||
"gain": 0.06, "pos": 0, "total": int(0.16 * SAMPLE_RATE)})
|
||||
|
||||
# ── Hauptschleife ─────────────────────────────────────────────────────────
|
||||
func _process(_delta: float) -> void:
|
||||
if _playing:
|
||||
@@ -562,6 +653,54 @@ func _fill_buffer() -> void:
|
||||
var snare_env := 1.0 - float(snare_pos) / 340.0
|
||||
s += randf_range(-1.0, 1.0) * snare_env * 0.13
|
||||
|
||||
# Voice 4: BH Proximity Sub-Bass — sine, beat-pulsed, frequency glide
|
||||
var v4_glide := 0.9997
|
||||
_v4_freq_cur = _v4_freq_cur * v4_glide + _v4_freq * (1.0 - v4_glide)
|
||||
if _v4_gain > 0.004 and _v4_freq_cur > 0.0:
|
||||
var beat_samples_v4 := int(_cur_beat * SAMPLE_RATE)
|
||||
if beat_samples_v4 > 0:
|
||||
var beat_pos_v4 := _sample_g % beat_samples_v4
|
||||
var beat_t_v4 := float(beat_pos_v4) / float(beat_samples_v4)
|
||||
var beat_pulse_v4: float
|
||||
if beat_t_v4 < 0.06:
|
||||
beat_pulse_v4 = beat_t_v4 / 0.06
|
||||
else:
|
||||
beat_pulse_v4 = 1.0 - (beat_t_v4 - 0.06) / 0.94 * 0.55
|
||||
_v4_phase += _v4_freq_cur / SAMPLE_RATE
|
||||
s += sin(_v4_phase * TAU) * _v4_gain * (0.45 + 0.55 * beat_pulse_v4)
|
||||
|
||||
# Stingers: short pitched musical overlays for celestial events
|
||||
for st in _stingers:
|
||||
st["pos"] = int(st["pos"]) + 1
|
||||
var sp: int = int(st["pos"])
|
||||
if sp <= 0:
|
||||
continue
|
||||
var stotal: int = int(st["total"])
|
||||
if sp > stotal:
|
||||
continue
|
||||
var t_st := float(sp) / float(stotal)
|
||||
var atk: int = int(st.get("attack", int(0.008 * SAMPLE_RATE)))
|
||||
var env_st: float
|
||||
if sp < atk:
|
||||
env_st = float(sp) / float(atk)
|
||||
else:
|
||||
var remaining := stotal - atk
|
||||
if remaining > 0:
|
||||
env_st = maxf(0.0, 1.0 - float(sp - atk) / float(remaining))
|
||||
else:
|
||||
env_st = 0.0
|
||||
var sf_st: float = lerp(float(st["freq"]), float(st["freq_end"]), t_st)
|
||||
match st["type"]:
|
||||
"sine":
|
||||
st["phase"] = fmod(float(st["phase"]) + sf_st / SAMPLE_RATE, 1.0)
|
||||
s += sin(float(st["phase"]) * TAU) * env_st * float(st["gain"])
|
||||
"triangle":
|
||||
st["phase"] = fmod(float(st["phase"]) + sf_st / SAMPLE_RATE, 1.0)
|
||||
s += (1.0 - absf(4.0 * float(st["phase"]) - 2.0)) * env_st * float(st["gain"])
|
||||
"noise":
|
||||
s += randf_range(-1.0, 1.0) * env_st * float(st["gain"])
|
||||
_stingers = _stingers.filter(func(st): return int(st["pos"]) <= int(st["total"]))
|
||||
|
||||
_playback.push_frame(Vector2(s, s))
|
||||
_mel_pos += 1
|
||||
_arp_pos += 1
|
||||
@@ -595,6 +734,7 @@ func _load_mel() -> void:
|
||||
_bass_freq = FREQ.get(bass_dict[_bass_chord], 0.0)
|
||||
_bass_phase = 0.0
|
||||
_bass2_phase = 0.0
|
||||
_v4_freq = _get_v4_freq()
|
||||
|
||||
func _load_arp() -> void:
|
||||
var arp_dict: Dictionary
|
||||
|
||||
Reference in New Issue
Block a user