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 "../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 }