summaryrefslogtreecommitdiff
path: root/servers/audio/effects/audio_effect_limiter.cpp
blob: 5cd02682abc36c7d25fb5d370b2b00bd8e6582ed (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
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;
}