diff options
author | Juan Linietsky <reduzio@gmail.com> | 2017-01-22 20:39:53 -0300 |
---|---|---|
committer | Juan Linietsky <reduzio@gmail.com> | 2017-01-22 20:39:53 -0300 |
commit | 4d9bc8b00cd9a561005ad145b3b95c58d4fbfa00 (patch) | |
tree | bc720e17ea0ea2055e4a02d8443518658795385a /servers/audio | |
parent | 4d944b499675976c0c91ed7c414621dfcea5a285 (diff) |
Added Audio Limiter bus effect, and sidechain ability to compressor.
Diffstat (limited to 'servers/audio')
-rw-r--r-- | servers/audio/effects/audio_effect_compressor.cpp | 41 | ||||
-rw-r--r-- | servers/audio/effects/audio_effect_compressor.h | 8 | ||||
-rw-r--r-- | servers/audio/effects/audio_effect_limiter.cpp | 124 | ||||
-rw-r--r-- | servers/audio/effects/audio_effect_limiter.h | 58 |
4 files changed, 229 insertions, 2 deletions
diff --git a/servers/audio/effects/audio_effect_compressor.cpp b/servers/audio/effects/audio_effect_compressor.cpp index 5a4a8c1bdf..5d116a9543 100644 --- a/servers/audio/effects/audio_effect_compressor.cpp +++ b/servers/audio/effects/audio_effect_compressor.cpp @@ -19,10 +19,19 @@ void AudioEffectCompressorInstance::process(const AudioFrame *p_src_frames,Audio float mix = base->mix; float gr_meter_decay = exp(1 / (1 * sample_rate)); + const AudioFrame *src = p_src_frames; + + if (base->sidechain!=StringName() && current_channel!=-1) { + + int bus = AudioServer::get_singleton()->thread_find_bus_index(base->sidechain); + if (bus>=0) { + src = AudioServer::get_singleton()->thread_get_channel_mix_buffer(bus,current_channel); + } + } for(int i=0;i<p_frame_count;i++) { - AudioFrame s = p_src_frames[i]; + AudioFrame s = src[i]; //convert to positive s.l = Math::abs(s.l); s.r = Math::abs(s.r); @@ -88,6 +97,7 @@ Ref<AudioEffectInstance> AudioEffectCompressor::instance() { ins->runmax=0; ins->maxover=0; ins->gr_meter=1.0; + ins->current_channel=-1; return ins; } @@ -147,6 +157,31 @@ float AudioEffectCompressor::get_mix() const { return mix; } +void AudioEffectCompressor::set_sidechain(const StringName& p_sidechain) { + + AudioServer::get_singleton()->lock(); + sidechain=p_sidechain; + AudioServer::get_singleton()->unlock(); +} + +StringName AudioEffectCompressor::get_sidechain() const { + + return sidechain; +} + +void AudioEffectCompressor::_validate_property(PropertyInfo& property) const { + + if (property.name=="sidechain") { + + String buses=""; + for(int i=0;i<AudioServer::get_singleton()->get_bus_count();i++) { + buses+=","; + buses+=AudioServer::get_singleton()->get_bus_name(i); + } + + property.hint_string=buses; + } +} void AudioEffectCompressor::_bind_methods() { @@ -168,12 +203,16 @@ void AudioEffectCompressor::_bind_methods() { ClassDB::bind_method(_MD("set_mix","mix"),&AudioEffectCompressor::set_mix); ClassDB::bind_method(_MD("get_mix"),&AudioEffectCompressor::get_mix); + ClassDB::bind_method(_MD("set_sidechain","sidechain"),&AudioEffectCompressor::set_sidechain); + ClassDB::bind_method(_MD("get_sidechain"),&AudioEffectCompressor::get_sidechain); + ADD_PROPERTY(PropertyInfo(Variant::REAL,"treshold",PROPERTY_HINT_RANGE,"-60,0,0.1"),_SCS("set_treshold"),_SCS("get_treshold")); ADD_PROPERTY(PropertyInfo(Variant::REAL,"ratio",PROPERTY_HINT_RANGE,"1,48,0.1"),_SCS("set_ratio"),_SCS("get_ratio")); ADD_PROPERTY(PropertyInfo(Variant::REAL,"gain",PROPERTY_HINT_RANGE,"-20,20,0.1"),_SCS("set_gain"),_SCS("get_gain")); ADD_PROPERTY(PropertyInfo(Variant::REAL,"attack_us",PROPERTY_HINT_RANGE,"20,2000,1"),_SCS("set_attack_us"),_SCS("get_attack_us")); ADD_PROPERTY(PropertyInfo(Variant::REAL,"release_ms",PROPERTY_HINT_RANGE,"20,2000,1"),_SCS("set_release_ms"),_SCS("get_release_ms")); ADD_PROPERTY(PropertyInfo(Variant::REAL,"mix",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_mix"),_SCS("get_mix")); + ADD_PROPERTY(PropertyInfo(Variant::REAL,"sidechain",PROPERTY_HINT_ENUM),_SCS("set_sidechain"),_SCS("get_sidechain")); } diff --git a/servers/audio/effects/audio_effect_compressor.h b/servers/audio/effects/audio_effect_compressor.h index 6b0c6a5ed5..eb06b3db77 100644 --- a/servers/audio/effects/audio_effect_compressor.h +++ b/servers/audio/effects/audio_effect_compressor.h @@ -12,8 +12,10 @@ friend class AudioEffectCompressor; Ref<AudioEffectCompressor> base; float rundb,averatio,runratio,runmax,maxover,gr_meter; + int current_channel; public: + void set_current_channel(int p_channel) { current_channel=p_channel; } virtual void process(const AudioFrame *p_src_frames,AudioFrame *p_dst_frames,int p_frame_count); }; @@ -29,10 +31,11 @@ friend class AudioEffectCompressorInstance; float attack_us; float release_ms; float mix; + StringName sidechain; protected: - + void _validate_property(PropertyInfo& property) const; static void _bind_methods(); public: @@ -58,6 +61,9 @@ public: void set_mix(float p_mix); float get_mix() const; + void set_sidechain(const StringName& p_sidechain); + StringName get_sidechain() const; + AudioEffectCompressor(); }; diff --git a/servers/audio/effects/audio_effect_limiter.cpp b/servers/audio/effects/audio_effect_limiter.cpp new file mode 100644 index 0000000000..5cd02682ab --- /dev/null +++ b/servers/audio/effects/audio_effect_limiter.cpp @@ -0,0 +1,124 @@ +#include "audio_effect_limiter.h" + +void AudioEffectLimiterInstance::process(const AudioFrame *p_src_frames,AudioFrame *p_dst_frames,int p_frame_count) { + + float thresh = Math::db2linear(base->treshold); + float threshdb = base->treshold; + float ceiling = Math::db2linear(base->ceiling); + float ceildb = base->ceiling; + float makeup = Math::db2linear(ceildb - threshdb); + float makeupdb = ceildb - threshdb; + float sc = -base->soft_clip; + float scv = Math::db2linear(sc); + float sccomp = Math::db2linear(-sc); + float peakdb = ceildb + 25; + float peaklvl = Math::db2linear(peakdb); + float scratio = base->soft_clip_ratio; + float scmult = Math::abs((ceildb - sc) / (peakdb - sc)); + + for(int i=0;i<p_frame_count;i++) { + + float spl0 = p_src_frames[i].l; + float spl1 = p_src_frames[i].r; + spl0 = spl0 * makeup; + spl1 = spl1 * makeup; + float sign0 = (spl0 < 0.0 ? -1.0 : 1.0 ); + float sign1 = (spl1 < 0.0 ? -1.0 : 1.0 ); + float abs0 = Math::abs(spl0); + float abs1 = Math::abs(spl1); + float overdb0 = Math::linear2db(abs0) - ceildb; + float overdb1 = Math::linear2db(abs1) - ceildb; + + if (abs0 > scv) + { + spl0 = sign0 * (scv + Math::db2linear(overdb0 * scmult)); + } + if (abs1 > scv) + { + spl1 = sign1 * (scv + Math::db2linear(overdb1 * scmult)); + } + + spl0 = MIN(ceiling, Math::abs(spl0)) * (spl0 < 0.0 ? -1.0 : 1.0); + spl1 = MIN(ceiling, Math::abs(spl1)) * (spl1 < 0.0 ? -1.0 : 1.0); + + p_dst_frames[i].l = spl0; + p_dst_frames[i].r = spl1; + } + +} + + +Ref<AudioEffectInstance> AudioEffectLimiter::instance() { + Ref<AudioEffectLimiterInstance> ins; + ins.instance(); + ins->base=Ref<AudioEffectLimiter>(this); + + return ins; +} + + +void AudioEffectLimiter::set_treshold_db(float p_treshold) { + + treshold=p_treshold; +} + +float AudioEffectLimiter::get_treshold_db() const{ + + return treshold; +} + +void AudioEffectLimiter::set_ceiling_db(float p_ceiling){ + + ceiling=p_ceiling; +} +float AudioEffectLimiter::get_ceiling_db() const{ + + return ceiling; +} + +void AudioEffectLimiter::set_soft_clip_db(float p_soft_clip){ + + soft_clip=p_soft_clip; +} +float AudioEffectLimiter::get_soft_clip_db() const{ + + return soft_clip; +} + +void AudioEffectLimiter::set_soft_clip_ratio(float p_soft_clip){ + + soft_clip_ratio=p_soft_clip; +} +float AudioEffectLimiter::get_soft_clip_ratio() const{ + + return soft_clip; +} + + +void AudioEffectLimiter::_bind_methods() { + + ClassDB::bind_method(_MD("set_ceiling_db","ceiling"),&AudioEffectLimiter::set_ceiling_db); + ClassDB::bind_method(_MD("get_ceiling_db"),&AudioEffectLimiter::get_ceiling_db); + + ClassDB::bind_method(_MD("set_treshold_db","treshold"),&AudioEffectLimiter::set_treshold_db); + ClassDB::bind_method(_MD("get_treshold_db"),&AudioEffectLimiter::get_treshold_db); + + ClassDB::bind_method(_MD("set_soft_clip_db","soft_clip"),&AudioEffectLimiter::set_soft_clip_db); + ClassDB::bind_method(_MD("get_soft_clip_db"),&AudioEffectLimiter::get_soft_clip_db); + + ClassDB::bind_method(_MD("set_soft_clip_ratio","soft_clip"),&AudioEffectLimiter::set_soft_clip_ratio); + ClassDB::bind_method(_MD("get_soft_clip_ratio"),&AudioEffectLimiter::get_soft_clip_ratio); + + ADD_PROPERTY(PropertyInfo(Variant::REAL,"ceiling_db",PROPERTY_HINT_RANGE,"-20,-0.1,0.1"),_SCS("set_ceiling_db"),_SCS("get_ceiling_db")); + ADD_PROPERTY(PropertyInfo(Variant::REAL,"treshold_db",PROPERTY_HINT_RANGE,"-30,0,0.1"),_SCS("set_treshold_db"),_SCS("get_treshold_db")); + ADD_PROPERTY(PropertyInfo(Variant::REAL,"soft_clip_db",PROPERTY_HINT_RANGE,"0,6,0.1"),_SCS("set_soft_clip_db"),_SCS("get_soft_clip_db")); + ADD_PROPERTY(PropertyInfo(Variant::REAL,"soft_clip_ratio",PROPERTY_HINT_RANGE,"3,20,0.1"),_SCS("set_soft_clip_ratio"),_SCS("get_soft_clip_ratio")); +} + +AudioEffectLimiter::AudioEffectLimiter() +{ + treshold=0; + ceiling=-0.1; + soft_clip=2; + soft_clip_ratio=10; +} diff --git a/servers/audio/effects/audio_effect_limiter.h b/servers/audio/effects/audio_effect_limiter.h new file mode 100644 index 0000000000..b0d7321205 --- /dev/null +++ b/servers/audio/effects/audio_effect_limiter.h @@ -0,0 +1,58 @@ +#ifndef AUDIO_EFFECT_LIMITER_H +#define AUDIO_EFFECT_LIMITER_H + + +#include "servers/audio/audio_effect.h" + +class AudioEffectLimiter; + +class AudioEffectLimiterInstance : public AudioEffectInstance { + GDCLASS(AudioEffectLimiterInstance,AudioEffectInstance) +friend class AudioEffectLimiter; + Ref<AudioEffectLimiter> base; + + float mix_volume_db; +public: + + virtual void process(const AudioFrame *p_src_frames,AudioFrame *p_dst_frames,int p_frame_count); + +}; + + +class AudioEffectLimiter : public AudioEffect { + GDCLASS(AudioEffectLimiter,AudioEffect) + +friend class AudioEffectLimiterInstance; + float treshold; + float ceiling; + float soft_clip; + float soft_clip_ratio; + +protected: + + static void _bind_methods(); +public: + + + void set_treshold_db(float p_treshold); + float get_treshold_db() const; + + void set_ceiling_db(float p_ceiling); + float get_ceiling_db() const; + + void set_soft_clip_db(float p_soft_clip); + float get_soft_clip_db() const; + + void set_soft_clip_ratio(float p_soft_clip); + float get_soft_clip_ratio() const; + + + Ref<AudioEffectInstance> instance(); + void set_volume_db(float p_volume); + float get_volume_db() const; + + AudioEffectLimiter(); +}; + + +#endif // AUDIO_EFFECT_LIMITER_H |