/*************************************************************************/ /* reverb.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* 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. */ /*************************************************************************/ // Author: Juan Linietsky , (C) 2006 #include "reverb.h" #include #include "math_funcs.h" const float Reverb::comb_tunings[MAX_COMBS]={ //freeverb comb tunings 0.025306122448979593, 0.026938775510204082, 0.028956916099773241, 0.03074829931972789, 0.032244897959183672, 0.03380952380952381, 0.035306122448979592, 0.036666666666666667 }; const float Reverb::allpass_tunings[MAX_ALLPASS]={ //freeverb allpass tunings 0.0051020408163265302, 0.007732426303854875, 0.01, 0.012607709750566893 }; void Reverb::process(float *p_src,float *p_dst,int p_frames) { if (p_frames>INPUT_BUFFER_MAX_SIZE) p_frames=INPUT_BUFFER_MAX_SIZE; int predelay_frames=lrint((params.predelay/1000.0)*params.mix_rate); if (predelay_frames<10) predelay_frames=10; if (predelay_frames>=echo_buffer_size) predelay_frames=echo_buffer_size-1; for (int i=0;i=echo_buffer_size) echo_buffer_pos=0; int read_pos=echo_buffer_pos-predelay_frames; while (read_pos<0) read_pos+=echo_buffer_size; float in=undenormalise(echo_buffer[read_pos]*params.predelay_fb+p_src[i]); echo_buffer[echo_buffer_pos]=in; input_buffer[i]=in; p_dst[i]=0; //take the chance and clear this echo_buffer_pos++; } if (params.hpf>0) { float hpaux=expf(-2.0*Math_PI*params.hpf*6000/params.mix_rate); float hp_a1=(1.0+hpaux)/2.0; float hp_a2=-(1.0+hpaux)/2.0; float hp_b1=hpaux; for (int i=0;i=size_limit) //reset this now just in case c.pos=0; float out=undenormalise(c.buffer[c.pos]*c.feedback); out=out*(1.0-c.damp)+c.damp_h*c.damp; //lowpass c.damp_h=out; c.buffer[c.pos]=input_buffer[j]+out; p_dst[j]+=out; c.pos++; } } static const float allpass_feedback=0.7; /* this one works, but the other version is just nicer.... int ap_size_limit[MAX_ALLPASS]; for (int i=0;ipos>=ap_size_limit[m_ap]) \ ap->pos=0; \ aux=undenormalise(ap->buffer[ap->pos]); \ in=sample; \ sample=-in+aux; \ ap->pos++; PROCESS_ALLPASS(0); PROCESS_ALLPASS(1); PROCESS_ALLPASS(2); PROCESS_ALLPASS(3); p_dst[i]=sample; } */ for (int i=0;i=size_limit) a.pos=0; float aux=a.buffer[a.pos]; a.buffer[a.pos]=undenormalise(allpass_feedback*aux+p_dst[j]); p_dst[j]=aux-allpass_feedback*a.buffer[a.pos]; a.pos++; } } static const float wet_scale=0.6; for (int i=0;i1) p_frq=1; if (p_frq<0) p_frq=0; params.hpf=p_frq; } void Reverb::set_extra_spread(float p_spread) { params.extra_spread=p_spread; } void Reverb::set_mix_rate(float p_mix_rate) { params.mix_rate=p_mix_rate; configure_buffers(); } void Reverb::set_extra_spread_base(float p_sec) { params.extra_spread_base=p_sec; configure_buffers(); } void Reverb::configure_buffers() { clear_buffers(); //clear if necesary for (int i=0;i(room_offset+room_scale)) c.feedback=(room_offset+room_scale); float auxdmp=params.damp/2.0+0.5; //only half the range (0.5 .. 1.0 is enough) auxdmp*=auxdmp; c.damp=expf(-2.0*Math_PI*auxdmp*10000/params.mix_rate); // 0 .. 10khz } } void Reverb::clear_buffers() { if (echo_buffer) memdelete_arr(echo_buffer); for (int i=0;i