Marsyas
0.6.0-alpha
|
00001 /* 00002 ** Copyright (C) 1998-2006 George Tzanetakis <gtzan@cs.uvic.ca> 00003 ** 00004 ** This program is free software; you can redistribute it and/or modify 00005 ** it under the terms of the GNU General Public License as published by 00006 ** the Free Software Foundation; either version 2 of the License, or 00007 ** (at your option) any later version. 00008 ** 00009 ** This program is distributed in the hope that it will be useful, 00010 ** but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 ** GNU General Public License for more details. 00013 ** 00014 ** You should have received a copy of the GNU General Public License 00015 ** along with this program; if not, write to the Free Software 00016 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00017 */ 00018 00019 #include "Plucked.h" 00020 #include "../common_source.h" 00021 00022 using std::ostringstream; 00023 using namespace Marsyas; 00024 00025 Plucked::Plucked(mrs_string name):MarSystem("Plucked",name) 00026 { 00027 // Why do these variables exist? 00028 pointer1_ = 0; 00029 pointer2_ = 0; 00030 pointer3_ = 0; 00031 00032 // 00033 a_ = 0; 00034 b_ = 0; 00035 noteon_ = false; 00036 delaylineSize_ = 0; 00037 gain_ = NULL; 00038 00039 addControls(); 00040 } 00041 00042 Plucked::~Plucked() 00043 { 00044 delete gain_; 00045 } 00046 00047 MarSystem* 00048 Plucked::clone() const 00049 { 00050 return new Plucked(*this); 00051 } 00052 00053 void Plucked::addControls() 00054 { 00055 addctrl("mrs_real/frequency", 100.0); 00056 addctrl("mrs_real/pluckpos", 0.5); 00057 addctrl("mrs_real/nton", 0.5); 00058 addctrl("mrs_bool/noteon", false); 00059 addctrl("mrs_real/loss",1.0); 00060 addctrl("mrs_real/stretch",0.2); 00061 setctrlState("mrs_real/frequency", true); 00062 setctrlState("mrs_real/nton", true); 00063 setctrlState("mrs_bool/noteon", true); 00064 setctrlState("mrs_real/loss", true); 00065 } 00066 00067 void Plucked::myUpdate(MarControlPtr sender) 00068 { 00069 mrs_natural t; 00070 MRSDIAG("Plucked.cpp - Plucked:localUpdate"); 00071 00072 MarSystem::myUpdate(sender); 00073 00074 gain_ = new Gain("pluckedGain"); 00075 gain_->updControl("mrs_natural/inSamples", getctrl("mrs_natural/inSamples")); 00076 gain_->updControl("mrs_natural/inSamples", getctrl("mrs_natural/inSamples")); 00077 gain_->updControl("mrs_real/israte", getctrl("mrs_real/israte")); 00078 gain_->updControl("mrs_real/gain", 1.3); 00079 00080 gout_.create(gain_->getctrl("mrs_natural/inObservations")->to<mrs_natural>(), 00081 gain_->getctrl("mrs_natural/inSamples")->to<mrs_natural>()); 00082 00083 mrs_real freq = getctrl("mrs_real/frequency")->to<mrs_real>(); 00084 mrs_real pos = getctrl("mrs_real/pluckpos")->to<mrs_real>(); 00085 00086 nton_ = getctrl("mrs_real/nton")->to<mrs_real>(); 00087 noteon_ = getctrl("mrs_bool/noteon")->to<mrs_bool>(); 00088 00089 loss_ = getctrl("mrs_real/loss")->to<mrs_real>(); 00090 00091 s_ = getctrl("mrs_real/stretch")->to<mrs_real>(); 00092 00093 mrs_real israte = (getctrl("mrs_real/israte")->to<mrs_real>()); 00094 00095 // loweset frequency on a piano is 27.5Hz ... sample rate/27.5 for commute 00096 // this is the longest delay line required 00097 if (delaylineSize_ == 0) 00098 { 00099 delaylineSize_ = israte/27.5; 00100 noise_.create((mrs_natural)delaylineSize_); 00101 delayline1_.create((mrs_natural)delaylineSize_); 00102 pickDelayLine_.create((mrs_natural)delaylineSize_); 00103 00104 for (t = 0; t < delaylineSize_; t++) 00105 { 00106 noise_(t) = (mrs_real)(rand() / (RAND_MAX + 1.0) -0.5); 00107 } 00108 } 00109 00110 if (nton_ > 0 || noteon_) 00111 { 00112 a_ = 0; 00113 d_ = 2*israte/freq; 00114 N_ = (mrs_natural)floor(d_); 00115 g_ = -(-1+d_)/(-d_-1); //for all pass implementation 00116 picklength_ = (mrs_natural)floor(N_*pos); //for inverse comb implementation 00117 00118 for (t = 0; t < N_; t++) 00119 { 00120 pickDelayLine_(0)=noise_(t); 00121 delayline1_(t) = noise_(t)+ (mrs_real)0.1 * pickDelayLine_(picklength_-1); 00122 00123 //shift the pick delayline to the right 1 cell 00124 for(p=0; p<=picklength_-2; p++) 00125 { 00126 pickDelayLine_(picklength_-1-p) = pickDelayLine_(picklength_-1-p-1); 00127 } 00128 } 00129 wp_ = 1; 00130 wpp_ = 0; 00131 rp_ = N_-1; 00132 } 00133 } 00134 00135 00136 void Plucked::myProcess(realvec &in, realvec &out) 00137 { 00138 (void)in; 00139 00140 if (noteon_) 00141 { 00142 for (mrs_natural t = 0; t < inSamples_; t++) 00143 { 00144 // wp holds the current sample 00145 // wpp holds the previous sample 00146 a_ = delayline1_(wp_); 00147 b_ = delayline1_(wpp_); 00148 00149 // rp_ holds the sample at delay N_ 00150 delayline1_(rp_) = loss_*((1-s_)*a_ + s_* b_); 00151 00152 rp_ = (rp_ + +1) % N_; 00153 wp_ = (wp_ + 1) % N_; 00154 wpp_ = (wpp_ + 1) % N_; 00155 gout_(0,t) = a_; 00156 } 00157 } 00158 gain_->process(gout_, out); 00159 }