Marsyas  0.6.0-alpha
/usr/src/RPM/BUILD/marsyas-0.6.0/src/marsyas/marsystems/PeakDistanceHorizontality.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 "../common_source.h"
00020 #include "PeakDistanceHorizontality.h"
00021 
00022 using std::ostringstream;
00023 using std::abs;
00024 
00025 using namespace Marsyas;
00026 
00027 //#define MTLB_DBG_LOG
00028 
00029 
00030 static const mrs_real kIdentityThresh   = 1e-6;
00031 static const mrs_real kSteepness        = .8;
00032 static const mrs_real kCutoff           = 1.;   // in Bark
00033 
00034 PeakDistanceHorizontality::PeakDistanceHorizontality(mrs_string name) : MarSystem("PeakDistanceHorizontality", name)
00035 {
00037   // Default controls that all MarSystems should have (like "inSamples"
00038   // and "onObservations"), are already added by MarSystem::addControl(),
00039   // which is already called by the constructor MarSystem::MarSystem(name).
00040   // If no specific controls are needed by a MarSystem there is no need to
00041   // implement and call this addControl() method (see for e.g. Rms.cpp)
00042   addControls();
00043 }
00044 
00045 PeakDistanceHorizontality::PeakDistanceHorizontality(const PeakDistanceHorizontality& a) : MarSystem(a)
00046 {
00047   ctrl_horizvert_   = getctrl("mrs_realvec/inpIsHorizontal");
00048   ctrl_rangeX_  = getctrl("mrs_real/rangeX");
00049   ctrl_rangeY_  = getctrl("mrs_real/rangeY");
00050 }
00051 
00052 
00053 PeakDistanceHorizontality::~PeakDistanceHorizontality()
00054 {
00055 }
00056 
00057 MarSystem*
00058 PeakDistanceHorizontality::clone() const
00059 {
00060   // Every MarSystem should do this.
00061   return new PeakDistanceHorizontality(*this);
00062 }
00063 
00064 void
00065 PeakDistanceHorizontality::addControls()
00066 {
00067   mrs_realvec tmp(1);
00068   tmp(0)    = 0;
00069 
00070   addctrl("mrs_bool/bypass", false);
00071   addctrl("mrs_realvec/weights", tmp);
00072   addctrl("mrs_natural/numInputs", 0);
00073   addctrl("mrs_realvec/inpIsHorizontal", tmp, ctrl_horizvert_);
00074   addctrl("mrs_real/rangeX", 0., ctrl_rangeX_);
00075   addctrl("mrs_real/rangeY", 0., ctrl_rangeY_);
00076 }
00077 
00078 void
00079 PeakDistanceHorizontality::myUpdate(MarControlPtr sender)
00080 {
00081   MRSDIAG("PeakDistanceHorizontality.cpp - PeakDistanceHorizontality:myUpdate");
00082 
00084   MarSystem::myUpdate(sender);
00085 
00086   weights_.stretch(inSamples_*getctrl ("mrs_natural/numInputs")->to<mrs_natural>(), inSamples_);
00087 
00088   sigSteepness_ = kSteepness;
00089   sigCutOff_        = kCutoff;
00090 }
00091 
00092 void
00093 PeakDistanceHorizontality::myProcess(realvec& in, realvec& out)
00094 {
00095   mrs_natural i;
00096   const mrs_natural numInputs   = getctrl ("mrs_natural/numInputs")->to<mrs_natural>();
00097   const mrs_realvec isHoriz     = ctrl_horizvert_->to<mrs_realvec>();
00098   const mrs_real        range[2]    = {ctrl_rangeX_->to<mrs_real>(), ctrl_rangeY_->to<mrs_real>()};
00099 
00100   out = in;
00101 
00102   MRSASSERT(range[0] > 0 && range[1] > 0);
00103   if (isHoriz.getSize () != numInputs)
00104   {
00105     MRSWARN("PeakDistanceHorizontality: dimension mismatch");
00106     MRSASSERT(false);
00107     out.setval(0);
00108     return;
00109   }
00110 
00111   if (getctrl("mrs_bool/bypass")->to<mrs_bool>())
00112   {
00113     weights_.setval(1.);
00114     setctrl ("mrs_realvec/weights", weights_);
00115     return;
00116   }
00117 
00118   for (i = 0; i < inSamples_; i++)
00119   {
00120     for (mrs_natural j = i; j < inSamples_; j++)
00121     {
00122       mrs_natural k;
00123       mrs_real  horizontality   = ComputeHorizontality (    std::abs(in(1,i)-in(1,j))/range[0],
00124                                 std::abs(in(0,i)-in(0,j))/range[1]),
00125                                 norm            = 0;
00126 
00127       for (k = 0; k < numInputs; k++)
00128       {
00129         mrs_real weight = horizontality;
00130 
00131         if (abs(isHoriz(k) - 2) < kIdentityThresh)
00132           weight    = .5;           // input is both horizontal and vertical
00133         else if (abs(isHoriz(k)) < kIdentityThresh)
00134           weight    = 1.-weight;    // input is vertical
00135 
00136         norm                            += weight;
00137         weights_(k*inSamples_ + i, j)   = weight;
00138         weights_(k*inSamples_ + j, i)   = weight;   // symmetry
00139       }
00140       if (norm != 0)
00141         norm    = 1./norm;
00142       for (k = 0; k < numInputs; k++)
00143       {
00144         weights_(k*inSamples_ + i, j)   *= norm;
00145         if (i != j)
00146           weights_(k*inSamples_ + j, i) *= norm;    // symmetry
00147       }
00148     }
00149   }
00150   setctrl ("mrs_realvec/weights", weights_);
00151 #ifdef MARSYAS_MATLAB
00152 #ifdef MTLB_DBG_LOG
00153   MATLAB_PUT(weights_, "weights");
00154   MATLAB_EVAL("figure(1);imagesc(weights),colorbar;");
00155 #endif
00156 #endif
00157 }
00158 
00159 mrs_real
00160 PeakDistanceHorizontality::ComputeHorizontality(mrs_real scaledDiffX, mrs_real scaledDiffY)
00161 {
00162 
00163   if (scaledDiffX == 0)
00164   {
00165     if (scaledDiffY == 0)
00166       return .5;
00167     else
00168       return 0.;
00169   }
00170   else if (scaledDiffY == 0)
00171     return   1.;
00172 
00173   mrs_real res = scaledDiffX / std::sqrt(scaledDiffX*scaledDiffX + scaledDiffY*scaledDiffY);
00174 
00175   return res*res;
00176 }