assaultcube / AC

AssaultCube
846 stars 215 forks source link

Reverb in game? #209

Open Noah11012 opened 4 years ago

Noah11012 commented 4 years ago

I want to contribute to AC and in order to do so I need to learn the code base which can take a long time especially with the mess that this one is. Also, I am no where ready to do anything with graphics and 3D rendering yet so maybe I could do something with the sound. So, I thought adding reverb would help add something positive to the overall feel of the game. The easiest way I can think of to accomplish this is to have three different reverb versions for specific sounds like shooting and reloading for the weapons and additionally, footsteps, landing, jumping, and any other way a player could make noise by moving around. The three types of reverb would be small, medium and large. Small would be played in a small room, medium would be played in a medium sized room, and large would be played in a large room. To make the reverb happen, each file that will have one will be processed by an audio program like Audacity by adding the reverb effect to the clip and saving it in the same folder as the base sound. I've already toyed around with this a bit and while I'm not 100% happy with any of them, they do look promising. Hopefully, this can bring AC more to par with other more modern games that feature reverb. Would anybody be interested in this?

Noah11012 commented 4 years ago

Also, if you have better access and knowledge to something better than Audacity and can produce better reverb effects, maybe create some and show them on youtube or something.

Noah11012 commented 4 years ago

So, I cobbled together a bunch of clips from different maps using the reverb effect I used in Audacity. https://www.youtube.com/watch?v=774xLhBGcvs

Tell me after you watch the video which spots feel better suited for the reverb used in the video.

Noah11012 commented 4 years ago

Made a new video to show how the game would feel if footsteps, jumping and landing all added reverb.

https://www.youtube.com/watch?v=keWBIsb83_g

Enjoy!

Noah11012 commented 4 years ago

After almost a month passing by without anything getting done, I found out that OpenAL through an extension called EFX can actually add reverberation to any sound! I've implemented it in AssaultCube along side with some debug commands to quickly change the reverb's properties without having to close the application and tweak the values in the code and compile it again.

Definitely very excited as this will bring us one step closer to getting reverb in AssaultCube. I hope to get a video uploaded to my YouTube channel about this progress in the following week or so. But knowing that I still have some more reverb properties to add and play around with and needing to record and edit the footage I'm not too sure when it will come out.

Noah11012 commented 4 years ago

Three days have passed and I've made a new video showcasing the new reverberation in AssaultCube! I'll link the video below but here I'll do a small change log.

Link to the YouTube video: https://www.youtube.com/watch?v=dTeOLGlk-mU

Noah11012 commented 4 years ago

Also, any criticisms and suggestions for the reverb that was shown in the latest Youtube video? Is it too loud or does it actually sound like a reverb from a stone room, etc.

aurhat commented 4 years ago

Quite impressive effect, in the last video it's though too loud. :)

Noah11012 commented 4 years ago

@aurhat Thank you! And as for the volume of the reverb I can definitely turn it down to something more reasonable and wouldn't be a drain on the players' ears. I wanted to make sure the reverb came through so I maxed the volume inside AssaultCube (volume = 255) and the gain for the reverb was 1.0 (that is the max and the default is 0.32). The next step is allowing the placement of "markers" around the map that tell which reverb properties to use.

drian0 commented 3 years ago

@Noah11012 Thank you for this nice showcase. Is OpenAL EAX supported on all relevant platforms. Also, is it supported for OpenAL-Soft?

Noah11012 commented 3 years ago

@drian0 I could't find any information on which platforms support OpenAL EAX or EFX. By the way, you can find the differences between EAX and EFX here and here.

As for being supported by OpenAL-Soft, it seems like it is as evidence by this C source file in the examples folder: https://github.com/kcat/openal-soft/blob/master/examples/almultireverb.c

drian0 commented 3 years ago

Thanks for sharing these materials. What are your thoughts regarding tools for mappers? How would you create entities or other elements so that mappers can add this fx to their maps? I think as a natural next step we should think about how we could embed this into the game.

Noah11012 commented 3 years ago

I've only thought briefly as how mappers could add reverb to their maps. Like I said previously on this thread, is to add "markers" or "entities" that change the properties of sound within a radius or area. At the edges, some sort of "lerping" can be done to smooth out the transition from a non reverb area to an area with reverb or from one room with a set of reverb properties to another room with different reverb properties. Obviously, I'm open to better alternatives. How it works right now is that all sounds get processed to have a reverb.

drian0 commented 3 years ago

I am not a mapper myself but I assume that we need an "area" meaning a NxM cubes surface so that things like a tunnel can be implemented properly. I am not sure if we need a radial distribution.

If I remember correctly we do not have infrastructure in place yet to flag floor cubes arbitrarily to define such an area. A more suitable approach might be adding reverb entities with a "square length" parameter. That means a reverb entity denotes the center of a given square. So to add reverb to a tunnel of 8x32 cubes you would add 4 reverb entities along the tunnel, each with a square length of 8. And then we might need more parameters for intensity and fadeout. This is just from the top of my head.

How about you approach some of the mappers in the community to discuss this and then come up with a prototype? This looks promising.

Noah11012 commented 3 years ago

So, after a whole lot of browsing the code base and not understanding anything especially how entities work in the game, I finally have something very rudimentary and will need a lot of work put into it.

In the map editor, it is now possible to place a reverb entity at the location of the cursor. You can't change any properties of the reverb. It is just a very simple and basic reverb. The gain or how prevalent the reverb sounds is calculated based on distance. This calculation is very much just for testing and we will need something way better.

Reverb gain should be calculated not based on the center which is the location of the reverb entity, but the edge of the NxM rectangle. Like mentioned before in this thread, there can be transitionary phase to make entering a place with reverb smoother and not too harsh on the player.

And one important thing to keep in mind: reverb is calculated based on camera1. Which means if you are in a room with no reverb and you throw a grenade into a room with reverb, the bounce and explosion of the grenade will have no reverb.

Some ideas and things that need to be done:

  1. When adding/editing a reverb, a popup box similar that of the popup box for adding/editing light entities should appear. It will provide several presets for the mapper to pick from and/or to fine tune the reverb to their liking.
  2. Use the selection as the area for the reverb entity. I feel this is the easiest way to do this.
  3. Save reverb entities to the map file.

Though I'm not too sure if we should use the selection for the area. There might be a problem with it or maybe I'm just being silly.

drian0 commented 3 years ago

Reverb gain should be calculated not based on the center which is the location of the reverb entity, but the edge of the NxM rectangle.

So in editmode, you could select a NxM rectangle on the floor and then type in the console:

/newent reverb X

This would create an entity with type reverb, the dimensions of the inner reverb rectangle are based on your NxM selection. The outer fade-in/out rectangle would have a dimension of (N+X)x(M+X)

This could be encoded into the entity as follows:

Like mentioned before in this thread, there can be transitionary phase to make entering a place with reverb smoother and not too harsh on the player.

So you would do a linear fade-out/fade-in? Or some other easing function?

And one important thing to keep in mind: reverb is calculated based on camera1. Which means if you are in a room with no reverb and you throw a grenade into a room with reverb, the bounce and explosion of the grenade will have no reverb.

I understand. I think that tradeoff is ok. Do I understand it correctly, if you are within the reverb rectangle then ALL sound you hear will have reverb applied to it? That means, not just your footsteps and your shooting has reverb, but also sounds coming from outside the rectangle.

Noah11012 commented 3 years ago

So in editmode, you could select a NxM rectangle on the floor and then type in the console:

/newent reverb X

This would create an entity with type reverb, the dimensions of the inner reverb rectangle are based on your NxM selection. The outer fade-in/out rectangle would have a dimension of (N+X)x(M+X)

This could be encoded into the entity as follows:

x/y/z denoting the center of the reverb rectangle. Z is ignored since we do calculation in 2D. attr1 distance between the inner reverb rectangle and the outer fade-in/out rectangle, measured in cubes attr2 side N of the inner reverb rectangle, measured in cubes attr3 size M of the inner reverb rectangle, measured in cubes

Honestly, it doesn't seem like a bad idea at all!

So you would do a linear fade-out/fade-in? Or some other easing function?

Right now it is linear but we could do something different. Maybe allow the user to pick or nah?

I understand. I think that tradeoff is ok. Do I understand it correctly, if you are within the reverb rectangle then ALL sound you hear will have reverb applied to it? That means, not just your footsteps and your shooting has reverb, but also sounds coming from outside the rectangle.

Yes, every and all sounds that are played in the game are processed with a reverb. From menu sounds when you scroll through the menu items to other players making sounds inside or outside the rectangle.

Noah11012 commented 3 years ago

Oh, and another thing that needs to be solved: how do we add the reverb properties to the entity? There are currently 11 properties:

  1. Decay
  2. Density
  3. Echo Depth
  4. Echo Time
  5. Diffusion
  6. Gain
  7. Delay
  8. Decay LF
  9. Decay HF
  10. LF Reference
  11. HF Reference

