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"