audio_effect_limiter.cpp 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. /**************************************************************************/
  2. /* audio_effect_limiter.cpp */
  3. /**************************************************************************/
  4. /* This file is part of: */
  5. /* GODOT ENGINE */
  6. /* https://godotengine.org */
  7. /**************************************************************************/
  8. /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
  9. /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
  10. /* */
  11. /* Permission is hereby granted, free of charge, to any person obtaining */
  12. /* a copy of this software and associated documentation files (the */
  13. /* "Software"), to deal in the Software without restriction, including */
  14. /* without limitation the rights to use, copy, modify, merge, publish, */
  15. /* distribute, sublicense, and/or sell copies of the Software, and to */
  16. /* permit persons to whom the Software is furnished to do so, subject to */
  17. /* the following conditions: */
  18. /* */
  19. /* The above copyright notice and this permission notice shall be */
  20. /* included in all copies or substantial portions of the Software. */
  21. /* */
  22. /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
  23. /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
  24. /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
  25. /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
  26. /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
  27. /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
  28. /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
  29. /**************************************************************************/
  30. #include "audio_effect_limiter.h"
  31. void AudioEffectLimiterInstance::process(const AudioFrame *p_src_frames, AudioFrame *p_dst_frames, int p_frame_count) {
  32. float threshdb = base->threshold;
  33. float ceiling = Math::db2linear(base->ceiling);
  34. float ceildb = base->ceiling;
  35. float makeup = Math::db2linear(ceildb - threshdb);
  36. float sc = -base->soft_clip;
  37. float scv = Math::db2linear(sc);
  38. float peakdb = ceildb + 25;
  39. float scmult = Math::abs((ceildb - sc) / (peakdb - sc));
  40. for (int i = 0; i < p_frame_count; i++) {
  41. float spl0 = p_src_frames[i].l;
  42. float spl1 = p_src_frames[i].r;
  43. spl0 = spl0 * makeup;
  44. spl1 = spl1 * makeup;
  45. float sign0 = (spl0 < 0.0 ? -1.0 : 1.0);
  46. float sign1 = (spl1 < 0.0 ? -1.0 : 1.0);
  47. float abs0 = Math::abs(spl0);
  48. float abs1 = Math::abs(spl1);
  49. float overdb0 = Math::linear2db(abs0) - ceildb;
  50. float overdb1 = Math::linear2db(abs1) - ceildb;
  51. if (abs0 > scv) {
  52. spl0 = sign0 * (scv + Math::db2linear(overdb0 * scmult));
  53. }
  54. if (abs1 > scv) {
  55. spl1 = sign1 * (scv + Math::db2linear(overdb1 * scmult));
  56. }
  57. spl0 = MIN(ceiling, Math::abs(spl0)) * (spl0 < 0.0 ? -1.0 : 1.0);
  58. spl1 = MIN(ceiling, Math::abs(spl1)) * (spl1 < 0.0 ? -1.0 : 1.0);
  59. p_dst_frames[i].l = spl0;
  60. p_dst_frames[i].r = spl1;
  61. }
  62. }
  63. Ref<AudioEffectInstance> AudioEffectLimiter::instance() {
  64. Ref<AudioEffectLimiterInstance> ins;
  65. ins.instance();
  66. ins->base = Ref<AudioEffectLimiter>(this);
  67. return ins;
  68. }
  69. void AudioEffectLimiter::set_threshold_db(float p_threshold) {
  70. threshold = p_threshold;
  71. }
  72. float AudioEffectLimiter::get_threshold_db() const {
  73. return threshold;
  74. }
  75. void AudioEffectLimiter::set_ceiling_db(float p_ceiling) {
  76. ceiling = p_ceiling;
  77. }
  78. float AudioEffectLimiter::get_ceiling_db() const {
  79. return ceiling;
  80. }
  81. void AudioEffectLimiter::set_soft_clip_db(float p_soft_clip) {
  82. soft_clip = p_soft_clip;
  83. }
  84. float AudioEffectLimiter::get_soft_clip_db() const {
  85. return soft_clip;
  86. }
  87. void AudioEffectLimiter::set_soft_clip_ratio(float p_soft_clip) {
  88. soft_clip_ratio = p_soft_clip;
  89. }
  90. float AudioEffectLimiter::get_soft_clip_ratio() const {
  91. return soft_clip_ratio;
  92. }
  93. void AudioEffectLimiter::_bind_methods() {
  94. ClassDB::bind_method(D_METHOD("set_ceiling_db", "ceiling"), &AudioEffectLimiter::set_ceiling_db);
  95. ClassDB::bind_method(D_METHOD("get_ceiling_db"), &AudioEffectLimiter::get_ceiling_db);
  96. ClassDB::bind_method(D_METHOD("set_threshold_db", "threshold"), &AudioEffectLimiter::set_threshold_db);
  97. ClassDB::bind_method(D_METHOD("get_threshold_db"), &AudioEffectLimiter::get_threshold_db);
  98. ClassDB::bind_method(D_METHOD("set_soft_clip_db", "soft_clip"), &AudioEffectLimiter::set_soft_clip_db);
  99. ClassDB::bind_method(D_METHOD("get_soft_clip_db"), &AudioEffectLimiter::get_soft_clip_db);
  100. ClassDB::bind_method(D_METHOD("set_soft_clip_ratio", "soft_clip"), &AudioEffectLimiter::set_soft_clip_ratio);
  101. ClassDB::bind_method(D_METHOD("get_soft_clip_ratio"), &AudioEffectLimiter::get_soft_clip_ratio);
  102. ADD_PROPERTY(PropertyInfo(Variant::REAL, "ceiling_db", PROPERTY_HINT_RANGE, "-20,-0.1,0.1"), "set_ceiling_db", "get_ceiling_db");
  103. ADD_PROPERTY(PropertyInfo(Variant::REAL, "threshold_db", PROPERTY_HINT_RANGE, "-30,0,0.1"), "set_threshold_db", "get_threshold_db");
  104. ADD_PROPERTY(PropertyInfo(Variant::REAL, "soft_clip_db", PROPERTY_HINT_RANGE, "0,6,0.1"), "set_soft_clip_db", "get_soft_clip_db");
  105. ADD_PROPERTY(PropertyInfo(Variant::REAL, "soft_clip_ratio", PROPERTY_HINT_RANGE, "3,20,0.1"), "set_soft_clip_ratio", "get_soft_clip_ratio");
  106. }
  107. AudioEffectLimiter::AudioEffectLimiter() {
  108. threshold = 0;
  109. ceiling = -0.1;
  110. soft_clip = 2;
  111. soft_clip_ratio = 10;
  112. }