We can definitely ignore the last four properties for now. We just the need the first 9 properties.

drian0 commented 3 years ago

You could outsource the full reverb definitions to the map .cfg file and the entity only contains a pointer to that definition.

For example, in the .cfg of the map you could have something like:

resetreverbs
registerreverb 123 123 123 123 123 ...
registerreverb 234 234 234 234 234 ...
...

And then in the ingame editor you would say /newent reverb 0

this would then reference the first reverb definition in the list. It is similarly done for mapmodels and textures.

Btw, in AC 1.3 (branch release_1.3) the map format has changed. The there is no more external .cfg file for the map but the config is embeeded into the .cgz map file.

Noah11012 commented 3 years ago

That actually might be the way we go and like you said, this is done for map models and textures so it would sync up perfectly. However, I was going to approach it a difference way using bitwise operations.

The first attribute, attr1 is a short and on most modern systems they are two bytes. I figured out that maybe we could store the values there and if any are left over we could store them in the other attribute variables. But after some thinking it didn't seem as feasible and easy like the idea you suggested. Plus, cubescript can't do bitwise operations.

Noah11012 commented 3 years ago

Hey, do you know any places where I can ask programming/development questions/help about AC?

Punjara commented 3 years ago

Oh, and another thing that needs to be solved: how do we add the reverb properties to the entity? There are currently 11 properties:

1. Decay

2. Density

3. Echo Depth

4. Echo Time

5. Diffusion

6. Gain

7. Delay

8. Decay LF

9. Decay HF

10. LF Reference

11. HF Reference

We can definitely ignore the last four properties for now. We just the need the first 9 properties.

Decay, density and echo are the main body of the reverb...you can club them together with one value, and another for Gain or (Mix) with original signal. You only need to tweak 2 properties or may be gain only ? You can tie these parameters with the entity box's size ? Bigger the size bigger the reverb ?

Noah11012 commented 3 years ago

The reason why I listed all those properties is because I want to give the mapper a lot of control over how the reverb sounds. Those are just the eleven properties that I listed and for now we can ignore the last four and focus on the rest. However, there are a lot more reverb properties than the ones presented here.

You can tie these parameters with the entity box's size ? Bigger the size bigger the reverb ?

Not a bad idea to tie the value of gain or decay or both to the size of the entity's size. However, that still leaves a lot of reverb properties to be manually set or use the default/preset values and tweak from there.

Noah11012 commented 3 years ago

Decay, density and echo are the main body of the reverb...you can club them together with one value

What do you mean by "club them together with one value"?

RonaldReagan commented 3 years ago

Hey, do you know any places where I can ask programming/development questions/help about AC?

On the main website of AC there is a discord link. I believe most if not all active developers are on that discord server.

Noah11012 commented 3 years ago

@RonaldReagan Thanks!

u0043 commented 3 years ago

I really do like the idea of expanding AC's sonic landscape, but to be honest, I'm not convinced about the approach outlined above.

As a mapper I wouldn't want to manage entities for physic based audio effects manually. Besides that, looking at the mostly poor use of the comparatively simple ambient sounds in AC-mapping I have serious doubts mappers will ever get this set up correctly. Therefore, reverb should be baked into the engine, rather than being an additional asset on the editing side of things.

In order to create a simple, yet somewhat realistic reverb effect, you would at least need to calculate the distance between sound sources and the listener (player) and adjust the filters accordingly. So every sound in a certain range will have a reverb effect applied relative to the listener's and sources' positions, not dependant on a static volume (i.e. reverb entity). That would still leave the surrounding geometry out of the equation. But this already should come closer to how sound actually works than the entity approach and not put the workload onto the mappers shoulders, but onto the CPU.

Maybe it wouldn't be that complicated to expand this basic implementation and taking geometry (i.e. size of the room where the sound occurs, walls between source and listener) into account, given that volumes can be calculated rather easily for AC geometry.

As a musician with some experience in recording and mixing I know a bit or two about psychoacoustics, like how to dial in a reverb processor to make it sound rather natural. Not saying I am an expert, far from it, but maybe I could help finding the right settings for the reverb filters if we ever get there. :)

drian0 commented 3 years ago

I understand that you prefer an automated solution over a manual solution. But how would you do it in a way that works reliably across all maps - what formula would you apply?

