/* * Copyright (c) 1983-2013 Richard Dobson and Composers Desktop Project Ltd * http://people.bath.ac.uk/masrwd * http://www.composersdesktop.com * This file is part of the CDP System. * The CDP System is free software; you can redistribute it * and/or modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * The CDP System is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General Public * License along with the CDP System; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ //smalldiff.cpp //implements diffuse reverberator for small rooms, based on gardner nested allpasses #include "reverberator.h" small_diffuser::small_diffuser(unsigned int pre_delay, const NESTDATA *apdata1, const NESTDATA *apdata2,double fb_gain,double lp_coeff){ ap1_data = *apdata1; ap2_data = *apdata2; predelay_time = pre_delay; lpgain = fb_gain; lpcoeff = lp_coeff; ap1 = ap2 = 0; lp1 = 0; predelay = 0; out1 = out2 = 0.0f; } small_diffuser::~small_diffuser() { delete ap1; delete ap2; if(predelay) delete predelay; delete lp1; } bool small_diffuser::create(void) { if(ap1_data.time1 == 0 || ap1_data.gain1 <= 0.0) return false; if(ap1_data.time2 ==0 || ap1_data.gain2 <= 0.0) return false; if(ap2_data.time1 == 0 || ap2_data.gain1 < 0.0) return false; if(ap2_data.time2 ==0 || ap2_data.gain2 < 0.0) return false; ap1 = new nested_allpass(ap1_data.time1,ap1_data.time2,ap1_data.time3, ap1_data.gain1,ap1_data.gain2,ap1_data.gain3,ap1_data.delay1,ap1_data.delay2); if(!ap1->create()) return false; if(ap2_data.gain1 != 0.0){ //allow ap to eliminate second block ap2 = new nested_allpass(ap2_data.time1,ap2_data.time2,ap2_data.time3, ap2_data.gain1,ap2_data.gain2,ap2_data.gain3,ap2_data.delay1,ap2_data.delay2); if(!ap2->create()) return false; } if(predelay_time > 0){ predelay = new delay(predelay_time,1.0); if(!predelay->create()) return false; } if(lpcoeff > 0.0) lp1 = new lowpass1(lpcoeff); return true; } float small_diffuser::tick(float insam) { float ip = insam; double temp; if(lp1) temp = lp1->tick((out2 + out1)*0.5f); else temp = (out2 + out1)*0.5f; ip += (float)(lpgain * temp); if(predelay) ip = predelay->tick(ip); out1 = ap1->tick(ip); if(ap2) out2 = ap2->tick(out1); return (out1 + out2) /** 0.5f*/; }