Skip to content

Commit

Permalink
initial
Browse files Browse the repository at this point in the history
  • Loading branch information
Doubleumc committed Jul 18, 2024
1 parent 93ec953 commit c8ea6fb
Show file tree
Hide file tree
Showing 7 changed files with 2,771 additions and 198 deletions.
9 changes: 9 additions & 0 deletions code/__DEFINES/sounds.dm
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,15 @@
#define SOUND_ECHO_REVERB_ON list(0, 0, 0, 0, 0, 0.0, 0, 0.25, 1.5, 1.0, 0, 1.0, 0, 0.0, 0.0, 0.0, 1.0, 0)
#define SOUND_ECHO_REVERB_OFF list(0, 0, -10000, -10000, 0, 0.0, 0, 0.25, 1.5, 1.0, 0, 1.0, 0, 0.0, 0.0, 0.0, 1.0, 0) //-10000 to Room & RoomHF makes enviromental reverb effectively inaudible

/// Enviromental sounds are effected by environmental reverb
#define SOUND_ENVIRONMENTAL (1<<4)
/// Sound can be muted by mob deafness
#define SOUND_CAN_DEAFEN (1<<5)
/// Spatial sounds set the sound position relative to the source
#define SOUND_SPATIAL (1<<6)
/// Sound is tracked by soundOutput for updating position, volume, etc
#define SOUND_TRACKED (1<<7)

#define AMBIENCE_SHIP 'sound/ambience/shipambience.ogg'
#define AMBIENCE_JUNGLE 'sound/ambience/ambienceLV624.ogg'
#define AMBIENCE_RIVER 'sound/ambience/ambienceriver.ogg'
Expand Down
2,423 changes: 2,423 additions & 0 deletions code/_globalvars/lists/sounds.dm

Large diffs are not rendered by default.

53 changes: 38 additions & 15 deletions code/controllers/subsystem/sound.dm
Original file line number Diff line number Diff line change
Expand Up @@ -17,28 +17,51 @@ SUBSYSTEM_DEF(sound)

for(var/datum/sound_template/run_template in run_queue)
if(!run_hearers) // Initialize for handling next template
run_hearers = run_queue[run_template] // get base hearers
if(run_template.range) // ranging
run_hearers |= SSquadtree.players_in_range(SQUARE(run_template.x, run_template.y, run_template.range), run_template.z)
run_hearers = run_queue[run_template] // get initial hearers
run_template.end_time = REALTIMEOFDAY + GLOB.sound_lengths["[run_template.file]"] SECONDS
if(MC_TICK_CHECK)
return

while(length(run_hearers)) // Output sound to hearers
var/client/C = run_hearers[length(run_hearers)]
var/client/hearer = run_hearers[length(run_hearers)]
run_hearers.len--
if(C && C.soundOutput)
C.soundOutput.process_sound(run_template)
hearer?.soundOutput.process_sound(run_template)
if(MC_TICK_CHECK)
return

run_queue.Remove(run_template) // Everyone that had to get this sound got it. Bye, template
run_hearers = null // Reset so we know next one is new

/datum/controller/subsystem/sound/proc/queue(datum/sound_template/template, list/client/hearers, list/datum/interior/extra_interiors)
if(!hearers)
hearers = list()
if(extra_interiors && SSmapping)
for(var/datum/interior/VI in extra_interiors)
if(VI?.ready)
var/list/bounds = VI.get_middle_coords()
if(length(bounds) >= 2)
hearers |= SSquadtree.players_in_range(RECT(bounds[1], bounds[2], VI.map_template.width, VI.map_template.height), bounds[3])
for(var/client/client as anything in GLOB.clients)
client.soundOutput.update_tracked_channels()
if(MC_TICK_CHECK)
return

/datum/controller/subsystem/sound/proc/queue(datum/sound_template/template, list/hearers)
LAZYINITLIST(hearers)

if(!CHECK_BITFIELD(template.sound_flags, SOUND_SPATIAL))
template_queue[template] = hearers
return

var/turf/source_turf = get_turf(template.source)
if(SSinterior.in_interior(source_turf)) //from interior, get hearers in interior and nearby to exterior
var/datum/interior/interior = SSinterior.get_interior_by_coords(source_turf.x, source_turf.y, source_turf.z)
var/list/bounds = interior.get_middle_coords()
hearers |= SSquadtree.players_in_range(RECT(bounds[1], bounds[2], interior.map_template.width, interior.map_template.height), bounds[3]) //in interior
if(interior.exterior)
hearers |= SSquadtree.players_in_range(SQUARE(interior.exterior.x, interior.exterior.y, template.range * 2), interior.exterior.z) //nearby to exterior

else //from exterior, get hearers nearby and in nearby interiors
hearers |= SSquadtree.players_in_range(SQUARE(source_turf.x, source_turf.y, template.range * 2), source_turf.z) //nearby
for(var/datum/interior/interior in SSinterior.interiors)
if(!interior.ready)
continue
if(interior.exterior?.z != source_turf.z)
continue
if(get_dist(interior.exterior, source_turf) > template.range)
continue
var/list/bounds = interior.get_middle_coords()
hearers |= SSquadtree.players_in_range(RECT(bounds[1], bounds[2], interior.map_template.width, interior.map_template.height), bounds[3]) //nearby interiors

