Marsyas  0.5.0-beta1
/Users/jleben/code/marsyas/src/marsyas/marsystems/Plucked.cpp
Go to the documentation of this file.
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 }