I think that in order to make an automated solution work reliably you would need to come up with a significant extension of the engine. For example, you would need to apply material information to all cubes in all maps. A grass floor does impact reverb significantly different than a concrete wall. And a flag mapmodels has a different impact than a bridge mapmodel. And even if you take all these things into account you might get strange reverbs in certain rooms and you will want to rectify that manually. You could compare this to lighting, which is highly unrealistic (it is 2D in fact) and needs to be done in a manual fashion as well.

Maybe there could still be reverb entities as outlined but some of its attributes could be pre-calculated to ease the process and to make a more consistent experience across maps?

Punjara commented 3 years ago

or just add three presets for 'Small', 'Medium' and 'Large' for simplifying stuff. Don't give any more control, as reverberation can be overdone if not done correctly.

Noah11012 commented 3 years ago

@Punjara The plan is to give the mapper control for most properties of a reverb but have several reverb presets for different environments like rooms mostly made out of ceramic tiling, stone, or metal. Then for each of those you would have small, medium and large.

Then from there is you wanted to you can tweak the values until you get something you like.

Noah11012 commented 3 years ago

While it would be great to have the game engine calculate and dynamically change the reverb properties depending where the ceiling, ground and walls are relative to the players and their distance, like drian0 said, it would require giving all textures material info and extending the engine somewhat significantly.

For now the plan is to interpolate the reverb's gain and possibly other properties based on the distance from the edge of the reverb entity. Say you have a reverb entity that expands 10x10 cubes then how prevalent depends on how close you get to the edge.

u0043 commented 3 years ago

I have been thinking about this and probably found a way in the middle to potentially have the strong points of both approaches combined. This might get a little long, but please bear with me. The following is based on the premiss that the characteristics of reverb can be separated into shape and color.

The shape is mainly defined by a reverb's

which is mainly dependant on

=> Can be calculated using the maps' geometry data and the positions of the sound sources and the listener

The color is mainly defined by a reverb's

which is mainly dependant on

=> Requires material information the engine does not provide as-is, but could be provided through mappers using reverb-entities like outlined above.

The shape would basically be hardwired into the engine and taken care of by an algorithm. This formula could be based on a very simplified 2D chunck-tree calculated from solids and non-solids, for instance. Therefore mappers won't have to fiddle around getting all the physics based aspects right to make it sound realistic. Besides that, there won't be drastic differences in reverb styles across different maps.

The default reverb color, when there is nothing configured by a mapper, could be designed to be rather subtle and smooth. That is, barely audible, so it's more like players get a feeling of three dimensionality subconsciously, than really hearing the effect. For how this default setting could sound like, picture how a map would sound if all walls were made of concrete covered with rigips: rigips)

The color would be where the mappers can get creative and how we get around implementing a fully fledged material system.

From a mapper's perspective I'd like to be able to set one 'world' reverb-color for the entire map (a little like /ambientlight), which will be used whenever there's a sound not located within a reverb entity. Then I'd set reverb entities in areas where this world configuration won't fit in order to fine tune things. Unlike with ambient lighting, the 'local' reverb entities would simply overwrite the 'world' settings.

Picture ac_desert, this might work with one setting for most outside areas and only three more entities for enclosed rooms with rock ceilings and one more fore the well.

The entities could work like clip entities, configured in-game during editing. Instead of registering variations in the config, there should be the full set of parameters available to mappers. In order to make things easier it would make sense to provide a config file with presets, which can be expanded per client. Selecting and applying those presets could be handled through a dedicated sub-menu, much like with arches and slopes.

From a technical point of view, the 2D chunk-tree would need to be calculated on each mapload once and for editing purpose only, on demand using something like /recalc. The chunk-tree object would take reverb entities into account and hold all the information needed to calculate reverb modifiers for each sound a player can here.

I do know there's a lot of details to be figured out further down the road, like overlapping entities just to name one. But I couldn't think of any problem that couldn't be solved on way or the other.

So, thanks for reading this far and what do you think?

drian0 commented 3 years ago

To me your idea sounds good. I can not comment on the details as I am not very knowledgeable in audio/physics. I guess there might/will be some pitfalls along the way that need to be addressed once you get there.

The question is, would you @Noah11012 be motivated to implement this together with @cf-1984 ?

Noah11012 commented 3 years ago

@drian0 I'm not 100% on this idea for one reason: I don't know how to implement geometry based reverb or whatever we're doing. Also I've never worked with someone before when it comes to programming. Lastly, I've been working on my own personal projects for now to take a break from this. Hopefully I gain some motivation to continue the work on the reverb stuff soon!

u0043 commented 3 years ago

@Noah11012 , just hit me up, if you ever feel like giving this another try. :)