summaryrefslogtreecommitdiff
path: root/servers/audio
diff options
context:
space:
mode:
authorJuan Linietsky <reduzio@gmail.com>2017-01-22 20:39:53 -0300
committerJuan Linietsky <reduzio@gmail.com>2017-01-22 20:39:53 -0300
commit4d9bc8b00cd9a561005ad145b3b95c58d4fbfa00 (patch)
treebc720e17ea0ea2055e4a02d8443518658795385a /servers/audio
parent4d944b499675976c0c91ed7c414621dfcea5a285 (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.cpp41
-rw-r--r--servers/audio/effects/audio_effect_compressor.h8
-rw-r--r--servers/audio/effects/audio_effect_limiter.cpp124
-rw-r--r--servers/audio/effects/audio_effect_limiter.h58
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