2024-10-05 09:50:03 +02:00
class_name SpatialAudioStreamPlayer2D
extends AudioStreamPlayer2D
2024-10-06 00:43:05 +02:00
# EXPORTED VARS
2024-10-06 00:45:20 +02:00
@ export_category ( " dampening effect " )
@ export var n_pointcasts_to_player : int = 25
2024-10-06 00:43:05 +02:00
@ export var lowpass_cutoff_mult : float = 1000
@ export var lowpass_cutoff_min : float = 100
@ export var dampening_distance_divisor_mult : float = 500
# DETERMINE REVERB EFFECT PARAMETERS
2024-10-05 09:50:03 +02:00
const RAYCAST_VECS : Array [ Vector2 ] = [
Vector2 ( - 1 , 0 ) , # 0 - left
Vector2 ( - 1 , - 1 ) , # 1 - top left
Vector2 ( 0 , - 1 ) , # 2 - top
Vector2 ( 1 , - 1 ) , # 3 - top right
Vector2 ( 1 , 0 ) , # 4 - right
Vector2 ( 1 , 1 ) , # 5 - bottom right
Vector2 ( 0 , 1 ) , # 6 - bottom
Vector2 ( - 1 , 1 ) # 7 - bottom left
]
2024-10-05 10:33:07 +02:00
const REVERB_MULT_PARALLEL = 1.0
const REVERB_MULT_OPP_45DEG = 0.5
const REVERB_MULT_90DEG = 0.25
2024-10-05 09:50:03 +02:00
const REVERB_PAIRS = [
# [<index in raycasts array>, <index in raycasts array>, <multiplier>]
# parallel walls
[ 0 , 4 , REVERB_MULT_PARALLEL ] , # left : right
[ 2 , 6 , REVERB_MULT_PARALLEL ] , # top : bottom
[ 1 , 5 , REVERB_MULT_PARALLEL ] , # top left : bottom right
[ 3 , 7 , REVERB_MULT_PARALLEL ] , # top right : bottom left
# opposing walls at an 45deg angle
[ 0 , 3 , REVERB_MULT_OPP_45DEG ] ,
[ 0 , 5 , REVERB_MULT_OPP_45DEG ] ,
[ 1 , 4 , REVERB_MULT_OPP_45DEG ] ,
[ 1 , 6 , REVERB_MULT_OPP_45DEG ] ,
[ 2 , 5 , REVERB_MULT_OPP_45DEG ] ,
[ 2 , 7 , REVERB_MULT_OPP_45DEG ] ,
[ 3 , 6 , REVERB_MULT_OPP_45DEG ] ,
[ 4 , 7 , REVERB_MULT_OPP_45DEG ] ,
# walls at an 90deg angle
[ 0 , 2 , REVERB_MULT_90DEG ] ,
[ 0 , 6 , REVERB_MULT_90DEG ] ,
[ 1 , 3 , REVERB_MULT_90DEG ] ,
[ 1 , 7 , REVERB_MULT_90DEG ] ,
[ 2 , 4 , REVERB_MULT_90DEG ] ,
[ 3 , 5 , REVERB_MULT_90DEG ] ,
[ 4 , 6 , REVERB_MULT_90DEG ] ,
[ 5 , 7 , REVERB_MULT_90DEG ]
]
2024-10-05 10:33:07 +02:00
const REVERB_PAIRS_SUM_DIVISOR = 2500.0 # i dunno
2024-10-05 09:50:03 +02:00
var raycasts : Array [ RayCast2D ] = [ ]
func create_raycasts ( ) :
2024-10-06 00:43:05 +02:00
# raycasts used for reverb
2024-10-05 09:50:03 +02:00
for v in RAYCAST_VECS :
var r = RayCast2D . new ( )
2024-10-05 10:33:07 +02:00
r . target_position = v . normalized ( ) * max_distance
2024-10-05 09:50:03 +02:00
raycasts . append ( r )
self . add_child ( r )
func determine_reverb_params ( ) - > Array [ float ] :
# returns [room_size, wetness]
2024-10-05 22:03:22 +02:00
var n_coll : int = 0
2024-10-05 09:50:03 +02:00
var collision_points : Array [ Vector2 ] = [ ]
for r in raycasts :
if r . is_colliding ( ) :
var collider = r . get_collider ( )
if collider is StaticBody2D or collider is RigidBody2D :
n_coll += 1
var collision_point = r . get_collision_point ( )
collision_points . append ( collision_point )
else :
collision_points . append ( Vector2 ( INF , INF ) )
else :
collision_points . append ( Vector2 ( INF , INF ) )
var reverb_pairs_sum : float = 0.0
for p in REVERB_PAIRS :
if collision_points [ p [ 0 ] ] != Vector2 ( INF , INF ) and collision_points [ p [ 1 ] ] != Vector2 ( INF , INF ) :
reverb_pairs_sum += (
2024-10-05 10:33:07 +02:00
collision_points [ p [ 0 ] ] . distance_to ( collision_points [ p [ 1 ] ] ) * p [ 2 ]
2024-10-05 09:50:03 +02:00
)
2024-10-05 10:33:07 +02:00
var room_size = reverb_pairs_sum / REVERB_PAIRS_SUM_DIVISOR
2024-10-05 09:50:03 +02:00
var wetness = n_coll / 8.0
return [ room_size , wetness ]
2024-10-06 00:43:05 +02:00
# DETERMINE DAMPENING (LOWPASS) EFFECT PARAMETERS
const POINTCAST_TO_PLAYER_COLL_MASK : int = 0 b00000000_00000000_00000000_00000001
const LOWPASS_CUTOFF_MAX : float = 20000
func determine_distance_amount_blocked ( ) - > float :
# returns how many points (in relation to the amount of points)
# between this and the player are intersecting
# and therefore an obstacle for the sound
var position_player = NodeRegistry . player . global_position
var distance_to_player = self . global_position . distance_to ( position_player )
# get n collisions
var n_coll : int = 0
# cast points towards player
var space_state = get_world_2d ( ) . direct_space_state
2024-10-06 00:45:20 +02:00
for i in range ( n_pointcasts_to_player ) :
2024-10-06 00:43:05 +02:00
# linear interpolate between own position and player position
2024-10-06 00:45:20 +02:00
var point_pos = lerp ( self . global_position , position_player , i / float ( n_pointcasts_to_player ) )
2024-10-06 00:43:05 +02:00
var query_params = PhysicsPointQueryParameters2D . new ( )
query_params . collision_mask = POINTCAST_TO_PLAYER_COLL_MASK
query_params . position = point_pos
var result = space_state . intersect_point ( query_params )
if len ( result ) > 0 :
n_coll += 1
2024-10-06 00:45:20 +02:00
return ( n_coll * distance_to_player ) / ( float ( n_pointcasts_to_player ) * dampening_distance_divisor_mult )
2024-10-06 00:43:05 +02:00
2024-10-05 09:50:03 +02:00
# AUDIO EFFECTS
var audio_effect_reverb = AudioEffectReverb . new ( )
2024-10-06 00:43:05 +02:00
var audio_effect_dampen = AudioEffectLowPassFilter . new ( )
2024-10-05 09:50:03 +02:00
func update_reverb ( room_size : float , wetness : float ) :
audio_effect_reverb . room_size = room_size
audio_effect_reverb . wet = wetness
2024-10-06 00:43:05 +02:00
func update_dampening ( distance_blocked : float ) :
audio_effect_dampen . cutoff_hz = clamp (
lowpass_cutoff_mult / max ( 0.001 , distance_blocked ) ,
lowpass_cutoff_min , LOWPASS_CUTOFF_MAX
)
2024-10-05 09:50:03 +02:00
# AUDIO BUS
const BUS_NAME_PREFIX = " Spatial2DBus# "
const BUS_EFFECT_POS_REVERB = 0
2024-10-06 00:43:05 +02:00
const BUS_EFFECT_POS_LOWPASS = 1
2024-10-05 09:50:03 +02:00
var bus_idx : int = - 1
var bus_name : String = " "
func create_audio_bus ( ) :
bus_idx = AudioServer . bus_count
bus_name = " BUS_NAME_PREFIX %s " % bus_idx
AudioServer . add_bus ( bus_idx )
AudioServer . set_bus_name ( bus_idx , bus_name )
AudioServer . set_bus_send ( bus_idx , bus )
self . bus = bus_name
func create_audio_bus_effects ( ) :
if bus_idx == - 1 :
push_error ( " Audio bus isn ' t created yet, bus create_audio_effects is called! " )
return
# reverb
AudioServer . add_bus_effect ( bus_idx , audio_effect_reverb , BUS_EFFECT_POS_REVERB )
2024-10-06 00:43:05 +02:00
# dampeing (lowpass)
AudioServer . add_bus_effect ( bus_idx , audio_effect_dampen , BUS_EFFECT_POS_LOWPASS )
2024-10-05 09:50:03 +02:00
#
func _ready ( ) - > void :
create_audio_bus ( )
create_audio_bus_effects ( )
create_raycasts ( )
func _physics_process ( _delta : float ) - > void :
var reverb_params = determine_reverb_params ( )
2024-10-06 00:43:05 +02:00
var blocked_amount = determine_distance_amount_blocked ( )
2024-10-05 09:50:03 +02:00
update_reverb ( reverb_params [ 0 ] , reverb_params [ 1 ] )
2024-10-06 00:43:05 +02:00
update_dampening ( blocked_amount )