Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AudioEffectReverb causes clipping due to output energy not matching input energy #88051

Open
Tracked by #76797
lander-vr opened this issue Feb 7, 2024 · 0 comments
Open
Tracked by #76797

Comments

@lander-vr
Copy link
Contributor

lander-vr commented Feb 7, 2024

Tested versions

v4.2.1.stable.official [b09f793]

System information

Godot v4.2.1.stable - Windows 10.0.19045 - Vulkan (Forward+) - dedicated NVIDIA GeForce RTX 2060 (NVIDIA; 31.0.15.3758) - AMD Ryzen 5 5600X 6-Core Processor (12 Threads)

Issue description

The total energy of the output of the AudioEffectReverb does not match the total energy of the input, which, despite setting up the filter dry + wet so they equals 1, results in an increases of sound energy.
Even when completely cutting out the dry sound this issue persists. With the audio file in this particular example, the wet value starts to introduce clipping at ~0.25.

When dry + wet = 1, the expected result is a loudness that is (relatively) equal to the loudness of the input, and not an increase in loudness. This would be consistent with reverb filters elsewhere, such as the default Ableton reverb, of which the loudness of the output, despite a reverb setup with a long tail of 5 seconds, at any dry/wet mixture represents the loudness of the input.

This combined with the limiter introducing clipping instead of preventing it (#36631) means that there is no reliable way to prevent this clipping from happening. To prevent this the user can: decrease the volume of the AudioStreamPlayer which drastically affects how the sound is perceived, or reduce the reverb wet signal depending on the audio stream being played to match the loudness to the dry signal, which is unrealistic when you consider that an undefined and unclear amount of any AudioStreamPlayers may be routed into a single bus through e.g. an Area3D bus override.

I have found clipping seems to happen faster with certain audio files, particularly with audio that either has a wide frequency range, or strong low frequencies. I will try to do more tests on this when I have more time.

I think it would make sense for the fix to combine the individual Dry and Wet sliders into a single Dry/Wet slider. I cannot think of a scenario where you would want a reverb filter to affect the energy of a sound, especially not when it means it can introduce unwanted distortion through clipping.
I would say an energy-preserving Dry/Wet slider also makes more sense for people who are less familiar with audio filters, who might not know that these are mix values that should sum up to 1 to maintain sound energy. Even the default setting being at Dry = 1 and Wet = 0.5 do not follow that logic.

It might also be worth noting that unexpected increases in volume, clipping, or unexpected audio behavior in general can be a legitimate cause for hearing damage. My MRP and attached video showcases the effect of just a single AudioPlayer being affected by this.

My audio example was exported from Ableton with a -6dB reduction and a limiter at -6dB. It was normalized on import in Godot. Consisting of an organ and a small choir, it contains a wide frequency range.

Showcase video (I'm not sure why my video isn't embedded):

WARNING: since this showcases clipping, you might want to be nice to your ears and make sure your volume is turned down a bit
https://github.com/godotengine/godot/assets/31851431/b79c0368-0943-4185-9740-1784dc5d8254

Steps to reproduce

  • Add reverb effect to bus
  • Create AudioStreamPlayer, assign a stream and route into bus.

Minimal reproduction project (MRP)

Issue Audio Clipping.zip

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants