Skip to content

Commit be1731f

Browse files
authored
Merge pull request #253 from Jrius/eax_listener_mod
Eax reverb
2 parents 22892ef + 23d0aeb commit be1731f

File tree

4 files changed

+290
-0
lines changed

4 files changed

+290
-0
lines changed

korman/properties/modifiers/region.py

Lines changed: 235 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,241 @@ def requires_actor(self):
215215
return True
216216

217217

218+
reverb_flags = [("kFlagDecayTimeScale", "Decay Time Scale", "Reverberation decay time"),
219+
("kFlagReflectionsScale", "Reflections Scale", "Reflection level"),
220+
("kFlagReflectionsDelayScale", "Reflections Delay Scale", "Initial reflection delay time"),
221+
("kFlagReverbScale", "Reverb Scale", "Reverberation level"),
222+
("kFlagReverbDelayScale", "Reverb Delay Scale", "Late reverberation delay time"),
223+
("kFlagEchoTimeScale", "Echo Time Scale", "Echo time"),
224+
("kFlagModulationTimeScale", "Modulation Time Scale", "Modulation time"),
225+
("kFlagDecayHFLimit", "Decay HF Limit", "Limit unnaturally long decay times of high-frequency sounds by forcing a limit to the decay time to be calculated from the Air Absorption HF value")]
226+
227+
class PlasmaReverbRegion(PlasmaModifierProperties):
228+
pl_id = "reverb"
229+
pl_depends = {"softvolume"}
230+
231+
bl_category = "Region"
232+
bl_label = "Sound Reverb Region"
233+
bl_description = "Sound Reverberation (EAX) Region"
234+
bl_icon = "IPO_ELASTIC"
235+
236+
preset = EnumProperty(name="Environment Preset",
237+
description="The type of audio environment to simulate",
238+
items=[("GENERIC", "Generic", "A generic-sounding environment with light reverberation"),
239+
("PADDEDCELL", "Padded cell", ""),
240+
("ROOM", "Room", ""),
241+
("BATHROOM", "Bathroom", ""),
242+
("LIVINGROOM", "Living room", ""),
243+
("STONEROOM", "Stone room", ""),
244+
("AUDITORIUM", "Auditorium", ""),
245+
("CONCERTHALL", "Concert Hall", ""),
246+
("CAVE", "Cave", ""),
247+
("ARENA", "Arena", ""),
248+
("HANGAR", "Hangar", ""),
249+
("CARPETTEDHALLWAY", "Carpetted hallway", ""),
250+
("HALLWAY", "Hallway", ""),
251+
("STONECORRIDOR", "Stone corridor", ""),
252+
("ALLEY", "Alley", ""),
253+
("FOREST", "Forest", ""),
254+
("CITY", "City", ""),
255+
("MOUNTAINS", "Mountains", ""),
256+
("QUARRY", "Quarry", ""),
257+
("PLAIN", "Plain", ""),
258+
("PARKINGLOT", "Parking lot", ""),
259+
("SEWERPIPE", "Sewer pipe", ""),
260+
("UNDERWATER", "Underwater", ""),
261+
("DRUGGED", "Drugged", ""),
262+
("DIZZY", "Drizzy", ""),
263+
("PSYCHOTIC", "Psychotic", ""),
264+
("CASTLE_SMALLROOM", "Castle - Small room", ""),
265+
("CASTLE_SHORTPASSAGE", "Castle - Short passage", ""),
266+
("CASTLE_MEDIUMROOM", "Castle - Medium room", ""),
267+
("CASTLE_LONGPASSAGE", "Castle - Long passage", ""),
268+
("CASTLE_LARGEROOM", "Castle - Large room", ""),
269+
("CASTLE_HALL", "Castle - Hall", ""),
270+
("CASTLE_CUPBOARD", "Castle - Cupboard", ""),
271+
("CASTLE_COURTYARD", "Castle - Courtyard", ""),
272+
("CASTLE_ALCOVE", "Castle - Alcove", ""),
273+
("FACTORY_ALCOVE", "Factory - Alcove", ""),
274+
("FACTORY_SHORTPASSAGE", "Factory - Short passage", ""),
275+
("FACTORY_MEDIUMROOM", "Factory - Medium room", ""),
276+
("FACTORY_LONGPASSAGE", "Factory - Long passage", ""),
277+
("FACTORY_LARGEROOM", "Factory - Large room", ""),
278+
("FACTORY_HALL", "Factory - Hall", ""),
279+
("FACTORY_CUPBOARD", "Factory - Cupboard", ""),
280+
("FACTORY_COURTYARD", "Factory - Courtyard", ""),
281+
("FACTORY_SMALLROOM", "Factory - Small room", ""),
282+
("ICEPALACE_ALCOVE", "Ice palace - Alcove", ""),
283+
("ICEPALACE_SHORTPASSAGE", "Ice palace - Short passage", ""),
284+
("ICEPALACE_MEDIUMROOM", "Ice palace - Medium room", ""),
285+
("ICEPALACE_LONGPASSAGE", "Ice palace - Long passage", ""),
286+
("ICEPALACE_LARGEROOM", "Ice palace - Large room", ""),
287+
("ICEPALACE_HALL", "Ice palace - Hall", ""),
288+
("ICEPALACE_CUPBOARD", "Ice palace - Cupboard", ""),
289+
("ICEPALACE_COURTYARD", "Ice palace - Courtyard", ""),
290+
("ICEPALACE_SMALLROOM", "Ice palace - Small room", ""),
291+
("SPACESTATION_ALCOVE", "Space station - Alcove", ""),
292+
("SPACESTATION_MEDIUMROOM", "Space station - Medium room", ""),
293+
("SPACESTATION_SHORTPASSAGE", "Space station - Short passage", ""),
294+
("SPACESTATION_LONGPASSAGE", "Space station - Long passage", ""),
295+
("SPACESTATION_LARGEROOM", "Space station - Large room", ""),
296+
("SPACESTATION_HALL", "Space station - Hall", ""),
297+
("SPACESTATION_CUPBOARD", "Space station - Cupboard", ""),
298+
("SPACESTATION_SMALLROOM", "Space station - Small room", ""),
299+
("WOODEN_ALCOVE", "Wooden alcove", ""),
300+
("WOODEN_SHORTPASSAGE", "Wooden short passage", ""),
301+
("WOODEN_MEDIUMROOM", "Wooden medium room", ""),
302+
("WOODEN_LONGPASSAGE", "Wooden long passage", ""),
303+
("WOODEN_LARGEROOM", "Wooden large room", ""),
304+
("WOODEN_HALL", "Wooden hall", ""),
305+
("WOODEN_CUPBOARD", "Wooden cupboard", ""),
306+
("WOODEN_SMALLROOM", "Wooden small room", ""),
307+
("WOODEN_COURTYARD", "Wooden courtyard", ""),
308+
("SPORT_EMPTYSTADIUM", "Sport - Empty stadium", ""),
309+
("SPORT_SQUASHCOURT", "Sport - Squash court", ""),
310+
("SPORT_SMALLSWIMMINGPOOL", "Sport - Small swimming pool", ""),
311+
("SPORT_LARGESWIMMINGPOOL", "Sport - Large swimming pool", ""),
312+
("SPORT_GYMNASIUM", "Sport - Gymnasium", ""),
313+
("SPORT_FULLSTADIUM", "Sport - Full stadium", ""),
314+
("SPORT_STADIUMTANNOY", "Sport - Stadium tannoy", ""),
315+
("PREFAB_WORKSHOP", "Prefab - Workshop", ""),
316+
("PREFAB_SCHOOLROOM", "Prefab - Schoolroom", ""),
317+
("PREFAB_PRACTISEROOM", "Prefab - Practise room", ""),
318+
("PREFAB_OUTHOUSE", "Prefab - Outhouse", ""),
319+
("PREFAB_CARAVAN", "Prefab - Zandi's Trailer", ""),
320+
("DOME_TOMB", "Tomb dome", ""),
321+
("DOME_SAINTPAULS", "St Paul's Dome", ""),
322+
("PIPE_SMALL", "Pipe - small", ""),
323+
("PIPE_LONGTHIN", "Pipe - long & thin", ""),
324+
("PIPE_LARGE", "Pipe - large", ""),
325+
("PIPE_RESONANT", "Pipe - resonant", ""),
326+
("OUTDOORS_BACKYARD", "Outdoors - Backyard", ""),
327+
("OUTDOORS_ROLLINGPLAINS", "Outdoors - Rolling plains", ""),
328+
("OUTDOORS_DEEPCANYON", "Outdoors - Deep canyon", ""),
329+
("OUTDOORS_CREEK", "Outdoors - Creek", ""),
330+
("OUTDOORS_VALLEY", "Outdoors - Valley", ""),
331+
("MOOD_HEAVEN", "Mood - Heaven", ""),
332+
("MOOD_HELL", "Mood - Hell", ""),
333+
("MOOD_MEMORY", "Mood - Memory", ""),
334+
("DRIVING_COMMENTATOR", "Driving - Commentator", ""),
335+
("DRIVING_PITGARAGE", "Driving - In pit garage", ""),
336+
("DRIVING_INCAR_RACER", "Driving - In racer car", ""),
337+
("DRIVING_INCAR_SPORTS", "Driving - In sports car", ""),
338+
("DRIVING_INCAR_LUXURY", "Driving - In luxury car", ""),
339+
("DRIVING_FULLGRANDSTAND", "Driving - Full grand stand", ""),
340+
("DRIVING_EMPTYGRANDSTAND", "Driving - Empty grand stand", ""),
341+
("DRIVING_TUNNEL", "Driving - Tunnel", ""),
342+
("CITY_STREETS", "City - Streets", ""),
343+
("CITY_SUBWAY", "City - Subway", ""),
344+
("CITY_MUSEUM", "City - Museum", ""),
345+
("CITY_LIBRARY", "City - Library", ""),
346+
("CITY_UNDERPASS", "City - Underpass", ""),
347+
("CITY_ABANDONED", "City - Abandoned", ""),
348+
("DUSTYROOM", "Dusty room", ""),
349+
("CHAPEL", "Chapel", ""),
350+
("SMALLWATERROOM", "Small water room", ""),
351+
("CUSTOM", "Custom", "Setup your own environment")],
352+
default="GENERIC",
353+
options=set())
354+
355+
environment_size = FloatProperty(name="Environment Size", description="Environment Size",
356+
default=7.5, min=1.0, max=100.0,
357+
options=set())
358+
environment_diffusion = FloatProperty(name="Environment Diffusion", description="Environment Diffusion",
359+
default=1.0, min=0.0, max=1.0,
360+
options=set())
361+
room = IntProperty(name="Room", description="Room",
362+
default=-1000, min=-10000, max=0,
363+
options=set())
364+
room_hf = IntProperty(name="Room HF", description="Room High Frequency",
365+
default=-100, min=-10000, max=0,
366+
options=set())
367+
room_lf = IntProperty(name="Room LF", description="Room Low Frequency",
368+
default=0, min=-10000, max=0,
369+
options=set())
370+
decay_time = FloatProperty(name="Decay Time", description="Decay Time",
371+
default=1.49, min=0.1, max=20.0,
372+
options=set())
373+
decay_hf_ratio = FloatProperty(name="Decay HF Ratio", description="Decay High Frequency Ratio",
374+
default=0.83, min=0.1, max=2.0,
375+
options=set())
376+
decay_lf_ratio = FloatProperty(name="Decay LF Ratio", description="Decay Low Frequency Ratio",
377+
default=1.0, min=0.1, max=2.0,
378+
options=set())
379+
reflections = IntProperty(name="Reflections", description="Reflections",
380+
default=-2602, min=-10000, max=1000,
381+
options=set())
382+
reflections_delay = FloatProperty(name="Reflections Delay", description="Reflections Delay",
383+
default=0.007, min=0.0, max=0.3,
384+
options=set())
385+
reverb = IntProperty(name="Reverb", description="Reverb",
386+
default=200, min=-10000, max=2000,
387+
options=set())
388+
reverb_delay = FloatProperty(name="Reverb Delay", description="Reverb Delay",
389+
default=0.011, min=0.0, max=0.3,
390+
options=set())
391+
echo_time = FloatProperty(name="Echo Time", description="Echo Time",
392+
default=0.25, min=0.1, max=0.5,
393+
options=set())
394+
echo_depth = FloatProperty(name="Echo Depth", description="Echo Depth",
395+
default=0.0, min=0.0, max=1.0,
396+
options=set())
397+
modulation_time = FloatProperty(name="Modulation Time", description="Modulation Time",
398+
default=0.25, min=0.1, max=5.0,
399+
options=set())
400+
modulation_depth = FloatProperty(name="Modulation Depth", description="Modulation Depth",
401+
default=0.0, min=0.0, max=1.0,
402+
options=set())
403+
air_absorption_hf = FloatProperty(name="Air Absorption HF", description="Air Absorption High Frequency",
404+
default=-5.0, min=-10.0, max=0.0,
405+
options=set())
406+
hf_reference = FloatProperty(name="HF reference", description="High Frequency Reference",
407+
default=5000.0, min=1000.0, max=20000.0,
408+
options=set())
409+
lf_reference = FloatProperty(name="LF reference", description="Low Frequency Reference",
410+
default=250.0, min=20.0, max=1000.0,
411+
options=set())
412+
413+
flags = EnumProperty(name="Flags",
414+
description="Reverb flags",
415+
items=reverb_flags,
416+
default={"kFlagDecayTimeScale", "kFlagReflectionsScale", "kFlagReflectionsDelayScale",
417+
"kFlagReverbScale", "kFlagReverbDelayScale", "kFlagEchoTimeScale"},
418+
options={"ENUM_FLAG"})
419+
420+
def export(self, exporter, bo, so):
421+
eax_listener = exporter.mgr.find_create_object(plEAXListenerMod, so=so)
422+
eax_listener.softRegion = bo.plasma_modifiers.softvolume.get_key(exporter, so)
423+
if self.preset == "CUSTOM":
424+
# Someone's feeling exceedingly confident today...
425+
props = EAXReverbProperties()
426+
props.environment = 26
427+
props.environmentSize = self.environment_size
428+
props.environmentDiffusion = self.environment_diffusion
429+
props.room = self.room
430+
props.roomHF = self.room_hf
431+
props.roomLF = self.room_lf
432+
props.decayTime = self.decay_time
433+
props.decayHFRatio = self.decay_hf_ratio
434+
props.decayLFRatio = self.decay_lf_ratio
435+
props.reflections = self.reflections
436+
props.reflectionsDelay = self.reflections_delay
437+
props.reverb = self.reverb
438+
props.reverbDelay = self.reverb_delay
439+
props.echoTime = self.echo_time
440+
props.echoDepth = self.echo_depth
441+
props.modulationTime = self.modulation_time
442+
props.modulationDepth = self.modulation_depth
443+
props.airAbsorptionHF = self.air_absorption_hf
444+
props.hfReference = self.hf_reference
445+
props.lfReference = self.lf_reference
446+
for flag in self.flags:
447+
props.flags |= getattr(EAXReverbProperties, flag)
448+
eax_listener.listenerProps = props
449+
else:
450+
eax_listener.listenerProps = getattr(EAXReverbProperties, "REVERB_PRESET_{}".format(self.preset))
451+
452+
218453
class PlasmaSoftVolume(idprops.IDPropMixin, PlasmaModifierProperties):
219454
pl_id = "softvolume"
220455

