Marsyas
0.6.0-alpha
|
00001 /* 00002 ** Copyright (C) 1998-2010 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 "Combinator.h" 00020 #include "../common_source.h" 00021 #include <algorithm> 00022 00023 using std::ostringstream; 00024 using std::min; 00025 using std::max; 00026 00027 using namespace Marsyas; 00028 00029 const mrs_string Combinator::combinatorStrings[kNumCombinators] = 00030 { 00031 "+", 00032 "*", 00033 "max", 00034 "min" 00035 }; 00036 00037 Combinator::Combinators_t Combinator::GetCombinatorIdx (const mrs_string ctrlString) 00038 { 00039 Combinators_t ret = kAdd; // default 00040 00041 for (mrs_natural i = 0; i < kNumCombinators; i++) 00042 { 00043 if (ctrlString == combinatorStrings[i]) 00044 return (Combinators_t)i; 00045 } 00046 00047 return ret; 00048 } 00049 00050 Combinator::Combinator(mrs_string name) : MarSystem("Combinator", name) 00051 { 00053 // Default controls that all MarSystems should have (like "inSamples" 00054 // and "onObservations"), are already added by MarSystem::addControl(), 00055 // which is already called by the constructor MarSystem::MarSystem(name). 00056 // If no specific controls are needed by a MarSystem there is no need to 00057 // implement and call this addControl() method (see for e.g. Rms.cpp) 00058 addControls(); 00059 } 00060 00061 Combinator::Combinator(const Combinator& a) : MarSystem(a) 00062 { 00063 // IMPORTANT! 00066 // Otherwise this would result in trying to deallocate them twice! 00067 ctrl_combinator_ = getctrl("mrs_string/combinator"); 00068 ctrl_weights_ = getctrl("mrs_realvec/weights"); 00069 ctrl_numInputs_ = getctrl("mrs_natural/numInputs"); 00070 } 00071 00072 00073 Combinator::~Combinator() 00074 { 00075 } 00076 00077 MarSystem* 00078 Combinator::clone() const 00079 { 00080 // Every MarSystem should do this. 00081 return new Combinator(*this); 00082 } 00083 00084 void 00085 Combinator::addControls() 00086 { 00087 mrs_realvec tmp(1); 00088 tmp(0) = 1; 00089 00090 addctrl("mrs_string/combinator", "+", ctrl_combinator_); 00091 addctrl("mrs_realvec/weights", tmp, ctrl_weights_); 00092 addctrl("mrs_natural/numInputs", 1, ctrl_numInputs_); 00093 00094 setctrlState("mrs_natural/numInputs", true); 00095 } 00096 00097 void 00098 Combinator::myUpdate(MarControlPtr sender) 00099 { 00100 MRSDIAG("Combinator.cpp - Combinator:myUpdate"); 00101 00103 MarSystem::myUpdate(sender); 00104 00105 //if (ctrl_inObservations_->to<mrs_natural>() % ctrl_numInputs_->to<mrs_natural>()) 00106 // MRSWARN("Combinator: dimension mismatch"); 00107 if (ctrl_numInputs_->to<mrs_natural>()) 00108 updControl ("mrs_natural/onObservations", ctrl_inObservations_->to<mrs_natural>() / ctrl_numInputs_->to<mrs_natural>()); 00109 else 00110 updControl ("mrs_natural/onObservations", 0); 00111 00112 } 00113 00114 void 00115 Combinator::myProcess(realvec& in, realvec& out) 00116 { 00117 mrs_natural k,i,j; 00118 mrs_real weight = 1; 00119 mrs_bool useWeights = false; 00120 00121 const Combinators_t combi = GetCombinatorIdx (ctrl_combinator_->to<mrs_string>()); 00122 const mrs_natural numInputs = ctrl_numInputs_->to<mrs_natural>(); 00123 00124 // initialize output buffer 00125 if(combi == kAdd) 00126 out.setval(0); //identity operator 00127 if(combi == kMult) 00128 out.setval(1); //identity operator 00129 if(combi == kMax) 00130 out.setval(-1.0*MAXREAL); 00131 if(combi == kMin) 00132 out.setval(MAXREAL); 00133 00134 // sanity check 00135 if ((inObservations_%numInputs) != 0) 00136 { 00137 MRSWARN("Combinator: dimension mismatch"); 00138 MRSASSERT(false); 00139 out.setval(0); 00140 return; 00141 } 00142 00143 if (ctrl_weights_->to<mrs_realvec>().getSize () == numInputs) 00144 useWeights = true; 00145 00147 for (k = 0; k < numInputs; k++) 00148 { 00149 weight = (useWeights) ? (ctrl_weights_->to<mrs_realvec>())(k) : weight; 00150 00151 for (i = 0; i < onObservations_; i++) 00152 { 00153 // do the col-loop inside the switch to avoid calling the switch for every entry 00154 // we might also do this with function pointers... 00155 switch (combi) 00156 { 00157 case kAdd: 00158 default: 00159 { 00160 for (j = 0; j < onSamples_; j++) 00161 out(i,j) += weight * in(i+k*onObservations_,j); 00162 break; 00163 } 00164 case kMult: 00165 { 00166 if (weight == 1.0) // avoid pow if possible 00167 { 00168 for (j = 0; j < onSamples_; j++) 00169 out(i,j) *= in(i+k*onObservations_,j); 00170 } 00171 else 00172 { 00173 for (j = 0; j < onSamples_; j++) 00174 out(i,j) *= pow (in(i+k*onObservations_,j), weight); 00175 } 00176 break; 00177 } 00178 case kMax: 00179 { 00180 for (j = 0; j < onSamples_; j++) 00181 out(i,j) = max (out(i,j),in(i+k*onObservations_,j)); 00182 break; 00183 } 00184 case kMin: 00185 { 00186 for (j = 0; j < onSamples_; j++) 00187 out(i,j) = min (out(i,j),in(i+k*onObservations_,j)); 00188 break; 00189 } 00190 } 00191 } 00192 } 00193 }