diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm index 1142f614775..5dfcf2dc888 100644 --- a/code/__DEFINES/misc.dm +++ b/code/__DEFINES/misc.dm @@ -297,10 +297,6 @@ #define FLAMMABLE 0 #define ON_FIRE 1 -// Sound -#define SOUND_MINIMUM_PRESSURE 10 -#define FALLOFF_SOUNDS 0.5 - // Bluespace shelter deploy checks #define SHELTER_DEPLOY_ALLOWED "allowed" #define SHELTER_DEPLOY_BAD_TURFS "bad turfs" diff --git a/code/__DEFINES/sound.dm b/code/__DEFINES/sound.dm new file mode 100644 index 00000000000..712c57b3b3e --- /dev/null +++ b/code/__DEFINES/sound.dm @@ -0,0 +1,16 @@ +//max channel is 1024. Only go lower from here, because byond tends to pick the first availiable channel to play sounds on +#define CHANNEL_LOBBYMUSIC 1024 +#define CHANNEL_ADMIN 1023 +#define CHANNEL_VOX 1022 +#define CHANNEL_HEARTBEAT 1021 //sound channel for heartbeats +#define CHANNEL_BUZZ 1020 +#define CHANNEL_AMBIENCE 1019 + +//THIS SHOULD ALWAYS BE THE LOWEST ONE! +//KEEP IT UPDATED + +#define CHANNEL_HIGHEST_AVAILABLE 1018 + + +#define SOUND_MINIMUM_PRESSURE 10 +#define FALLOFF_SOUNDS 0.5 \ No newline at end of file diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm index 140b6116cd6..0ac2f242b08 100644 --- a/code/game/area/areas.dm +++ b/code/game/area/areas.dm @@ -313,14 +313,15 @@ // Ambience goes down here -- make sure to list each area seperately for ease of adding things in later, thanks! Note: areas adjacent to each other should have the same sounds to prevent cutoff when possible.- LastyScratch if(L && L.client && !L.client.ambience_playing && (L.client.prefs.sound & SOUND_BUZZ)) //split off the white noise from the rest of the ambience because of annoyance complaints - Kluys L.client.ambience_playing = 1 - L << sound('sound/ambience/shipambience.ogg', repeat = 1, wait = 0, volume = 35, channel = 2) - else if(L && L.client && !(L.client.prefs.sound & SOUND_BUZZ)) L.client.ambience_playing = 0 + L << sound('sound/ambience/shipambience.ogg', repeat = 1, wait = 0, volume = 35, channel = CHANNEL_BUZZ) + else if(L && L.client && !(L.client.prefs.sound & SOUND_BUZZ)) + L.client.ambience_playing = 0 if(prob(35) && L && L.client && (L.client.prefs.sound & SOUND_AMBIENCE)) var/sound = pick(ambientsounds) if(!L.client.played) - L << sound(sound, repeat = 0, wait = 0, volume = 25, channel = 1) + L << sound(sound, repeat = 0, wait = 0, volume = 25, channel = CHANNEL_AMBIENCE) L.client.played = 1 spawn(600) //ewww - this is very very bad if(L.&& L.client) diff --git a/code/game/objects/explosion.dm b/code/game/objects/explosion.dm index 4aea96c167b..eae6da6a09b 100644 --- a/code/game/objects/explosion.dm +++ b/code/game/objects/explosion.dm @@ -57,7 +57,7 @@ var/close = range(world.view+round(devastation_range,1), epicenter) // to all distanced mobs play a different sound - for(var/mob/M in world) + for(var/mob/M in mob_list) if(M.z == epicenter.z && !(M in close)) // check if the mob can hear if(M.can_hear() && !istype(M.loc,/turf/space)) diff --git a/code/game/sound.dm b/code/game/sound.dm index 8033e928173..fa313aa0476 100644 --- a/code/game/sound.dm +++ b/code/game/sound.dm @@ -17,19 +17,18 @@ var/list/terminal_type = list('sound/machines/terminal_button01.ogg', 'sound/mac 'sound/machines/terminal_button07.ogg', 'sound/machines/terminal_button08.ogg') var/list/growls = list('sound/goonstation/voice/growl1.ogg', 'sound/goonstation/voice/growl2.ogg', 'sound/goonstation/voice/growl3.ogg') -/proc/playsound(var/atom/source, soundin, vol as num, vary, extrarange as num, falloff, var/is_global, var/pitch) - - soundin = get_sfx(soundin) // same sound for everyone - +/proc/playsound(atom/source, soundin, vol as num, vary, extrarange as num, falloff, frequency = null, channel = 0, pressure_affected = TRUE) if(isarea(source)) error("[source] is an area and is trying to make the sound: [soundin]") return - var/frequency = pitch var/turf/turf_source = get_turf(source) + //allocate a channel if necessary now so its the same for everyone + channel = (channel ? channel : open_sound_channel()) + // Looping through the player list has the added bonus of working for mobs inside containers - var/sound/S = sound(soundin) + var/sound/S = sound(get_sfx(soundin)) var/maxdistance = (world.view + extrarange) * 3 for(var/P in player_list) var/mob/M = P @@ -41,18 +40,19 @@ var/list/growls = list('sound/goonstation/voice/growl1.ogg', 'sound/goonstation/ var/turf/T = get_turf(M) if(T && T.z == turf_source.z) - M.playsound_local(turf_source, soundin, vol, vary, frequency, falloff, is_global, S) + M.playsound_local(turf_source, soundin, vol, vary, frequency, falloff, channel, pressure_affected, S) -/mob/proc/playsound_local(var/turf/turf_source, soundin, vol as num, vary, frequency, falloff, is_global, sound/S) +/mob/proc/playsound_local(turf/turf_source, soundin, vol as num, vary, frequency, falloff, channel = 0, pressure_affected = TRUE, sound/S) if(!src.client || !can_hear()) return if(!S) S = sound(get_sfx(soundin)) + S.wait = 0 //No queue - S.channel = 0 //Any channel + S.channel = (channel ? channel : open_sound_channel()) S.volume = vol - S.environment = -1 + if(vary) if(frequency) S.frequency = frequency @@ -60,7 +60,6 @@ var/list/growls = list('sound/goonstation/voice/growl1.ogg', 'sound/goonstation/ S.frequency = get_rand_frequency() if(isturf(turf_source)) - // 3D sounds, the technology is here! var/turf/T = get_turf(src) //sound volume falloff with distance @@ -68,27 +67,27 @@ var/list/growls = list('sound/goonstation/voice/growl1.ogg', 'sound/goonstation/ S.volume -= max(distance - world.view, 0) * 2 //multiplicative falloff to add on top of natural audio falloff. - //sound volume falloff with pressure - var/pressure_factor = 1.0 + if(pressure_affected) + //Atmosphere affects sound + var/pressure_factor = 1 + var/datum/gas_mixture/hearer_env = T.return_air() + var/datum/gas_mixture/source_env = turf_source.return_air() - var/datum/gas_mixture/hearer_env = T.return_air() - var/datum/gas_mixture/source_env = turf_source.return_air() + if(hearer_env && source_env) + var/pressure = min(hearer_env.return_pressure(), source_env.return_pressure()) + if(pressure < ONE_ATMOSPHERE) + pressure_factor = max((pressure - SOUND_MINIMUM_PRESSURE)/(ONE_ATMOSPHERE - SOUND_MINIMUM_PRESSURE), 0) + else //space + pressure_factor = 0 - if(hearer_env && source_env) - var/pressure = min(hearer_env.return_pressure(), source_env.return_pressure()) + if(distance <= 1) + pressure_factor = max(pressure_factor, 0.15) //touching the source of the sound - if(pressure < ONE_ATMOSPHERE) - pressure_factor = max((pressure - SOUND_MINIMUM_PRESSURE)/(ONE_ATMOSPHERE - SOUND_MINIMUM_PRESSURE), 0) - else //in space - pressure_factor = 0 - - if(distance <= 1) - pressure_factor = max(pressure_factor, 0.15) //hearing through contact - - S.volume *= pressure_factor + S.volume *= pressure_factor + //End Atmosphere affecting sound if(S.volume <= 0) - return //no volume means no sound + return //No sound var/dx = turf_source.x - T.x // Hearing from the right/left S.x = dx @@ -97,16 +96,24 @@ var/list/growls = list('sound/goonstation/voice/growl1.ogg', 'sound/goonstation/ // The y value is for above your head, but there is no ceiling in 2d spessmens. S.y = 1 S.falloff = (falloff ? falloff : FALLOFF_SOUNDS) - if(!is_global) - S.environment = 2 + src << S /client/proc/playtitlemusic() if(!ticker || !ticker.login_music || config.disable_lobby_music) return if(prefs.sound & SOUND_LOBBY) - src << sound(ticker.login_music, repeat = 0, wait = 0, volume = 85, channel = 1) // MAD JAMS + src << sound(ticker.login_music, repeat = 0, wait = 0, volume = 85, channel = CHANNEL_LOBBYMUSIC) // MAD JAMS +/proc/open_sound_channel() + var/static/next_channel = 1 //loop through the available 1024 - (the ones we reserve) channels and pray that its not still being used + . = ++next_channel + if(next_channel > CHANNEL_HIGHEST_AVAILABLE) + next_channel = 1 + +/mob/proc/stop_sound_channel(chan) + src << sound(null, repeat = 0, wait = 0, channel = chan) + /proc/get_rand_frequency() return rand(32000, 55000) //Frequency stuff only works with 45kbps oggs. diff --git a/code/modules/admin/verbs/playsound.dm b/code/modules/admin/verbs/playsound.dm index 69093944f67..1e3e3784e6e 100644 --- a/code/modules/admin/verbs/playsound.dm +++ b/code/modules/admin/verbs/playsound.dm @@ -6,7 +6,7 @@ var/list/sounds_cache = list() if(!check_rights(R_SOUNDS)) return - var/sound/awful_sound = sound(null, repeat = 0, wait = 0, channel = 777) + var/sound/awful_sound = sound(null, repeat = 0, wait = 0, channel = CHANNEL_ADMIN) log_admin("[key_name(src)] stopped admin sounds.") message_admins("[key_name_admin(src)] stopped admin sounds.", 1) @@ -18,7 +18,7 @@ var/list/sounds_cache = list() set name = "Play Global Sound" if(!check_rights(R_SOUNDS)) return - var/sound/uploaded_sound = sound(S, repeat = 0, wait = 1, channel = 777) + var/sound/uploaded_sound = sound(S, repeat = 0, wait = 1, channel = CHANNEL_ADMIN) uploaded_sound.priority = 250 sounds_cache += S diff --git a/code/modules/client/preference/preferences.dm b/code/modules/client/preference/preferences.dm index 9ef12f3d19e..b4d4bc60041 100644 --- a/code/modules/client/preference/preferences.dm +++ b/code/modules/client/preference/preferences.dm @@ -2036,10 +2036,10 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts if("lobby_music") sound ^= SOUND_LOBBY - if(sound & SOUND_LOBBY) - user << sound(ticker.login_music, repeat = 0, wait = 0, volume = 85, channel = 1) + if((sound & SOUND_LOBBY) && user.client) + user.client.playtitlemusic() else - user << sound(null, repeat = 0, wait = 0, volume = 85, channel = 1) + user.stop_sound_channel(CHANNEL_LOBBYMUSIC) if("ghost_ears") toggles ^= CHAT_GHOSTEARS diff --git a/code/modules/client/preference/preferences_toggles.dm b/code/modules/client/preference/preferences_toggles.dm index b922706fd61..40804aa83b2 100644 --- a/code/modules/client/preference/preferences_toggles.dm +++ b/code/modules/client/preference/preferences_toggles.dm @@ -95,12 +95,11 @@ prefs.save_preferences(src) if(prefs.sound & SOUND_LOBBY) to_chat(src, "You will now hear music in the game lobby.") - if(istype(mob, /mob/new_player)) - playtitlemusic() + if(isnewplayer(usr)) + usr.client.playtitlemusic() else to_chat(src, "You will no longer hear music in the game lobby.") - if(istype(mob, /mob/new_player)) - src << sound(null, repeat = 0, wait = 0, volume = 85, channel = 1)// stop the jamsz + usr.stop_sound_channel(CHANNEL_LOBBYMUSIC) feedback_add_details("admin_verb","TLobby") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! @@ -113,9 +112,7 @@ if(prefs.sound & SOUND_MIDI) to_chat(src, "You will now hear any sounds uploaded by admins.") else - var/sound/break_sound = sound(null, repeat = 0, wait = 0, channel = 777) - break_sound.priority = 250 - src << break_sound //breaks the client's sound output on channel 777 + usr.stop_sound_channel(CHANNEL_ADMIN) to_chat(src, "You will no longer hear sounds uploaded by admins; any currently playing midis have been disabled.") feedback_add_details("admin_verb","TMidi") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! @@ -150,7 +147,7 @@ to_chat(src, "You will now hear ambient sounds.") else to_chat(src, "You will no longer hear ambient sounds.") - src << sound(null, repeat = 0, wait = 0, volume = 0, channel = 1) + usr.stop_sound_channel(CHANNEL_AMBIENCE) feedback_add_details("admin_verb","TAmbi") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! /client/verb/Toggle_Buzz() //No more headaches because headphones bump up shipambience.ogg to insanity levels. @@ -163,7 +160,7 @@ to_chat(src, "You will now hear ambient white noise.") else to_chat(src, "You will no longer hear ambient white noise.") - src << sound(null, repeat = 0, wait = 0, volume = 0, channel = 2) + usr.stop_sound_channel(CHANNEL_BUZZ) feedback_add_details("admin_verb","TBuzz") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! @@ -177,8 +174,7 @@ to_chat(src, "You will now hear heartbeat sounds.") else to_chat(src, "You will no longer hear heartbeat sounds.") - src << sound(null, repeat = 0, wait = 0, volume = 0, channel = 1) - src << sound(null, repeat = 0, wait = 0, volume = 0, channel = 2) + usr.stop_sound_channel(CHANNEL_HEARTBEAT) feedback_add_details("admin_verb","Thb") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! // This needs a toggle because you people are awful and spammed terrible music diff --git a/code/modules/mob/living/carbon/human/emote.dm b/code/modules/mob/living/carbon/human/emote.dm index 89f8b9a5c9d..7083b04ee35 100644 --- a/code/modules/mob/living/carbon/human/emote.dm +++ b/code/modules/mob/living/carbon/human/emote.dm @@ -734,9 +734,9 @@ message = "[src] [species.scream_verb][M ? " at [M]" : ""]!" m_type = 2 if(gender == FEMALE) - playsound(loc, "[species.female_scream_sound]", 80, 1, 0, pitch = get_age_pitch()) + playsound(loc, "[species.female_scream_sound]", 80, 1, frequency = get_age_pitch()) else - playsound(loc, "[species.male_scream_sound]", 80, 1, 0, pitch = get_age_pitch()) //default to male screams if no gender is present. + playsound(loc, "[species.male_scream_sound]", 80, 1, frequency = get_age_pitch()) //default to male screams if no gender is present. else message = "[src] makes a very loud noise[M ? " at [M]" : ""]." diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index 294c78c4ec0..a1833635fe7 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -1092,7 +1092,7 @@ if(heartbeat >= rate) heartbeat = 0 - src << sound('sound/effects/electheart.ogg',0,0,0,30)//Credit to GhostHack (www.ghosthack.de) for sound. + src << sound('sound/effects/electheart.ogg',0,0,CHANNEL_HEARTBEAT,30)//Credit to GhostHack (www.ghosthack.de) for sound. else heartbeat++ @@ -1111,9 +1111,9 @@ if(heartbeat >= rate) heartbeat = 0 if(H.status & ORGAN_ASSISTED) - src << sound('sound/effects/pacemakebeat.ogg',0,0,0,50) + src << sound('sound/effects/pacemakebeat.ogg',0,0,CHANNEL_HEARTBEAT,50) else - src << sound('sound/effects/singlebeat.ogg',0,0,0,50) + src << sound('sound/effects/singlebeat.ogg',0,0,CHANNEL_HEARTBEAT,50) else heartbeat++ diff --git a/code/modules/mob/living/silicon/ai/say.dm b/code/modules/mob/living/silicon/ai/say.dm index 39af8059e8b..f360d07a4cb 100644 --- a/code/modules/mob/living/silicon/ai/say.dm +++ b/code/modules/mob/living/silicon/ai/say.dm @@ -66,7 +66,6 @@ */ var/announcing_vox = 0 // Stores the time of the last announcement -var/const/VOX_CHANNEL = 200 var/const/VOX_DELAY = 100 var/const/VOX_PATH = "sound/vox_fem/" @@ -136,11 +135,14 @@ var/const/VOX_PATH = "sound/vox_fem/" play_vox_word(word, src.z, null) -/proc/play_vox_word(var/word, var/z_level, var/mob/only_listener) +/proc/play_vox_word(word, z_level, mob/only_listener) + word = lowertext(word) + if(vox_sounds[word]) + var/sound_file = vox_sounds[word] - var/sound/voice = sound(sound_file, wait = 1, channel = VOX_CHANNEL) + var/sound/voice = sound(sound_file, wait = 1, channel = CHANNEL_VOX) voice.status = SOUND_STREAM // If there is no single listener, broadcast to everyone in the same z level diff --git a/code/modules/mob/new_player/new_player.dm b/code/modules/mob/new_player/new_player.dm index 67d057435d0..19c72238c3a 100644 --- a/code/modules/mob/new_player/new_player.dm +++ b/code/modules/mob/new_player/new_player.dm @@ -123,7 +123,7 @@ var/mob/dead/observer/observer = new() src << browse(null, "window=playersetup") spawning = 1 - src << sound(null, repeat = 0, wait = 0, volume = 85, channel = 1)// MAD JAMS cant last forever yo + stop_sound_channel(CHANNEL_LOBBYMUSIC) observer.started_as_observer = 1 @@ -451,7 +451,7 @@ client.prefs.real_name = random_name(client.prefs.gender) client.prefs.copy_to(new_character) - src << sound(null, repeat = 0, wait = 0, volume = 85, channel = 1)// MAD JAMS cant last forever yo + stop_sound_channel(CHANNEL_LOBBYMUSIC) if(mind) diff --git a/code/modules/mob/transform_procs.dm b/code/modules/mob/transform_procs.dm index 51890a7337f..072300a85f8 100644 --- a/code/modules/mob/transform_procs.dm +++ b/code/modules/mob/transform_procs.dm @@ -20,7 +20,7 @@ /mob/proc/AIize() if(client) - src << sound(null, repeat = 0, wait = 0, volume = 85, channel = 1)// stop the jams for AIs + stop_sound_channel(CHANNEL_LOBBYMUSIC) var/mob/living/silicon/ai/O = new (loc,,,1)//No MMI but safety is in effect. O.invisibility = 0 diff --git a/code/modules/spacepods/spacepod.dm b/code/modules/spacepods/spacepod.dm index a90bd9bb1d8..e2a21f507fa 100644 --- a/code/modules/spacepods/spacepod.dm +++ b/code/modules/spacepods/spacepod.dm @@ -284,7 +284,7 @@ return var/sound/S = sound(mysound) S.wait = 0 //No queue - S.channel = 0 //Any channel + S.channel = open_sound_channel() S.volume = 50 for(var/mob/M in passengers | pilot) M << S diff --git a/paradise.dme b/paradise.dme index 1e66e3547b5..4b7ed662b34 100644 --- a/paradise.dme +++ b/paradise.dme @@ -49,6 +49,7 @@ #include "code\__DEFINES\rolebans.dm" #include "code\__DEFINES\sight.dm" #include "code\__DEFINES\snpc.dm" +#include "code\__DEFINES\sound.dm" #include "code\__DEFINES\stat.dm" #include "code\__DEFINES\tick.dm" #include "code\__DEFINES\zlevel.dm"