Marsyas  0.6.0-alpha
/usr/src/RPM/BUILD/marsyas-0.6.0/src/marsyas/marsystems/MatchBassModel.cpp
Go to the documentation of this file.
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 }