Skip to content

Commit 12d884d

Browse files
authored
A port of an early version of Baystation's new instruments (#37447)
* first commit instruments first commit for instruments, should have everything ready * open dream linter fix 1 * fix linter warnings 1 * subsystem + other small fixes * alternative sprites * more alternative sprites * style fixes + src. removal
1 parent 8107706 commit 12d884d

File tree

458 files changed

+1867
-4
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

458 files changed

+1867
-4
lines changed

__DEFINES/subsystem.dm

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
#define SS_PRIORITY_THERM_DISS 19
6161
#define SS_PRIORITY_AMBIENCE 18
6262
#define SS_PRIORITY_DBCORE 17
63+
#define SS_PRIORITY_MUSIC 16
6364
#define SS_PRIORITY_SUN 3
6465
#define SS_PRIORITY_GARBAGE 2
6566
#define SS_PRIORITY_INACTIVITY 1
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
var/datum/subsystem/music/SSmusic
2+
3+
4+
/datum/subsystem/music
5+
name = "Music"
6+
wait = 1
7+
priority = SS_PRIORITY_MUSIC
8+
flags = SS_NO_INIT | SS_KEEP_TIMING
9+
10+
var/list/datum/musical_event/events = list()
11+
12+
/datum/subsystem/music/New()
13+
NEW_SS_GLOBAL(SSmusic)
14+
15+
/datum/subsystem/music/fire(resumed = FALSE)
16+
if (isemptylist(events))
17+
return
18+
var/list/datum/musical_event/left_events = list()
19+
for (var/datum/musical_event/event in events)
20+
event.time -= wait
21+
if (event.time <= 0)
22+
event.tick()
23+
else
24+
left_events += event
25+
events = left_events
26+
27+
/datum/subsystem/music/proc/push_event(datum/sound_player/source, mob/subject, sound/object, time, volume)
28+
if (istype(source) && istype(subject) && istype(object) && volume >= 0 && volume <= 100)
29+
events += new /datum/musical_event(source, subject, object, time, volume)
30+
31+
/datum/subsystem/music/proc/is_overloaded()
32+
return events.len > global.musical_config.max_events

code/datums/supply_packs/hospitality.dm

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,3 +292,13 @@
292292
containername = "big band musical instruments crate"
293293
group = "Hospitality"
294294
containsdesc = "One way around the strange space law is to just order the whole band. Contains one of every instrument."
295+
296+
/datum/supply_packs/synthesizer
297+
contains = list(/obj/structure/synthesized_instrument/synthesizer)
298+
name = "Synthesizer crate"
299+
cost = 50
300+
containertype = /obj/structure/closet/crate/basic
301+
containername = "new age synthesizer crate"
302+
containsdesc = "A new synthesizer has hit the market! Get it while it's still hot!"
303+
304+
group = "Hospitality"

code/game/objects/structures/musician.dm

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -120,8 +120,13 @@
120120
//to_chat(world, "beat: [beat] / beat length: [length(beat)]")
121121
if(!length(beat)) //This occurs when a comma is at the end of a line
122122
beat = " " //It's intended to be a space so here we make it a space
123+
123124
var/list/notes = splittext(beat, "/")
124-
for(var/note in splittext(notes[1], "-"))
125+
var/delta = length(notes)==2 && text2num(notes[2]) ? text2num(notes[2]) : 1
126+
var/note_str = splittext(notes[1], "-")
127+
128+
var/duration = sanitize_tempo(src.tempo/delta)
129+
for(var/note in note_str)
125130
//to_chat(world, "note: [note]")
126131
if(!playing || shouldStopPlaying(user))//If the instrument is playing, or special case
127132
playing = 0
@@ -146,10 +151,11 @@
146151
if (ui)
147152
ui.send_message("activeChord", list2params(list(lineCount, chordCount)))
148153
//nanomanager.send_message(src, instrumentObj.name, "activeChord", list(lineCount, chordCount))
149-
if(notes.len >= 2 && text2num(notes[2]))
154+
/*if(notes.len >= 2 && text2num(notes[2]))
150155
sleep(sanitize_tempo(tempo / text2num(notes[2])))
151156
else
152-
sleep(tempo)
157+
sleep(tempo)*/
158+
sleep(duration)
153159
chordCount++
154160

