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 00020 00021 #include "MatchBassModel.h" 00022 #include "Metric2.h" 00023 00024 00025 using std::ostringstream; 00026 using std::cout; 00027 using std::endl; 00028 00029 using namespace Marsyas; 00030 00031 MatchBassModel::MatchBassModel(mrs_string name):MarSystem("MatchBassModel", name) 00032 { 00033 isComposite_ = true; 00034 addControls(); 00035 } 00036 00037 MatchBassModel::MatchBassModel(const MatchBassModel& a):MarSystem(a) 00038 { 00039 ctrl_nTemplates_ = getctrl("mrs_natural/nTemplates"); 00040 ctrl_nDevision_ = getctrl("mrs_natural/nDevision"); 00041 ctrl_intervals_ = getctrl("mrs_realvec/intervals"); 00042 ctrl_selections_ = getctrl("mrs_realvec/selections"); 00043 ctrl_segmentation_ = getctrl("mrs_realvec/segmentation"); 00044 ctrl_time_ = getctrl("mrs_realvec/time"); 00045 ctrl_freq_ = getctrl("mrs_realvec/freq"); 00046 ctrl_lowFreq_ = getctrl("mrs_real/lowFreq"); 00047 ctrl_highFreq_ = getctrl("mrs_real/highFreq"); 00048 ctrl_rootFreq_ = getctrl("mrs_real/rootFreq"); 00049 ctrl_totalDistance_ = getctrl("mrs_real/totalDistance"); 00050 ctrl_mode_ = getctrl("mrs_string/mode"); 00051 ctrl_calcCovMatrix_ = getctrl("mrs_natural/calcCovMatrix"); 00052 ctrl_covMatrix_ = getctrl("mrs_realvec/covMatrix"); 00053 ctrl_templates_ = getctrl("mrs_realvec/templates"); 00054 ctrl_stdDev_ = getctrl("mrs_real/stdDev"); 00055 ctrl_normalize_ = getctrl("mrs_string/normalize"); 00056 ctrl_distance_ = getctrl("mrs_realvec/distance"); 00057 } 00058 00059 MatchBassModel::~MatchBassModel() 00060 { 00061 } 00062 00063 MarSystem* 00064 MatchBassModel::clone() const 00065 { 00066 return new MatchBassModel(*this); 00067 } 00068 00069 void 00070 MatchBassModel::addControls() 00071 { 00072 addControl("mrs_natural/nTemplates", 3, ctrl_nTemplates_); 00073 addControl("mrs_natural/nDevision", 64, ctrl_nDevision_); 00074 addControl("mrs_realvec/intervals", realvec(), ctrl_intervals_); 00075 addControl("mrs_realvec/selections", realvec(), ctrl_selections_); 00076 addControl("mrs_realvec/segmentation", realvec(), ctrl_segmentation_); 00077 addControl("mrs_realvec/time", realvec(), ctrl_time_); 00078 addControl("mrs_realvec/freq", realvec(), ctrl_freq_); 00079 addControl("mrs_real/lowFreq", 40.0, ctrl_lowFreq_); 00080 addControl("mrs_real/highFreq", 220.0, ctrl_highFreq_); 00081 addControl("mrs_real/rootFreq", 110.0, ctrl_rootFreq_); 00082 addControl("mrs_real/totalDistance", 0.0, ctrl_totalDistance_); 00083 addControl("mrs_string/mode", "estimate", ctrl_mode_); 00084 addControl("mrs_realvec/templates", realvec(), ctrl_templates_); 00085 addControl("mrs_natural/calcCovMatrix", 0, ctrl_calcCovMatrix_); 00086 addControl("mrs_realvec/covMatrix", realvec(), ctrl_covMatrix_); 00087 addControl("mrs_real/stdDev", 1.0, ctrl_stdDev_); 00088 addControl("mrs_string/normalize", "none", ctrl_normalize_); 00089 addControl("mrs_realvec/distance", realvec(), ctrl_distance_); 00090 } 00091 00092 void MatchBassModel::myUpdate(MarControlPtr sender) 00093 { 00094 (void) sender; //suppress warning of unused parameter(s) 00095 mrs_natural i, j, o; 00096 ostringstream oss; 00097 realvec tmpvec; 00098 (void) sender; //suppress warning of unused parameter(s) 00099 // get value from controller 00100 K_ = ctrl_nTemplates_->to<mrs_natural>(); 00101 I_ = ctrl_nDevision_->to<mrs_natural>(); 00102 seg_ = ctrl_segmentation_->to<mrs_realvec>(); 00103 time_ = ctrl_time_->to<mrs_realvec>(); 00104 freq_ = ctrl_freq_->to<mrs_realvec>(); 00105 lowFreq_ = ctrl_lowFreq_->to<mrs_real>(); 00106 highFreq_ = ctrl_highFreq_->to<mrs_real>(); 00107 rootFreq_ = ctrl_rootFreq_->to<mrs_real>(); 00108 templates_ = ctrl_templates_->to<mrs_realvec>(); 00109 00110 // check size 00111 ctrl_inSamples_->setValue(time_.getSize()); 00112 ctrl_inObservations_->setValue(freq_.getSize()); 00113 ctrl_onObservations_->setValue(inObservations_, NOUPDATE); 00114 ctrl_onSamples_->setValue(inSamples_, NOUPDATE); 00115 ctrl_osrate_->setValue(inSamples_, NOUPDATE); 00116 for(o=0; o<inObservations_; o++) 00117 oss << "MatchBassModel_" << o << ","; 00118 ctrl_onObsNames_->setValue(oss.str(), NOUPDATE); 00119 00120 // calculate log frequency 00121 logFreq_.create(freq_.getSize()); 00122 for(i=0; i<logFreq_.getSize(); ++i) { 00123 logFreq_(i) = log(lowFreq_)+(log(highFreq_)-log(lowFreq_))/(double)(logFreq_.getSize()-1)*(double)i; 00124 } 00125 // calculate start vector 00126 start_.create(seg_.getSize()); 00127 i=0; 00128 j=0; 00129 while(i<inSamples_ && j<seg_.getSize()) { 00130 if(seg_(j) <= time_(i)) { 00131 start_(j) = i; 00132 j++; 00133 } else { 00134 ++i; 00135 } 00136 } 00137 if(j<seg_.getSize()) { 00138 start_.stretch(j+1); 00139 start_(j) = i; 00140 } 00141 i=0; 00142 while(freq_(i) < rootFreq_ && i<inObservations_) { 00143 ++i; 00144 } 00145 rootBin_ = i; 00146 i=0; 00147 while(freq_(i) < lowFreq_ && i<inObservations_) { 00148 ++i; 00149 } 00150 rootMin_ = i;// - rootBin_; 00151 i=0; 00152 while(freq_(i) < highFreq_ && i<inObservations_) { 00153 ++i; 00154 } 00155 rootMax_ = i;// - rootBin_; 00156 // memory allocation 00157 invec_.create(rootMax_-rootMin_, inSamples_); 00158 d_.create(seg_.getSize()-1); 00159 //for(i=0; i<seg_.getSize()-1; ++i){ 00160 //d_(i) = -rootBin_; 00161 //} 00162 ctrl_intervals_->setValue(d_); 00163 k_.create(seg_.getSize()-1); 00164 costVector_.create(rootMax_-rootMin_,K_); 00165 distance_.create(K_,seg_.getSize()-1); 00166 00167 child_count_t child_count = marsystems_.size(); 00168 if(child_count == 1 && inSamples_ > 0) { 00169 // configure the metric child MarSystem: 00170 // the input to metric are the two vectors to process stacked vertically 00171 i_featVec_.create(rootMax_-rootMin_, I_); 00172 j_featVec_.create((rootMax_-rootMin_)*2, I_*K_); 00173 stackedFeatVecs_.create((rootMax_-rootMin_)*2,1); 00174 marsystems_[0]->setctrl("mrs_natural/inObservations", stackedFeatVecs_.getRows()); 00175 marsystems_[0]->setctrl("mrs_natural/inSamples", 1); 00176 marsystems_[0]->setctrl("mrs_real/israte", ctrl_israte_->to<mrs_real>()); 00177 oss.clear(); 00178 for(i=0; i<2; ++i) { 00179 for(o=0; o<rootMax_-rootMin_; o++) { 00180 oss << "MatchBassModel_" << o << ","; 00181 } 00182 } 00183 marsystems_[0]->setctrl("mrs_string/inObsNames", oss.str()); 00184 marsystems_[0]->update(); 00185 00186 // link covMatrix control 00187 MarControlPtr ctrl_childCovMat = marsystems_[0]->getctrl("mrs_realvec/covMatrix"); 00188 if(!ctrl_childCovMat.isInvalid()) 00189 ctrl_childCovMat->linkTo(ctrl_covMatrix_); 00190 metricResult_.create(1,1); 00191 if(marsystems_[0]->getctrl("mrs_natural/onObservations") != 1 || 00192 marsystems_[0]->getctrl("mrs_natural/onSamples") != 1) { 00193 MRSWARN("MatchBassModel:myUpdate - invalid Child Metric MarSystem (does not output a real value)!"); 00194 } 00195 } else if(child_count > 1) { 00196 MRSWARN("MatchBassModel:myUpdate - more than one children MarSystem exist! Only one MarSystem should be added as a metric!"); 00197 } 00198 00199 } 00200 00201 void 00202 MatchBassModel::myProcess(realvec& in, realvec& out) 00203 { 00204 child_count_t child_count = marsystems_.size(); 00205 mrs_natural i, j, k, l, m, d; 00206 mrs_real tmpreal, min; 00207 realvec covMatrix, tmpvec; 00208 00209 if(inSamples_ > 0) { 00210 if(child_count == 1) { 00211 // copy input realvec to output realvec 00212 for(i=0; i<inSamples_; ++i) { 00213 for(j=0; j<inObservations_; j++) { 00214 out(j,i) = in(j,i); 00215 } 00216 } 00217 00218 // normalize features if necessary 00219 for(i=0; i<I_*K_; ++i) { 00220 for(j=0; j<(rootMax_-rootMin_)*2; j++) { 00221 j_featVec_(j,i) = templates_(j,i); 00222 } 00223 } 00224 for(i=0; i<inSamples_; ++i) { 00225 for(j=rootMin_; j<rootMax_; j++) { 00226 invec_(j-rootMin_, i) = in(j,i); 00227 } 00228 } 00229 if(ctrl_normalize_->to<mrs_string>() == "MinMax") { 00230 invec_.normObsMinMax(); // (x - min)/(max - min) 00231 j_featVec_.normObsMinMax(); 00232 } else if(ctrl_normalize_->to<mrs_string>() == "MeanStd") { 00233 invec_.normObs(); // (x - mean)/std 00234 j_featVec_.normObs(); 00235 } 00236 distance_.stretch(K_,seg_.getSize()-1); 00237 00238 // calculate the Covariance Matrix from the inputm, in case 00239 if(ctrl_calcCovMatrix_->to<mrs_natural>() & MatchBassModel::fixedStdDev) { 00240 covMatrix.create(rootMax_-rootMin_, rootMax_-rootMin_); 00241 tmpreal = ctrl_stdDev_->to<mrs_real>(); 00242 tmpreal *= tmpreal; 00243 for(i=0; i<rootMax_-rootMin_; ++i) { 00244 covMatrix(i,i) = tmpreal; 00245 } 00246 } else if(ctrl_calcCovMatrix_->to<mrs_natural>() & MatchBassModel::diagCovMatrix) { 00247 covMatrix.create(rootMax_-rootMin_, rootMax_-rootMin_); 00248 invec_.varObs(tmpvec); 00249 for(i=0; i<rootMax_-rootMin_; ++i) { 00250 covMatrix(i,i) = tmpvec(i); 00251 } 00252 } else if(ctrl_calcCovMatrix_->to<mrs_natural>() & MatchBassModel::fullCovMatrix) { 00253 covMatrix.create(rootMax_-rootMin_, rootMax_-rootMin_); 00254 invec_.covariance(covMatrix); 00255 } else if(ctrl_calcCovMatrix_->to<mrs_natural>() & MatchBassModel::noCovMatrix) { 00256 ctrl_covMatrix_->setValue(realvec()); 00257 } 00258 00259 totaldis_ = 0.0; 00260 tmpvec.stretch(rootMax_-rootMin_, I_); 00261 for(j=0; j<(int)start_.getSize()-1; j++) { 00262 tmpreal = 0.0; 00263 for(i=0; i<rootMax_-rootMin_; ++i) { 00264 for(k=0; k<K_; k++) { 00265 costVector_(i,k) = 0; 00266 } 00267 } 00268 for(i=0; i<I_; ++i) { 00269 for(l=0; l<rootMax_-rootMin_; l++) { 00270 i_featVec_(l,i) = 0; 00271 tmpvec(l,i) = 0; 00272 } 00273 } 00274 for(i=0; i<I_; ++i) { 00275 for(m=(mrs_natural)(((double)i/I_*(start_(j+1)-start_(j)))+start_(j)); m<(int)((double)(i+1)/I_*(start_(j+1)-start_(j)))+start_(j); m++) { 00276 for(l=0; l<rootMax_-rootMin_; l++) { 00277 i_featVec_(l,i) += invec_(l, m); 00278 tmpvec(l,i) ++; 00279 } 00280 } 00281 } 00282 for(i=0; i<I_; ++i) { 00283 for(l=0; l<rootMax_-rootMin_; l++) { 00284 if(tmpvec(l,i) > 0) { 00285 i_featVec_(l,i) /= tmpvec(l,i); 00286 } 00287 } 00288 } 00289 for(k=0; k<K_; k++) { 00290 for(i=0; i<I_; ++i) { 00291 for(l=0; l<rootMax_-rootMin_; l++) { 00292 stackedFeatVecs_(l,0) = i_featVec_(l,i); 00293 } 00294 for(d=0; d<rootMax_-rootMin_; d++) { 00295 for(l=0; l<rootMax_-rootMin_; l++) { 00296 stackedFeatVecs_(l+rootMax_-rootMin_,0) = j_featVec_(l+rootMax_-rootMin_-d,k*I_+i); 00297 } 00298 marsystems_[0]->process(stackedFeatVecs_, metricResult_); 00299 costVector_(d, k) += metricResult_(0,0); 00300 } 00301 } 00302 } 00303 min = costVector_(0,0); 00304 d_(j) = 0; 00305 k_(j) = 0; 00306 for(d=0; d<rootMax_-rootMin_; d++) { 00307 for(k=0; k<K_; k++) { 00308 if(min>costVector_(d, k)) { 00309 min = costVector_(d,k); 00310 d_(j) = d; 00311 k_(j) = k; 00312 } 00313 } 00314 } 00315 totaldis_ += min; 00316 for(k=0; k<K_; k++) { 00317 min = costVector_(0,k); 00318 for(d=0; d<rootMax_-rootMin_; d++) { 00319 if(min > costVector_(d,k)) { 00320 min = costVector_(d,k); 00321 } 00322 } 00323 distance_(k,j) = min; 00324 } 00325 } 00326 ctrl_intervals_->setValue(d_); 00327 ctrl_selections_->setValue(k_); 00328 ctrl_totalDistance_->setValue(totaldis_); 00329 ctrl_distance_->setValue(distance_); 00330 } else { 00331 if(child_count == 0) { 00332 MRSWARN("MatchBassModel::myProcess - no Child Metric MarSystem added"); 00333 } else { 00334 MRSWARN("MatchBassModel::myProcess - more than on Child MarSystem exists (i.e. invalid metric)"); 00335 } 00336 } 00337 } else { 00338 cout << "Not ready" << endl; 00339 } 00340 }