| 
									
										
										
										
											2017-03-05 15:47:28 +01:00
										 |  |  | /*************************************************************************/ | 
					
						
							|  |  |  | /*  audio_effect_chorus.cpp                                              */ | 
					
						
							|  |  |  | /*************************************************************************/ | 
					
						
							|  |  |  | /*                       This file is part of:                           */ | 
					
						
							|  |  |  | /*                           GODOT ENGINE                                */ | 
					
						
							| 
									
										
										
										
											2017-08-27 14:16:55 +02:00
										 |  |  | /*                      https://godotengine.org                          */ | 
					
						
							| 
									
										
										
										
											2017-03-05 15:47:28 +01:00
										 |  |  | /*************************************************************************/ | 
					
						
							| 
									
										
										
										
											2021-01-01 20:13:46 +01:00
										 |  |  | /* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur.                 */ | 
					
						
							|  |  |  | /* Copyright (c) 2014-2021 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.                */ | 
					
						
							|  |  |  | /*************************************************************************/ | 
					
						
							| 
									
										
										
										
											2018-01-05 00:50:27 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-22 11:19:56 -03:00
										 |  |  | #include "audio_effect_chorus.h"
 | 
					
						
							| 
									
										
										
										
											2018-09-11 18:13:45 +02:00
										 |  |  | #include "core/math/math_funcs.h"
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | #include "servers/audio_server.h"
 | 
					
						
							| 
									
										
										
										
											2017-01-22 11:19:56 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | void AudioEffectChorusInstance::process(const AudioFrame *p_src_frames, AudioFrame *p_dst_frames, int p_frame_count) { | 
					
						
							| 
									
										
										
										
											2017-01-22 11:19:56 -03:00
										 |  |  | 	int todo = p_frame_count; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	while (todo) { | 
					
						
							|  |  |  | 		int to_mix = MIN(todo, 256); //can't mix too much
 | 
					
						
							| 
									
										
										
										
											2017-01-22 11:19:56 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		_process_chunk(p_src_frames, p_dst_frames, to_mix); | 
					
						
							| 
									
										
										
										
											2017-01-22 11:19:56 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		p_src_frames += to_mix; | 
					
						
							|  |  |  | 		p_dst_frames += to_mix; | 
					
						
							| 
									
										
										
										
											2017-01-22 11:19:56 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		todo -= to_mix; | 
					
						
							| 
									
										
										
										
											2017-01-22 11:19:56 -03:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | void AudioEffectChorusInstance::_process_chunk(const AudioFrame *p_src_frames, AudioFrame *p_dst_frames, int p_frame_count) { | 
					
						
							| 
									
										
										
										
											2017-01-22 11:19:56 -03:00
										 |  |  | 	//fill ringbuffer
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	for (int i = 0; i < p_frame_count; i++) { | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | 		audio_buffer.write[(buffer_pos + i) & buffer_mask] = p_src_frames[i]; | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		p_dst_frames[i] = p_src_frames[i] * base->dry; | 
					
						
							| 
									
										
										
										
											2017-01-22 11:19:56 -03:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	float mix_rate = AudioServer::get_singleton()->get_mix_rate(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* process voices */ | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	for (int vc = 0; vc < base->voice_count; vc++) { | 
					
						
							|  |  |  | 		AudioEffectChorus::Voice &v = base->voice[vc]; | 
					
						
							| 
									
										
										
										
											2017-01-22 11:19:56 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		double time_to_mix = (float)p_frame_count / mix_rate; | 
					
						
							|  |  |  | 		double cycles_to_mix = time_to_mix * v.rate; | 
					
						
							| 
									
										
										
										
											2017-01-22 11:19:56 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		unsigned int local_rb_pos = buffer_pos; | 
					
						
							|  |  |  | 		AudioFrame *dst_buff = p_dst_frames; | 
					
						
							| 
									
										
										
										
											2017-11-25 00:07:54 -03:00
										 |  |  | 		AudioFrame *rb_buff = audio_buffer.ptrw(); | 
					
						
							| 
									
										
										
										
											2017-01-22 11:19:56 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		double delay_msec = v.delay; | 
					
						
							|  |  |  | 		unsigned int delay_frames = Math::fast_ftoi((delay_msec / 1000.0) * mix_rate); | 
					
						
							|  |  |  | 		float max_depth_frames = (v.depth / 1000.0) * mix_rate; | 
					
						
							| 
									
										
										
										
											2017-01-22 11:19:56 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		uint64_t local_cycles = cycles[vc]; | 
					
						
							|  |  |  | 		uint64_t increment = llrint(cycles_to_mix / (double)p_frame_count * (double)(1 << AudioEffectChorus::CYCLES_FRAC)); | 
					
						
							| 
									
										
										
										
											2017-01-22 11:19:56 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-24 21:45:31 +01:00
										 |  |  | 		//check the LFO doesn't read ahead of the write pos
 | 
					
						
							| 
									
										
										
										
											2017-08-31 23:30:35 +02:00
										 |  |  | 		if ((((unsigned int)max_depth_frames) + 10) > delay_frames) { //10 as some threshold to avoid precision stuff
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 			delay_frames += (int)max_depth_frames - delay_frames; | 
					
						
							|  |  |  | 			delay_frames += 10; //threshold to avoid precision stuff
 | 
					
						
							| 
									
										
										
										
											2017-01-22 11:19:56 -03:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		//low pass filter
 | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 		if (v.cutoff == 0) { | 
					
						
							| 
									
										
										
										
											2017-01-22 11:19:56 -03:00
										 |  |  | 			continue; | 
					
						
							| 
									
										
										
										
											2020-05-14 16:41:43 +02:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-04-03 05:50:40 -04:00
										 |  |  | 		float auxlp = expf(-Math_TAU * v.cutoff / mix_rate); | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		float c1 = 1.0 - auxlp; | 
					
						
							|  |  |  | 		float c2 = auxlp; | 
					
						
							|  |  |  | 		AudioFrame h = filter_h[vc]; | 
					
						
							|  |  |  | 		if (v.cutoff >= AudioEffectChorus::MS_CUTOFF_MAX) { | 
					
						
							|  |  |  | 			c1 = 1.0; | 
					
						
							|  |  |  | 			c2 = 0.0; | 
					
						
							| 
									
										
										
										
											2017-01-22 11:19:56 -03:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		//vol modifier
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		AudioFrame vol_modifier = AudioFrame(base->wet, base->wet) * Math::db2linear(v.level); | 
					
						
							|  |  |  | 		vol_modifier.l *= CLAMP(1.0 - v.pan, 0, 1); | 
					
						
							|  |  |  | 		vol_modifier.r *= CLAMP(1.0 + v.pan, 0, 1); | 
					
						
							| 
									
										
										
										
											2017-01-22 11:19:56 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		for (int i = 0; i < p_frame_count; i++) { | 
					
						
							| 
									
										
										
										
											2017-01-22 11:19:56 -03:00
										 |  |  | 			/** COMPUTE WAVEFORM **/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 			float phase = (float)(local_cycles & AudioEffectChorus::CYCLES_MASK) / (float)(1 << AudioEffectChorus::CYCLES_FRAC); | 
					
						
							| 
									
										
										
										
											2017-01-22 11:19:56 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-03 05:50:40 -04:00
										 |  |  | 			float wave_delay = sinf(phase * Math_TAU) * max_depth_frames; | 
					
						
							| 
									
										
										
										
											2017-01-22 11:19:56 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 			int wave_delay_frames = lrint(floor(wave_delay)); | 
					
						
							|  |  |  | 			float wave_delay_frac = wave_delay - (float)wave_delay_frames; | 
					
						
							| 
									
										
										
										
											2017-01-22 11:19:56 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			/** COMPUTE RINGBUFFER POS**/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 			unsigned int rb_source = local_rb_pos; | 
					
						
							|  |  |  | 			rb_source -= delay_frames; | 
					
						
							| 
									
										
										
										
											2017-01-22 11:19:56 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 			rb_source -= wave_delay_frames; | 
					
						
							| 
									
										
										
										
											2017-01-22 11:19:56 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			/** READ FROM RINGBUFFER, LINEARLY INTERPOLATE */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 			AudioFrame val = rb_buff[rb_source & buffer_mask]; | 
					
						
							|  |  |  | 			AudioFrame val_next = rb_buff[(rb_source - 1) & buffer_mask]; | 
					
						
							| 
									
										
										
										
											2017-01-22 11:19:56 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 			val += (val_next - val) * wave_delay_frac; | 
					
						
							| 
									
										
										
										
											2017-01-22 11:19:56 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 			val = val * c1 + h * c2; | 
					
						
							|  |  |  | 			h = val; | 
					
						
							| 
									
										
										
										
											2017-01-22 11:19:56 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			/** MIX VALUE TO OUTPUT **/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 			dst_buff[i] += val * vol_modifier; | 
					
						
							| 
									
										
										
										
											2017-01-22 11:19:56 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 			local_cycles += increment; | 
					
						
							| 
									
										
										
										
											2017-01-22 11:19:56 -03:00
										 |  |  | 			local_rb_pos++; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		filter_h[vc] = h; | 
					
						
							|  |  |  | 		cycles[vc] += Math::fast_ftoi(cycles_to_mix * (double)(1 << AudioEffectChorus::CYCLES_FRAC)); | 
					
						
							| 
									
										
										
										
											2017-01-22 11:19:56 -03:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	buffer_pos += p_frame_count; | 
					
						
							| 
									
										
										
										
											2017-01-22 11:19:56 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Ref<AudioEffectInstance> AudioEffectChorus::instance() { | 
					
						
							|  |  |  | 	Ref<AudioEffectChorusInstance> ins; | 
					
						
							|  |  |  | 	ins.instance(); | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	ins->base = Ref<AudioEffectChorus>(this); | 
					
						
							|  |  |  | 	for (int i = 0; i < 4; i++) { | 
					
						
							|  |  |  | 		ins->filter_h[i] = AudioFrame(0, 0); | 
					
						
							|  |  |  | 		ins->cycles[i] = 0; | 
					
						
							| 
									
										
										
										
											2017-01-22 11:19:56 -03:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	float ring_buffer_max_size = AudioEffectChorus::MAX_DELAY_MS + AudioEffectChorus::MAX_DEPTH_MS + AudioEffectChorus::MAX_WIDTH_MS; | 
					
						
							| 
									
										
										
										
											2017-01-22 11:19:56 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	ring_buffer_max_size *= 2; //just to avoid complications
 | 
					
						
							|  |  |  | 	ring_buffer_max_size /= 1000.0; //convert to seconds
 | 
					
						
							|  |  |  | 	ring_buffer_max_size *= AudioServer::get_singleton()->get_mix_rate(); | 
					
						
							| 
									
										
										
										
											2017-01-22 11:19:56 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	int ringbuff_size = ring_buffer_max_size; | 
					
						
							| 
									
										
										
										
											2017-01-22 11:19:56 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	int bits = 0; | 
					
						
							| 
									
										
										
										
											2017-01-22 11:19:56 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	while (ringbuff_size > 0) { | 
					
						
							| 
									
										
										
										
											2017-01-22 11:19:56 -03:00
										 |  |  | 		bits++; | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		ringbuff_size /= 2; | 
					
						
							| 
									
										
										
										
											2017-01-22 11:19:56 -03:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	ringbuff_size = 1 << bits; | 
					
						
							|  |  |  | 	ins->buffer_mask = ringbuff_size - 1; | 
					
						
							|  |  |  | 	ins->buffer_pos = 0; | 
					
						
							| 
									
										
										
										
											2017-01-22 11:19:56 -03:00
										 |  |  | 	ins->audio_buffer.resize(ringbuff_size); | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	for (int i = 0; i < ringbuff_size; i++) { | 
					
						
							| 
									
										
										
										
											2018-07-25 03:11:03 +02:00
										 |  |  | 		ins->audio_buffer.write[i] = AudioFrame(0, 0); | 
					
						
							| 
									
										
										
										
											2017-01-22 11:19:56 -03:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return ins; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void AudioEffectChorus::set_voice_count(int p_voices) { | 
					
						
							| 
									
										
										
										
											2017-09-25 20:39:41 +07:00
										 |  |  | 	ERR_FAIL_COND(p_voices < 1 || p_voices > MAX_VOICES); | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	voice_count = p_voices; | 
					
						
							| 
									
										
										
										
											2017-01-22 11:19:56 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | int AudioEffectChorus::get_voice_count() const { | 
					
						
							| 
									
										
										
										
											2017-01-22 11:19:56 -03:00
										 |  |  | 	return voice_count; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | void AudioEffectChorus::set_voice_delay_ms(int p_voice, float p_delay_ms) { | 
					
						
							|  |  |  | 	ERR_FAIL_INDEX(p_voice, MAX_VOICES); | 
					
						
							| 
									
										
										
										
											2017-01-22 11:19:56 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	voice[p_voice].delay = p_delay_ms; | 
					
						
							| 
									
										
										
										
											2017-01-22 11:19:56 -03:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2020-05-14 14:29:06 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | float AudioEffectChorus::get_voice_delay_ms(int p_voice) const { | 
					
						
							|  |  |  | 	ERR_FAIL_INDEX_V(p_voice, MAX_VOICES, 0); | 
					
						
							| 
									
										
										
										
											2017-01-22 11:19:56 -03:00
										 |  |  | 	return voice[p_voice].delay; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | void AudioEffectChorus::set_voice_rate_hz(int p_voice, float p_rate_hz) { | 
					
						
							|  |  |  | 	ERR_FAIL_INDEX(p_voice, MAX_VOICES); | 
					
						
							| 
									
										
										
										
											2017-01-22 11:19:56 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	voice[p_voice].rate = p_rate_hz; | 
					
						
							| 
									
										
										
										
											2017-01-22 11:19:56 -03:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2020-05-14 14:29:06 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | float AudioEffectChorus::get_voice_rate_hz(int p_voice) const { | 
					
						
							|  |  |  | 	ERR_FAIL_INDEX_V(p_voice, MAX_VOICES, 0); | 
					
						
							| 
									
										
										
										
											2017-01-22 11:19:56 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return voice[p_voice].rate; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | void AudioEffectChorus::set_voice_depth_ms(int p_voice, float p_depth_ms) { | 
					
						
							|  |  |  | 	ERR_FAIL_INDEX(p_voice, MAX_VOICES); | 
					
						
							| 
									
										
										
										
											2017-01-22 11:19:56 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	voice[p_voice].depth = p_depth_ms; | 
					
						
							| 
									
										
										
										
											2017-01-22 11:19:56 -03:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2020-05-14 14:29:06 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | float AudioEffectChorus::get_voice_depth_ms(int p_voice) const { | 
					
						
							|  |  |  | 	ERR_FAIL_INDEX_V(p_voice, MAX_VOICES, 0); | 
					
						
							| 
									
										
										
										
											2017-01-22 11:19:56 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return voice[p_voice].depth; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | void AudioEffectChorus::set_voice_level_db(int p_voice, float p_level_db) { | 
					
						
							|  |  |  | 	ERR_FAIL_INDEX(p_voice, MAX_VOICES); | 
					
						
							| 
									
										
										
										
											2017-01-22 11:19:56 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	voice[p_voice].level = p_level_db; | 
					
						
							| 
									
										
										
										
											2017-01-22 11:19:56 -03:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2020-05-14 14:29:06 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | float AudioEffectChorus::get_voice_level_db(int p_voice) const { | 
					
						
							|  |  |  | 	ERR_FAIL_INDEX_V(p_voice, MAX_VOICES, 0); | 
					
						
							| 
									
										
										
										
											2017-01-22 11:19:56 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return voice[p_voice].level; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | void AudioEffectChorus::set_voice_cutoff_hz(int p_voice, float p_cutoff_hz) { | 
					
						
							|  |  |  | 	ERR_FAIL_INDEX(p_voice, MAX_VOICES); | 
					
						
							| 
									
										
										
										
											2017-01-22 11:19:56 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	voice[p_voice].cutoff = p_cutoff_hz; | 
					
						
							| 
									
										
										
										
											2017-01-22 11:19:56 -03:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2020-05-14 14:29:06 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | float AudioEffectChorus::get_voice_cutoff_hz(int p_voice) const { | 
					
						
							|  |  |  | 	ERR_FAIL_INDEX_V(p_voice, MAX_VOICES, 0); | 
					
						
							| 
									
										
										
										
											2017-01-22 11:19:56 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return voice[p_voice].cutoff; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | void AudioEffectChorus::set_voice_pan(int p_voice, float p_pan) { | 
					
						
							|  |  |  | 	ERR_FAIL_INDEX(p_voice, MAX_VOICES); | 
					
						
							| 
									
										
										
										
											2017-01-22 11:19:56 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	voice[p_voice].pan = p_pan; | 
					
						
							| 
									
										
										
										
											2017-01-22 11:19:56 -03:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2020-05-14 14:29:06 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | float AudioEffectChorus::get_voice_pan(int p_voice) const { | 
					
						
							|  |  |  | 	ERR_FAIL_INDEX_V(p_voice, MAX_VOICES, 0); | 
					
						
							| 
									
										
										
										
											2017-01-22 11:19:56 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return voice[p_voice].pan; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | void AudioEffectChorus::set_wet(float amount) { | 
					
						
							|  |  |  | 	wet = amount; | 
					
						
							| 
									
										
										
										
											2017-01-22 11:19:56 -03:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2020-05-14 14:29:06 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | float AudioEffectChorus::get_wet() const { | 
					
						
							| 
									
										
										
										
											2017-01-22 11:19:56 -03:00
										 |  |  | 	return wet; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | void AudioEffectChorus::set_dry(float amount) { | 
					
						
							|  |  |  | 	dry = amount; | 
					
						
							| 
									
										
										
										
											2017-01-22 11:19:56 -03:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2020-05-14 14:29:06 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | float AudioEffectChorus::get_dry() const { | 
					
						
							| 
									
										
										
										
											2017-01-22 11:19:56 -03:00
										 |  |  | 	return dry; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | void AudioEffectChorus::_validate_property(PropertyInfo &property) const { | 
					
						
							| 
									
										
										
										
											2017-01-22 11:19:56 -03:00
										 |  |  | 	if (property.name.begins_with("voice/")) { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		int voice_idx = property.name.get_slice("/", 1).to_int(); | 
					
						
							|  |  |  | 		if (voice_idx > voice_count) { | 
					
						
							|  |  |  | 			property.usage = 0; | 
					
						
							| 
									
										
										
										
											2017-01-22 11:19:56 -03:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void AudioEffectChorus::_bind_methods() { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	ClassDB::bind_method(D_METHOD("set_voice_count", "voices"), &AudioEffectChorus::set_voice_count); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("get_voice_count"), &AudioEffectChorus::get_voice_count); | 
					
						
							| 
									
										
										
										
											2017-01-22 11:19:56 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	ClassDB::bind_method(D_METHOD("set_voice_delay_ms", "voice_idx", "delay_ms"), &AudioEffectChorus::set_voice_delay_ms); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("get_voice_delay_ms", "voice_idx"), &AudioEffectChorus::get_voice_delay_ms); | 
					
						
							| 
									
										
										
										
											2017-01-22 11:19:56 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	ClassDB::bind_method(D_METHOD("set_voice_rate_hz", "voice_idx", "rate_hz"), &AudioEffectChorus::set_voice_rate_hz); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("get_voice_rate_hz", "voice_idx"), &AudioEffectChorus::get_voice_rate_hz); | 
					
						
							| 
									
										
										
										
											2017-01-22 11:19:56 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	ClassDB::bind_method(D_METHOD("set_voice_depth_ms", "voice_idx", "depth_ms"), &AudioEffectChorus::set_voice_depth_ms); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("get_voice_depth_ms", "voice_idx"), &AudioEffectChorus::get_voice_depth_ms); | 
					
						
							| 
									
										
										
										
											2017-01-22 11:19:56 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	ClassDB::bind_method(D_METHOD("set_voice_level_db", "voice_idx", "level_db"), &AudioEffectChorus::set_voice_level_db); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("get_voice_level_db", "voice_idx"), &AudioEffectChorus::get_voice_level_db); | 
					
						
							| 
									
										
										
										
											2017-01-22 11:19:56 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	ClassDB::bind_method(D_METHOD("set_voice_cutoff_hz", "voice_idx", "cutoff_hz"), &AudioEffectChorus::set_voice_cutoff_hz); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("get_voice_cutoff_hz", "voice_idx"), &AudioEffectChorus::get_voice_cutoff_hz); | 
					
						
							| 
									
										
										
										
											2017-01-22 11:19:56 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	ClassDB::bind_method(D_METHOD("set_voice_pan", "voice_idx", "pan"), &AudioEffectChorus::set_voice_pan); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("get_voice_pan", "voice_idx"), &AudioEffectChorus::get_voice_pan); | 
					
						
							| 
									
										
										
										
											2017-01-22 11:19:56 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	ClassDB::bind_method(D_METHOD("set_wet", "amount"), &AudioEffectChorus::set_wet); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("get_wet"), &AudioEffectChorus::get_wet); | 
					
						
							| 
									
										
										
										
											2017-01-22 11:19:56 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	ClassDB::bind_method(D_METHOD("set_dry", "amount"), &AudioEffectChorus::set_dry); | 
					
						
							|  |  |  | 	ClassDB::bind_method(D_METHOD("get_dry"), &AudioEffectChorus::get_dry); | 
					
						
							| 
									
										
										
										
											2017-02-12 01:11:37 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	ADD_PROPERTY(PropertyInfo(Variant::INT, "voice_count", PROPERTY_HINT_RANGE, "1,4,1"), "set_voice_count", "get_voice_count"); | 
					
						
							| 
									
										
										
											
												Variant: Added 64-bit packed arrays, renamed Variant::REAL to FLOAT.
- Renames PackedIntArray to PackedInt32Array.
- Renames PackedFloatArray to PackedFloat32Array.
- Adds PackedInt64Array and PackedFloat64Array.
- Renames Variant::REAL to Variant::FLOAT for consistency.
Packed arrays are for storing large amount of data and creating stuff like
meshes, buffers. textures, etc. Forcing them to be 64 is a huge waste of
memory. That said, many users requested the ability to have 64 bits packed
arrays for their games, so this is just an optional added type.
For Variant, the float datatype is always 64 bits, and exposed as `float`.
We still have `real_t` which is the datatype that can change from 32 to 64
bits depending on a compile flag (not entirely working right now, but that's
the idea). It affects math related datatypes and code only.
Neither Variant nor PackedArray make use of real_t, which is only intended
for math precision, so the term is removed from there to keep only float.
											
										 
											2020-02-24 15:20:53 -03:00
										 |  |  | 	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "dry", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_dry", "get_dry"); | 
					
						
							|  |  |  | 	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "wet", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_wet", "get_wet"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/1/delay_ms", PROPERTY_HINT_RANGE, "0,50,0.01"), "set_voice_delay_ms", "get_voice_delay_ms", 0); | 
					
						
							|  |  |  | 	ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/1/rate_hz", PROPERTY_HINT_RANGE, "0.1,20,0.1"), "set_voice_rate_hz", "get_voice_rate_hz", 0); | 
					
						
							|  |  |  | 	ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/1/depth_ms", PROPERTY_HINT_RANGE, "0,20,0.01"), "set_voice_depth_ms", "get_voice_depth_ms", 0); | 
					
						
							|  |  |  | 	ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/1/level_db", PROPERTY_HINT_RANGE, "-60,24,0.1"), "set_voice_level_db", "get_voice_level_db", 0); | 
					
						
							|  |  |  | 	ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/1/cutoff_hz", PROPERTY_HINT_RANGE, "1,20500,1"), "set_voice_cutoff_hz", "get_voice_cutoff_hz", 0); | 
					
						
							|  |  |  | 	ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/1/pan", PROPERTY_HINT_RANGE, "-1,1,0.01"), "set_voice_pan", "get_voice_pan", 0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/2/delay_ms", PROPERTY_HINT_RANGE, "0,50,0.01"), "set_voice_delay_ms", "get_voice_delay_ms", 1); | 
					
						
							|  |  |  | 	ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/2/rate_hz", PROPERTY_HINT_RANGE, "0.1,20,0.1"), "set_voice_rate_hz", "get_voice_rate_hz", 1); | 
					
						
							|  |  |  | 	ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/2/depth_ms", PROPERTY_HINT_RANGE, "0,20,0.01"), "set_voice_depth_ms", "get_voice_depth_ms", 1); | 
					
						
							|  |  |  | 	ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/2/level_db", PROPERTY_HINT_RANGE, "-60,24,0.1"), "set_voice_level_db", "get_voice_level_db", 1); | 
					
						
							|  |  |  | 	ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/2/cutoff_hz", PROPERTY_HINT_RANGE, "1,20500,1"), "set_voice_cutoff_hz", "get_voice_cutoff_hz", 1); | 
					
						
							|  |  |  | 	ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/2/pan", PROPERTY_HINT_RANGE, "-1,1,0.01"), "set_voice_pan", "get_voice_pan", 1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/3/delay_ms", PROPERTY_HINT_RANGE, "0,50,0.01"), "set_voice_delay_ms", "get_voice_delay_ms", 2); | 
					
						
							|  |  |  | 	ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/3/rate_hz", PROPERTY_HINT_RANGE, "0.1,20,0.1"), "set_voice_rate_hz", "get_voice_rate_hz", 2); | 
					
						
							|  |  |  | 	ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/3/depth_ms", PROPERTY_HINT_RANGE, "0,20,0.01"), "set_voice_depth_ms", "get_voice_depth_ms", 2); | 
					
						
							|  |  |  | 	ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/3/level_db", PROPERTY_HINT_RANGE, "-60,24,0.1"), "set_voice_level_db", "get_voice_level_db", 2); | 
					
						
							|  |  |  | 	ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/3/cutoff_hz", PROPERTY_HINT_RANGE, "1,20500,1"), "set_voice_cutoff_hz", "get_voice_cutoff_hz", 2); | 
					
						
							|  |  |  | 	ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/3/pan", PROPERTY_HINT_RANGE, "-1,1,0.01"), "set_voice_pan", "get_voice_pan", 2); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/4/delay_ms", PROPERTY_HINT_RANGE, "0,50,0.01"), "set_voice_delay_ms", "get_voice_delay_ms", 3); | 
					
						
							|  |  |  | 	ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/4/rate_hz", PROPERTY_HINT_RANGE, "0.1,20,0.1"), "set_voice_rate_hz", "get_voice_rate_hz", 3); | 
					
						
							|  |  |  | 	ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/4/depth_ms", PROPERTY_HINT_RANGE, "0,20,0.01"), "set_voice_depth_ms", "get_voice_depth_ms", 3); | 
					
						
							|  |  |  | 	ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/4/level_db", PROPERTY_HINT_RANGE, "-60,24,0.1"), "set_voice_level_db", "get_voice_level_db", 3); | 
					
						
							|  |  |  | 	ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/4/cutoff_hz", PROPERTY_HINT_RANGE, "1,20500,1"), "set_voice_cutoff_hz", "get_voice_cutoff_hz", 3); | 
					
						
							|  |  |  | 	ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/4/pan", PROPERTY_HINT_RANGE, "-1,1,0.01"), "set_voice_pan", "get_voice_pan", 3); | 
					
						
							| 
									
										
										
										
											2017-01-22 11:19:56 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | AudioEffectChorus::AudioEffectChorus() { | 
					
						
							|  |  |  | 	voice_count = 2; | 
					
						
							|  |  |  | 	voice[0].delay = 15; | 
					
						
							|  |  |  | 	voice[1].delay = 20; | 
					
						
							|  |  |  | 	voice[0].rate = 0.8; | 
					
						
							|  |  |  | 	voice[1].rate = 1.2; | 
					
						
							|  |  |  | 	voice[0].depth = 2; | 
					
						
							|  |  |  | 	voice[1].depth = 3; | 
					
						
							|  |  |  | 	voice[0].cutoff = 8000; | 
					
						
							|  |  |  | 	voice[1].cutoff = 8000; | 
					
						
							|  |  |  | 	voice[0].pan = -0.5; | 
					
						
							|  |  |  | 	voice[1].pan = 0.5; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	wet = 0.5; | 
					
						
							|  |  |  | 	dry = 1.0; | 
					
						
							| 
									
										
										
										
											2017-01-22 11:19:56 -03:00
										 |  |  | } |