155161
lineCount++
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
This module uses 4 components:
2+
Real instruments -- the physical manifestation of the instrument, the one that is placed in the world
3+
Virtual instruments -- the definition of an instrument, that is, what samples it uses, name and category
4+
Sound player -- used to apply modification to all sounds emitted. Represents the actual source of sound
5+
Synthesized Song - just like /datum/song it's what parses and plays a melody
6+
---
7+
Real instruments inherit from either /obj/structure/synthesized_instrument (static musical instrument) or /obj/item/device/synthesized_instrument (handheld musical instrument)
8+
---
9+
Virtual instruments all inherit from /datum/instrument.
10+
Virtual instruments should follow this structure: /datum/instrument/category_name/instrument_name.
11+
12+
Refer to any file in ./instrument_data to see how it's done.
13+
---
14+
Sound player inherits from /datum/sound_player
15+
---
16+
For synthesized song only use /datum/synthesized_song
17+
---
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/datum/musical_event
2+
var/sound/object
3+
var/mob/subject
4+
var/datum/sound_player/source
5+
var/time = 0
6+
var/new_volume = 100
7+
8+
9+
/datum/musical_event/New(datum/sound_player/source_, mob/subject_, sound/object_, time_, volume_)
10+
source = source_
11+
subject = subject_
12+
object = object_
13+
time = time_
14+
new_volume = volume_
15+
16+
17+
/datum/musical_event/proc/tick()
18+
if (!(istype(object) && istype(subject) && istype(source)))
19+
return
20+
if (new_volume > 0)
21+
update_sound()
22+
else
23+
destroy_sound()
24+
25+
26+
/datum/musical_event/proc/update_sound()
27+
object.volume = new_volume
28+
object.status |= SOUND_UPDATE
29+
if (subject)
30+
subject << object
31+
32+
33+
/datum/musical_event/proc/destroy_sound()
34+
if (subject)
35+
var/sound/null_sound = sound(channel=object.channel, wait=0)
36+
if (global.musical_config.env_settings_available)
37+
null_sound.environment = -1
38+
subject << null_sound
39+
if (source || source.song)
40+
source.song.free_channel(object.channel)
41+
42+
Lines changed: 244 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,244 @@
1+
var/global/datum/musical_config/musical_config = new
2+
3+
/datum/musical_config
4+
var/highest_octave = 9
5+
var/lowest_octave = 0
6+
7+
var/highest_transposition = 4
8+
var/lowest_transposition = -4
9+
10+
var/longest_sustain_timer = 50
11+
var/gentlest_drop = 1.07
12+
var/steepest_drop = 10.0
13+
14+
var/channels_per_instrument = 128
15+
var/max_lines = 1000
16+
var/max_line_length = 100
17+
var/max_events = 2400
18+
var/song_editor_lines_per_page = 20
19+
20+
var/usage_info_channel_resolution = 1
21+
var/usage_info_event_resolution = 8
22+
23+
var/env_settings_available = 0
24+
// Keep disabled until I figure out how to preserve environment settings
25+
26+
var/list/env_default = list(7.5, 1.0, -1000, -100, 0, 1.49, 0.83, 1.0, -2602, 0.0007, 200, 0.011, 0.25, 0.0, 0.25, 0.0, -5.0, 5000, 250.0, 0.0, 100, 100, 63)
27+
var/list/list/env_params_bounds = list(
28+
list(1, 100, 1),
29+
list(0, 1, 1),
30+
list(-10000, 0, 1),
31+
list(-10000, 0, 1),
32+
list(-10000, 0, 1),
33+
list(0.1, 20, 1),
34+
list(0.1, 2.0, 1),
35+
list(0.1, 2.0, 1),
36+
list(-10000, 1000, 0),
37+
list(0, 0.3, 1),
38+
list(-10000, 2000, 0),
39+
list(0, 0.1, 1),
40+
list(0.075, 0.25, 1),
41+
list(0, 1, 1),
42+
list(0.04, 4.0, 1),
43+
list(0, 1, 1),
44+
list(-100, 0.0, 1),
45+
list(1000, 20000, 0),
46+
list(20, 1000, 1),
47+
list(0, 10, 1),
48+
list(0, 100, 1),
49+
list(0, 100, 1),
50+
list(0, 256, 0))
51+
var/list/all_environments = list(
52+
"None",
53+
"Generic",
54+
"Padded cell",
55+
"Room",
56+
"Bathroom",
57+
"Living Room",
58+
"Stone Room",
59+
"Auditorium",
60+
"Concert Hall",
61+
"Cave",
62+
"Arena",
63+
"Hangar",
64+
"Carpetted Hallway",
65+
"Hallway",
66+
"Stone Coridor",
67+
"Alley",
68+
"Forest",
69+
"City",
70+
"Mountains",
71+
"Quarry",
72+
"Plain",
73+
"Parking Lot",
74+
"Sewer Pipe",
75+
"Underwater",
76+
"Drugged",
77+
"Dizzy",
78+
"Psychotic",
79+
"Custom")
80+
var/list/env_param_names = list(
81+
"Env. Size",
82+
"Env. Diff.",
83+
"Room",
84+
"Room (High Frequency)",
85+
"Room (Low Frequency)",
86+
"Decay Time",
87+
"Decay (High Frequency Ratio)",
88+
"Decay (Low Frequency Ratio)",
89+
"Reflections",
90+
"Reflections Delay",
91+
"Reverb",
92+
"Reverb Delay",
93+
"Echo Time",
94+
"Echo Depth",
95+
"Modulation Time",
96+
"Modulation Depth",
97+
"Air Absorption (High Frequency)",
98+
"High Frequency Reference",
99+
"Low Frequency Reference",
100+
"Room Rolloff Factor",
101+
"Diffusion",
102+
"Density",
103+
"Flags")
104+
var/list/env_param_desc = list(
105+
"environment size in meters",
106+
"environment diffusion",
107+
"room effect level (at mid frequencies)",
108+
"relative room effect level at high frequencies",
109+
"relative room effect level at low frequencies",
110+
"reverberation decay time at mid frequencies",
111+
"high-frequency to mid-frequency decay time ratio",
112+
"low-frequency to mid-frequency decay time ratio",
113+
"early reflections level relative to room effect",
114+
"initial reflection delay time",
115+
"late reverberation level relative to room effect",
116+
"late reverberation delay time relative to initial reflection",
117+
"echo time",
118+
"echo depth",
119+
"modulation time",
120+
"modulation depth",
121+
"change in level per meter at high frequencies",
122+
"reference high frequency (hz)",
123+
"reference low frequency (hz)",
124+
"like rolloffscale in System::set3DSettings but for reverb room size effect",
125+
"Value that controls the echo density in the late reverberation decay.",
126+
"Value that controls the modal density in the late reverberation decay",
127+
{"
128+
Bit flags that modify the behavior of above properties
129+
•1 - 'EnvSize' affects reverberation decay time
130+
•2 - 'EnvSize' affects reflection level
131+
•4 - 'EnvSize' affects initial reflection delay time
132+
•8 - 'EnvSize' affects reflections level
133+
•16 - 'EnvSize' affects late reverberation delay time
134+
•32 - AirAbsorptionHF affects DecayHFRatio
135+
•64 - 'EnvSize' affects echo time
136+
•128 - 'EnvSize' affects modulation time"})
137+
138+
var/list/echo_default = 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, 7)
139+
var/list/list/echo_params_bounds = list(
140+
list(-10000, 1000, 0),
141+
list(-10000, 0, 0),
142+
list(-10000, 1000, 0),
143+
list(-10000, 0, 0),
144+
list(-10000, 0, 0),
145+
list(0, 1, 1),
146+
list(-10000, 0, 0),
147+
list(0, 1, 1),
148+
list(0, 10, 1),
149+
list(0, 10, 1),
150+
list(-10000, 0, 0),
151+
list(0, 1, 1),
152+
list(-10000, 0, 0),
153+
list(0, 10, 1),
154+
list(0, 10, 1),
155+
list(0, 10, 1),
156+
list(0, 10, 1),
157+
list(0, 16, 0))
158+
var/list/echo_param_names = list(
159+
"Direct",
160+
"Direct (High Frequency)",
161+
"Room",
162+
"Room (High Frequency)",
163+
"Obstruction",
164+
"Obstruction (Low Frequency Ratio)",
165+
"Occlusion",
166+
"Occlusion (Low Frequency Ratio)",
167+
"Occlusion (Room Ratio)",
168+
"Occlusion (Direct Ratio)",
169+
"Exclusion",
170+
"Exclusion (Low Frequency Ratio)",
171+
"Outside Volume (High Frequency)",
172+
"Doppler Factor",
173+
"Rolloff Factor",
174+
"Room Rolloff Factor",
175+
"Air Absorption Factor",
176+
"Flags")
177+
var/list/echo_param_desc = list(
178+
"direct path level (at low and mid frequencies)",
179+
"relative direct path level at high frequencies ",
180+
"room effect level (at low and mid frequencies)",
181+
"relative room effect level at high frequencies",
182+
"main obstruction control (attenuation at high frequencies)",
183+
"obstruction low-frequency level re. main control",
184+
"main occlusion control (attenuation at high frequencies)",
185+
"occlusion low-frequency level re. main control",
186+
"relative occlusion control for room effect",
187+
"relative occlusion control for direct path",
188+
"main exlusion control (attenuation at high frequencies)",
189+
"exclusion low-frequency level re. main control",
190+
"outside sound cone level at high frequencies",
191+
"like DS3D flDopplerFactor but per source",
192+
"like DS3D flRolloffFactor but per source",
193+
"like DS3D flRolloffFactor but for room effect",
194+
"multiplies AirAbsorptionHF member of environment reverb properties.",
195+
{"
196+
Bit flags that modify the behavior of properties•1 - Automatic setting of 'Direct' due to distance from listener
197+
•2 - Automatic setting of 'Room' due to distance from listener
198+
•4 - Automatic setting of 'RoomHF' due to distance from listener"})
199+
200+
var/list/n2t_int = list() // Instead of num2text it is used for faster access in n2t
201+
var/list/free_channels = list() // Used to take up some channels and avoid istruments cancelling each other
202+
var/free_channels_populated = 0
203+
var/list/nn2no = list(0,2,4,5,7,9,11) // Maps note num onto note offset
204+
205+
206+
/datum/musical_config/proc/n2t(key) // Used instead of num2text for faster access in sample_map
207+
if (!n2t_int.len)
208+
for (var/i=1, i<=127, i++)
209+
n2t_int += num2text(i)
210+
211+
if (key==0)
212+
return "0" // Fuck you BYOND
213+
if (!isnum(key) || key < 0 || key>127 || round(key) != key)
214+
CRASH("n2t argument must be an integer from 0 to 127")
215+
return n2t_int[key]
216+
217+
218+
/datum/musical_config/proc/environment_to_id(environment)
219+
if (environment in all_environments)
220+
return all_environments.Find(environment) - 2
221+
return -1
222+
223+
224+
/datum/musical_config/proc/id_to_environment(id)
225+
if (id >= -1 && id <= 26)
226+
return all_environments[id+2]
227+
return "None"
228+
229+
230+
/datum/musical_config/proc/index_to_id(index)
231+
return max(min(index-2, 26), -1)
232+
233+
234+
/datum/musical_config/proc/is_custom_env(id)
235+
return id_to_environment(id) == all_environments[28]
236+
237+
238+
/datum/sample_pair
239+
var/sample
240+
var/deviation = 0
241+
242+
/datum/sample_pair/New(sample_file, deviation_)
243+
sample = sample_file
244+
deviation = deviation_

0 commit comments

Comments
 (0)