| 
									
										
										
										
											2017-03-05 15:47:28 +01:00
										 |  |  | /*************************************************************************/ | 
					
						
							|  |  |  | /*  audio_effect_limiter.cpp                                             */ | 
					
						
							|  |  |  | /*************************************************************************/ | 
					
						
							|  |  |  | /*                       This file is part of:                           */ | 
					
						
							|  |  |  | /*                           GODOT ENGINE                                */ | 
					
						
							|  |  |  | /*                    http://www.godotengine.org                         */ | 
					
						
							|  |  |  | /*************************************************************************/ | 
					
						
							|  |  |  | /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur.                 */ | 
					
						
							| 
									
										
										
										
											2017-04-08 00:11:42 +02:00
										 |  |  | /* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md)    */ | 
					
						
							| 
									
										
										
										
											2017-03-05 15:47:28 +01:00
										 |  |  | /*                                                                       */ | 
					
						
							|  |  |  | /* Permission is hereby granted, free of charge, to any person obtaining */ | 
					
						
							|  |  |  | /* a copy of this software and associated documentation files (the       */ | 
					
						
							|  |  |  | /* "Software"), to deal in the Software without restriction, including   */ | 
					
						
							|  |  |  | /* without limitation the rights to use, copy, modify, merge, publish,   */ | 
					
						
							|  |  |  | /* distribute, sublicense, and/or sell copies of the Software, and to    */ | 
					
						
							|  |  |  | /* permit persons to whom the Software is furnished to do so, subject to */ | 
					
						
							|  |  |  | /* the following conditions:                                             */ | 
					
						
							|  |  |  | /*                                                                       */ | 
					
						
							|  |  |  | /* The above copyright notice and this permission notice shall be        */ | 
					
						
							|  |  |  | /* included in all copies or substantial portions of the Software.       */ | 
					
						
							|  |  |  | /*                                                                       */ | 
					
						
							|  |  |  | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */ | 
					
						
							|  |  |  | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */ | 
					
						
							|  |  |  | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ | 
					
						
							|  |  |  | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */ | 
					
						
							|  |  |  | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */ | 
					
						
							|  |  |  | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */ | 
					
						
							|  |  |  | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */ | 
					
						
							|  |  |  | /*************************************************************************/ | 
					
						
							| 
									
										
										
										
											2017-01-22 20:39:53 -03:00
										 |  |  | #include "audio_effect_limiter.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | void AudioEffectLimiterInstance::process(const AudioFrame *p_src_frames, AudioFrame *p_dst_frames, int p_frame_count) { | 
					
						
							| 
									
										
										
										
											2017-01-22 20:39:53 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	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)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	for (int i = 0; i < p_frame_count; i++) { | 
					
						
							| 
									
										
										
										
											2017-01-22 20:39:53 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		float spl0 = p_src_frames[i].l; | 
					
						
							|  |  |  | 		float spl1 = p_src_frames[i].r; | 
					
						
							|  |  |  | 		spl0 = spl0 * makeup; | 
					
						
							|  |  |  | 		spl1 = spl1 * makeup; | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		float sign0 = (spl0 < 0.0 ? -1.0 : 1.0); | 
					
						
							|  |  |  | 		float sign1 = (spl1 < 0.0 ? -1.0 : 1.0); | 
					
						
							| 
									
										
										
										
											2017-01-22 20:39:53 -03:00
										 |  |  | 		float abs0 = Math::abs(spl0); | 
					
						
							|  |  |  | 		float abs1 = Math::abs(spl1); | 
					
						
							|  |  |  | 		float overdb0 = Math::linear2db(abs0) - ceildb; | 
					
						
							|  |  |  | 		float overdb1 = Math::linear2db(abs1) - ceildb; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		if (abs0 > scv) { | 
					
						
							| 
									
										
										
										
											2017-01-22 20:39:53 -03:00
										 |  |  | 			spl0 = sign0 * (scv + Math::db2linear(overdb0 * scmult)); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		if (abs1 > scv) { | 
					
						
							| 
									
										
										
										
											2017-01-22 20:39:53 -03:00
										 |  |  | 			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(); | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	ins->base = Ref<AudioEffectLimiter>(this); | 
					
						
							| 
									
										
										
										
											2017-01-22 20:39:53 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return ins; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void AudioEffectLimiter::set_treshold_db(float p_treshold) { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	treshold = p_treshold; | 
					
						
							| 
									
										
										
										
											2017-01-22 20:39:53 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | float AudioEffectLimiter::get_treshold_db() const { | 
					
						
							| 
									
										
										
										
											2017-01-22 20:39:53 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return treshold; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | void AudioEffectLimiter::set_ceiling_db(float p_ceiling) { | 
					
						
							| 
									
										
										
										
											2017-01-22 20:39:53 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	ceiling = p_ceiling; | 
					
						
							| 
									
										
										
										
											2017-01-22 20:39:53 -03:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | float AudioEffectLimiter::get_ceiling_db() const { | 
					
						
							| 
									
										
										
										
											2017-01-22 20:39:53 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return ceiling; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | void AudioEffectLimiter::set_soft_clip_db(float p_soft_clip) { | 
					
						
							| 
									
										
										
										
											2017-01-22 20:39:53 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	soft_clip = p_soft_clip; | 
					
						
							| 
									
										
										
										
											2017-01-22 20:39:53 -03:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | float AudioEffectLimiter::get_soft_clip_db() const { | 
					
						
							| 
									
										
										
										
											2017-01-22 20:39:53 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return soft_clip; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | void AudioEffectLimiter::set_soft_clip_ratio(float p_soft_clip) { | 
					
						
							| 
									
										
										
										
											2017-01-22 20:39:53 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	soft_clip_ratio = p_soft_clip; | 
					
						
							| 
									
										
										
										
											2017-01-22 20:39:53 -03:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | float AudioEffectLimiter::get_soft_clip_ratio() const { | 
					
						
							| 
									
										
										
										
											2017-01-22 20:39:53 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return soft_clip; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void AudioEffectLimiter::_bind_methods() { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	ClassDB::bind_method(D_METHOD("set_ceiling_db", "ceiling"), &AudioEffectLimiter::set_ceiling_db); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("get_ceiling_db"), &AudioEffectLimiter::get_ceiling_db); | 
					
						
							| 
									
										
										
										
											2017-01-22 20:39:53 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	ClassDB::bind_method(D_METHOD("set_treshold_db", "treshold"), &AudioEffectLimiter::set_treshold_db); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("get_treshold_db"), &AudioEffectLimiter::get_treshold_db); | 
					
						
							| 
									
										
										
										
											2017-01-22 20:39:53 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	ClassDB::bind_method(D_METHOD("set_soft_clip_db", "soft_clip"), &AudioEffectLimiter::set_soft_clip_db); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("get_soft_clip_db"), &AudioEffectLimiter::get_soft_clip_db); | 
					
						
							| 
									
										
										
										
											2017-01-22 20:39:53 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	ClassDB::bind_method(D_METHOD("set_soft_clip_ratio", "soft_clip"), &AudioEffectLimiter::set_soft_clip_ratio); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("get_soft_clip_ratio"), &AudioEffectLimiter::get_soft_clip_ratio); | 
					
						
							| 
									
										
										
										
											2017-01-22 20:39:53 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	ADD_PROPERTY(PropertyInfo(Variant::REAL, "ceiling_db", PROPERTY_HINT_RANGE, "-20,-0.1,0.1"), "set_ceiling_db", "get_ceiling_db"); | 
					
						
							|  |  |  | 	ADD_PROPERTY(PropertyInfo(Variant::REAL, "treshold_db", PROPERTY_HINT_RANGE, "-30,0,0.1"), "set_treshold_db", "get_treshold_db"); | 
					
						
							|  |  |  | 	ADD_PROPERTY(PropertyInfo(Variant::REAL, "soft_clip_db", PROPERTY_HINT_RANGE, "0,6,0.1"), "set_soft_clip_db", "get_soft_clip_db"); | 
					
						
							|  |  |  | 	ADD_PROPERTY(PropertyInfo(Variant::REAL, "soft_clip_ratio", PROPERTY_HINT_RANGE, "3,20,0.1"), "set_soft_clip_ratio", "get_soft_clip_ratio"); | 
					
						
							| 
									
										
										
										
											2017-01-22 20:39:53 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | AudioEffectLimiter::AudioEffectLimiter() { | 
					
						
							|  |  |  | 	treshold = 0; | 
					
						
							|  |  |  | 	ceiling = -0.1; | 
					
						
							|  |  |  | 	soft_clip = 2; | 
					
						
							|  |  |  | 	soft_clip_ratio = 10; | 
					
						
							| 
									
										
										
										
											2017-01-22 20:39:53 -03:00
										 |  |  | } |