korman/properties/modifiers/sound.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,12 @@ def _update_name(self, context=None):
285285
options={"ANIMATABLE"},
286286
subtype="PERCENTAGE")
287287

288+
reverb_amount = IntProperty(name="Reverb amount",
289+
description="Amount of reverb to apply to this sound (at 0%, reverb volume is reduced by 100 dB and thus disabled)",
290+
min=0, max=100, default=100,
291+
options=set(),
292+
subtype="PERCENTAGE")
293+
288294
fade_in = PointerProperty(type=PlasmaSfxFade, options=set())
289295
fade_out = PointerProperty(type=PlasmaSfxFade, options=set())
290296

@@ -425,6 +431,21 @@ def _convert_sound(self, exporter, so, pClass, wavHeader, dataSize, channel=None
425431
else:
426432
sound.channel = plWin32Sound.kRightChannel
427433

434+
# Reverb/EAX
435+
if self.sfx_type in {"kSoundFX", "kNPCVoices"} and self.reverb_amount > 0:
436+
eax = sound.eaxSettings
437+
eax.enable = True
438+
# Occlusion: the minimum is -100 dB (but the value is multiplied by 100 in EAX's API)
439+
eax.room = int(-10000 * (1 - (self.reverb_amount / 100.0)))
440+
441+
# I couldn't get doppler effect working ingame, nor could I figure out how soft
442+
# starts/ends are supposed to work in conjunction with the soft region.
443+
# If you have more infos about those, feel free to share.
444+
445+
# Make sure we use sensible defaults for soft starts/ends
446+
eax.softStarts.reset()
447+
eax.softEnds.reset()
448+
428449
# Whew, that was a lot of work!
429450
return sound.key
430451

korman/ui/modifiers/region.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,36 @@ def paniclink(modifier, layout, context):
4848
_draw_bounds_prop(modifier, layout, context)
4949
layout.prop(modifier, "play_anim")
5050

51+
def reverb(modifier, layout, context):
52+
layout.prop(modifier, "preset")
53+
if modifier.preset == "MORE":
54+
layout.prop(modifier, "preset_more")
55+
elif modifier.preset == "CUSTOM":
56+
split = layout.split()
57+
colA = split.column()
58+
colB = split.column()
59+
colA.prop(modifier, "environment_size")
60+
colA.prop(modifier, "environment_diffusion")
61+
colB.prop(modifier, "room")
62+
colB.prop(modifier, "room_hf")
63+
colB.prop(modifier, "room_lf")
64+
colA.prop(modifier, "decay_time")
65+
colA.prop(modifier, "decay_hf_ratio")
66+
colA.prop(modifier, "decay_lf_ratio")
67+
colB.prop(modifier, "reflections")
68+
colB.prop(modifier, "reflections_delay")
69+
colB.prop(modifier, "reverb")
70+
colB.prop(modifier, "reverb_delay")
71+
colA.prop(modifier, "echo_time")
72+
colA.prop(modifier, "echo_depth")
73+
colA.prop(modifier, "modulation_time")
74+
colA.prop(modifier, "modulation_depth")
75+
colA.prop(modifier, "air_absorption_hf")
76+
colB.prop(modifier, "hf_reference")
77+
colB.prop(modifier, "lf_reference")
78+
# colB.prop(modifier, "room_rolloff_factor")
79+
layout.prop(modifier, "flags")
80+
5181
def softvolume(modifier, layout, context):
5282
row = layout.row()
5383
row.prop(modifier, "use_nodes", text="", icon="NODETREE")

korman/ui/modifiers/sound.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,10 @@ def soundemit(modifier, layout, context):
117117
col.separator()
118118
_draw_fade_ui(sound.fade_out, col, "Fade Out:")
119119

120+
if sound.sfx_type in {"kSoundFX", "kNPCVoices"}:
121+
col.separator()
122+
col.prop(sound, "reverb_amount", text="Reverb Amount")
123+
120124
col = split.column()
121125
col.label("Cone Effect:")
122126
col.prop(sound, "inner_cone")

0 commit comments

Comments
 (0)