Marsyas  0.6.0-alpha
/usr/src/RPM/BUILD/marsyas-0.6.0/src/marsyas/marsystems/PeakerOnset.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 "PeakerOnset.h"
00020 #include "../common_source.h"
00021 
00022 using namespace std;
00023 using namespace Marsyas;
00024 
00025 PeakerOnset::PeakerOnset(mrs_string name):MarSystem("PeakerOnset", name)
00026 {
00027   addControls();
00028 
00029   prevValue_ = 0.0;
00030   t_ = 0;
00031 }
00032 
00033 PeakerOnset::PeakerOnset(const PeakerOnset& a) : MarSystem(a)
00034 {
00035   ctrl_lookAheadSamples_ = getctrl("mrs_natural/lookAheadSamples");
00036   ctrl_threshold_ = getctrl("mrs_real/threshold");
00037   ctrl_onsetDetected_ = getctrl("mrs_bool/onsetDetected");
00038   ctrl_confidence_ = getctrl("mrs_real/confidence");
00039 
00040   prevValue_ = a.prevValue_;
00041   t_ = a.t_;
00042 }
00043 
00044 PeakerOnset::~PeakerOnset()
00045 {
00046 }
00047 
00048 MarSystem*
00049 PeakerOnset::clone() const
00050 {
00051   return new PeakerOnset(*this);
00052 }
00053 
00054 void
00055 PeakerOnset::addControls()
00056 {
00057   addctrl("mrs_natural/lookAheadSamples", 0, ctrl_lookAheadSamples_);
00058   addctrl("mrs_real/threshold", 0.0, ctrl_threshold_);
00059   addctrl("mrs_bool/onsetDetected", false, ctrl_onsetDetected_);
00060   addctrl("mrs_real/confidence", 0.0, ctrl_confidence_);
00061 }
00062 
00063 void
00064 PeakerOnset::myUpdate(MarControlPtr sender)
00065 {
00066   (void) sender;  //suppress warning of unused parameter(s)
00067   MRSDIAG("PeakerOnset.cpp - PeakerOnset:myUpdate");
00068 
00069   ctrl_onSamples_->setValue(1, NOUPDATE);
00070   if(inObservations_ > 1)
00071   {
00072     MRSWARN("PeakerOnset::myUpdate() - inObservations is bigget than 1. This MarSystem only takes the first observation into consideration...");
00073   }
00074   ctrl_onObservations_->setValue(1, NOUPDATE);
00075   ctrl_osrate_->setValue(ctrl_israte_, NOUPDATE);
00076   ctrl_onObsNames_->setValue("onset_confidence");
00077 
00078   if(inSamples_ < 1 + 2 * ctrl_lookAheadSamples_->to<mrs_natural>())
00079   {
00080     cout << "inSamples_ = " << inSamples_ << endl;
00081     cout << "lookAhead = " << ctrl_lookAheadSamples_->to<mrs_natural>() << endl;
00082     MRSWARN("PeakerOnset::myUpdate() - inSamples is too small for specified onsetWinSize: onset detection not possible to be performed!");
00083     ctrl_lookAheadSamples_->setValue(0, NOUPDATE);
00084   }
00085 }
00086 
00087 void
00088 PeakerOnset::myProcess(realvec& in, realvec& out)
00089 {
00090   mrs_natural o,t;
00091   (void) o;
00092   ctrl_onsetDetected_->setValue(false);
00093   ctrl_confidence_->setValue(0.0);
00094   out.setval(0.0);
00095 
00096   mrs_natural w = ctrl_lookAheadSamples_->to<mrs_natural>();
00097 
00098   if(w == 0)
00099     return;
00100 
00101   //point to check for an onset
00102   mrs_natural checkPoint = inSamples_-1-w;
00103   mrs_real checkPointValue = in(checkPoint);
00104   mrs_bool isOnset = true;
00105 
00106   //check first condition
00107   mrs_natural interval = mrs_natural(2.0/3.0*w);
00108   //for (t = inSamples_-1; t >= inSamples_-1-2*w ; t--)
00109   for(t=checkPoint-interval; t <= checkPoint+interval; t++)
00110   {
00111     if(checkPointValue < in(t))
00112     {
00113       isOnset = false;
00114       MRSDIAG("PeakerOnset::myProcess() - Failed 1st condition!");
00115       break;
00116     }
00117   }
00118 
00119 //  //new check proposed by Fabien Gouyon
00120 //  mrs_real ww = w/2;
00121 //  mrs_real maxVal = MINREAL;
00122 //  for(t = inSamples_-1-ww; t > checkPoint; t--)
00123 //  {
00124 //      if(in(t) > maxVal)
00125 //      {
00126 //          maxVal = in(t);
00127 //      }
00128 //      else
00129 //      {
00130 //          isOnset = false;
00131 //          //cout << "failed 1st condition!" << endl;
00132 //          break;
00133 //      }
00134 //  }
00135 //  maxVal = MINREAL;
00136 //  for(t = inSamples_-1-2*ww; t < checkPoint; t++)
00137 //  {
00138 //      if(in(t) > maxVal)
00139 //      {
00140 //          maxVal = in(t);
00141 //      }
00142 //      else
00143 //      {
00144 //          isOnset = false;
00145 //          //cout << "failed 1st condition!" << endl;
00146 //          break;
00147 //      }
00148 //  }
00149 
00150   /* Last version (by lgmartins) -> corrected (below) for not being strict to the window size defined by the precede ShiftInput
00151     //check second condition
00152     mrs_real m = 0.0;
00153     for(t=0; t < inSamples_; t++)
00154         m += in(t);
00155     m /= inSamples_;
00156   */
00157 
00158   mrs_natural mul = 3; //multiplier proposed in Dixon2006
00159   mrs_real m = 0.0;
00160   for(t=checkPoint-(mul*w); t < inSamples_; t++)
00161     m += in(t);
00162   m /= (w*4+1);
00163 
00164   //checkPoint value should be higher than the window mean and mean should
00165   //be a significant value (otherwise we most probably are in a silence segment,
00166   //and we do not want to detect onsets on segments!)
00167   if(checkPointValue <= (m * ctrl_threshold_->to<mrs_real>()) || m < 10e-20)
00168   {
00169     isOnset = false;
00170     MRSDIAG("PeakerOnset::myProcess() - Failed 2nd condition!");
00171   }
00172 
00173   //third condition from Dixon2006 (DAFx paper) is not implemented
00174   //since it was found on that paper that its impact is minimal...
00175 
00176   if(isOnset)
00177   {
00178     ctrl_onsetDetected_->setValue(true);
00179     //ctrl_confidence_->setValue(1.0); //[!] must still find a way to output a confidence...
00180     ctrl_confidence_->setValue(checkPointValue/100.0); // ad-hoc value which should still have more meaning than a pure 1.0 vs. 0.0.
00181     out.setval(1.0);
00182     MRSDIAG("PeakerOnset::myProcess() - Onset Detected!");
00183   }
00184 
00185   //used for toy_with_onsets.m (DO NOT DELETE! - COMMENT INSTEAD)
00186 
00187   //t_++;
00188 
00189   //if(t_ == 0)
00190   //    MATLAB_PUT(in, "PeakerOnset_inWIN");
00191   //MATLAB_PUT(in, "PeakerOnset_in");
00192   //if(t_ <= 431)
00193   //    MATLAB_EVAL("PK_TS2 = [PK_TS2 PeakerOnset_in]");
00194   //MATLAB_EVAL("plot(PK_TS, 'r');");
00195   //MATLAB_EVAL("plot(FluxTS); hold on; plot(PK_TS, 'r');");
00196   //MATLAB_EVAL("plot(PeakerOnset_in,'r');hold on; plot(ShiftInput_out); hold off");
00197   //MATLAB_PUT(out,"PeakerOnset_out");
00198   //MATLAB_EVAL("onsetTS = [onsetTS, PeakerOnset_out];");
00199 }