template_queue[template] = hearers
101 changes: 69 additions & 32 deletions code/datums/soundOutput.dm
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

/// Currently applied environmental reverb.
VAR_PROTECTED/owner_environment = SOUND_ENVIRONMENT_NONE
/// Assoc list of important channels and their assigned template, in the form of: "channel" = template
var/list/tracked_channels = list()

/datum/soundOutput/New(client/client)
if(!client)
Expand All @@ -24,38 +26,73 @@
owner = null
return ..()

/datum/soundOutput/proc/process_sound(datum/sound_template/T)
var/sound/S = sound(T.file, T.wait, T.repeat)
S.volume = owner.volume_preferences[T.volume_cat] * T.volume
if(T.channel == 0)
S.channel = get_free_channel()
else
S.channel = T.channel
S.frequency = T.frequency
S.falloff = T.falloff
S.status = T.status
if(T.x && T.y && T.z)
var/turf/owner_turf = get_turf(owner.mob)
if(owner_turf)
// We're in an interior and sound came from outside
if(SSinterior.in_interior(owner_turf) && owner_turf.z != T.z)
var/datum/interior/VI = SSinterior.get_interior_by_coords(owner_turf.x, owner_turf.y, owner_turf.z)
if(VI && VI.exterior)
var/turf/candidate = get_turf(VI.exterior)
if(candidate.z != T.z)
return // Invalid location
S.falloff /= 2
owner_turf = candidate
S.x = T.x - owner_turf.x
S.y = 0
S.z = T.y - owner_turf.y
S.y += T.y_s_offset
S.x += T.x_s_offset
S.echo = SOUND_ECHO_REVERB_ON //enable environment reverb for positional sounds
if(owner.mob.ear_deaf > 0)
S.status |= SOUND_MUTE

sound_to(owner,S)
/datum/soundOutput/proc/process_sound(datum/sound_template/template, update)
var/sound/sound = sound(template.file, template.repeat, template.wait)

sound.channel = template.channel
sound.volume = template.volume * owner.volume_preferences[template.volume_cat]
sound.frequency = template.frequency
sound.offset = template.offset
sound.pitch = template.pitch
sound.status = template.status
sound.falloff = template.falloff

if(update)
ENABLE_BITFIELD(sound.status, SOUND_UPDATE)

if(CHECK_BITFIELD(template.sound_flags, SOUND_CAN_DEAFEN) && CHECK_BITFIELD(src.status_flags, EAR_DEAF_MUTE))
ENABLE_BITFIELD(sound.status, SOUND_MUTE)

if(CHECK_BITFIELD(template.sound_flags, SOUND_ENVIRONMENTAL))
sound.echo = SOUND_ECHO_REVERB_ON

if(CHECK_BITFIELD(template.sound_flags, SOUND_TRACKED) && !update)
if(GLOB.spatial_sound_tracking && GLOB.sound_lengths["[template.file]"] SECONDS >= GLOB.spatial_sound_tracking_min_length) //debug
tracked_channels[num2text(sound.channel)] = template

if(!CHECK_BITFIELD(template.sound_flags, SOUND_SPATIAL)) //non-spatial
sound.x = template.x
sound.y = template.y
sound.z = template.z
sound_to(owner, sound)
return

if(QDELETED(template.source))
return

var/turf/owner_turf = get_turf(owner.mob)
var/turf/source_turf = get_turf(template.source)
//soundsys only traverses one "step", so will never send from one interior to another
if(owner_turf.z == source_turf.z) //both in exterior, or both in same interior
sound.x = source_turf.x - owner_turf.x
sound.z = source_turf.y - owner_turf.y
else if(SSinterior.in_interior(owner_turf)) //source in exterior, owner in interior
var/datum/interior/interior = SSinterior.get_interior_by_coords(owner_turf.x, owner_turf.y, owner_turf.z)
sound.falloff *= 0.5
sound.x = source_turf.x - interior.exterior.x
sound.z = source_turf.y - interior.exterior.y
else if(SSinterior.in_interior(source_turf)) //source in interior, owner in exterior
var/datum/interior/interior = SSinterior.get_interior_by_coords(source_turf.x, source_turf.y, source_turf.z)
sound.falloff *= 0.5
sound.x = interior.exterior.x - owner_turf.x
sound.z = interior.exterior.y - owner_turf.y
else //moved to unrelated z while sound was playing, leave it alone
return

sound_to(owner, sound)

/datum/soundOutput/proc/update_tracked_channels()
for(var/i in length(tracked_channels) to 1 step -1)
var/channel = tracked_channels[i]
var/datum/sound_template/template = tracked_channels[channel]
if(REALTIMEOFDAY >= template.end_time)
tracked_channels -= channel
continue
if(!CHECK_BITFIELD(template.sound_flags, SOUND_SPATIAL))
continue
if(template.source == owner.mob)
continue
process_sound(template, update = TRUE)

/datum/soundOutput/proc/update_ambience(area/target_area, ambience_override, force_update = FALSE)
var/status_flags = SOUND_STREAM
Expand Down
Loading

0 comments on commit c8ea6fb

Please sign in to comment.