Marsyas  0.6.0-alpha
/usr/src/RPM/BUILD/marsyas-0.6.0/src/marsyas/marsystems/TempoHypotheses.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 "TempoHypotheses.h"
00020 #include "../common_source.h"
00021 
00022 using namespace std;
00023 using namespace Marsyas;
00024 
00025 TempoHypotheses::TempoHypotheses(mrs_string name):MarSystem("TempoHypotheses", name)
00026 {
00027   addControls();
00028   timeElapsed_ = 0;
00029   foundPeriods_ = false;
00030   foundPhases_ = false;
00031 }
00032 
00033 TempoHypotheses::TempoHypotheses(const TempoHypotheses& a) : MarSystem(a)
00034 {
00035   // For any MarControlPtr in a MarSystem
00036   // it is necessary to perform this getctrl
00037   // in the copy constructor in order for cloning to work
00038   ctrl_nPhases_ = getctrl("mrs_natural/nPhases");
00039   ctrl_nPeriods_ = getctrl("mrs_natural/nPeriods");
00040   ctrl_inductionTime_ = getctrl("mrs_natural/inductionTime");
00041   ctrl_hopSize_ = getctrl("mrs_natural/hopSize");
00042   ctrl_srcFs_ = getctrl("mrs_real/srcFs");
00043   ctrl_dumbInduction_ = getctrl("mrs_bool/dumbInduction");
00044   ctrl_dumbInductionRequest_ = getctrl("mrs_bool/dumbInductionRequest");
00045   ctrl_tickCount_ = getctrl("mrs_natural/tickCount");
00046   ctrl_triggerInduction_ = getctrl("mrs_bool/triggerInduction");
00047   ctrl_accSize_ = getctrl("mrs_natural/accSize");
00048   ctrl_maxPeriod_ = getctrl("mrs_natural/maxPeriod");
00049   ctrl_minPeriod_ = getctrl("mrs_natural/minPeriod");
00050 
00051   foundPeriods_ = a.foundPeriods_;
00052   foundPhases_ = a.foundPhases_;
00053   dumbInductionRequest_ = a.dumbInductionRequest_;
00054   triggerInduction_ = a.triggerInduction_;
00055 }
00056 
00057 TempoHypotheses::~TempoHypotheses()
00058 {
00059 }
00060 
00061 MarSystem*
00062 TempoHypotheses::clone() const
00063 {
00064   return new TempoHypotheses(*this);
00065 }
00066 
00067 void
00068 TempoHypotheses::addControls()
00069 {
00070   //Add specific controls needed by this MarSystem.
00071   addctrl("mrs_natural/nPhases", 1, ctrl_nPhases_);
00072   setctrlState("mrs_natural/nPhases", true);
00073   addctrl("mrs_natural/nPeriods", 1, ctrl_nPeriods_);
00074   setctrlState("mrs_natural/nPeriods", true);
00075   addctrl("mrs_natural/inductionTime", -1, ctrl_inductionTime_);
00076   setctrlState("mrs_natural/inductionTime", true);
00077   addctrl("mrs_natural/hopSize", 1, ctrl_hopSize_);
00078   addctrl("mrs_real/srcFs", 1.0, ctrl_srcFs_);
00079   setctrlState("mrs_real/srcFs", true);
00080   addctrl("mrs_bool/dumbInduction", false, ctrl_dumbInduction_);
00081   addctrl("mrs_bool/dumbInductionRequest", false, ctrl_dumbInductionRequest_);
00082   addctrl("mrs_natural/tickCount", 0, ctrl_tickCount_);
00083   addctrl("mrs_bool/triggerInduction", false, ctrl_triggerInduction_);
00084   setctrlState("mrs_bool/triggerInduction", true);
00085   addctrl("mrs_natural/accSize", -1, ctrl_accSize_);
00086   addctrl("mrs_natural/maxPeriod", -1, ctrl_maxPeriod_);
00087   setctrlState("mrs_natural/maxPeriod", true);
00088   addctrl("mrs_natural/minPeriod", -1, ctrl_minPeriod_);
00089   setctrlState("mrs_natural/minPeriod", true);
00090 }
00091 
00092 void
00093 TempoHypotheses::myUpdate(MarControlPtr sender)
00094 {
00095   (void) sender;  //suppress warning of unused parameter(s)
00096   MRSDIAG("TempoHypotheses.cpp - TempoHypotheses:myUpdate");
00097 
00098   nPhases_ = ctrl_nPhases_->to<mrs_natural>();
00099   nPeriods_ = ctrl_nPeriods_->to<mrs_natural>();
00100   inductionSize_ = ctrl_inductionTime_->to<mrs_natural>();
00101   srcFs_ = ctrl_srcFs_->to<mrs_real>();
00102   hopSize_ = ctrl_hopSize_->to<mrs_natural>();
00103   triggerInduction_ = ctrl_triggerInduction_->to<mrs_bool>();
00104   accSize_ = ctrl_accSize_->to<mrs_natural>();
00105   dumbInductionRequest_ = ctrl_dumbInductionRequest_->to<mrs_bool>();
00106   maxPeriod_ = ctrl_maxPeriod_->to<mrs_natural>();
00107   minPeriod_ = ctrl_minPeriod_->to<mrs_natural>();
00108 
00109   setctrl("mrs_real/osrate", getctrl("mrs_real/israte"));
00110   setctrl("mrs_natural/onSamples", 3);
00111   setctrl("mrs_natural/onObservations", nPhases_ * nPeriods_);
00112 }
00113 
00114 
00115 void
00116 TempoHypotheses::myProcess(realvec& in, realvec& out)
00117 {
00118   //timeElapsed_ is constantly updated with the referee's next time frame
00119   timeElapsed_ = ctrl_tickCount_->to<mrs_natural>();
00120 
00121   //cout << "THyp: " << timeElapsed_ << "; Ind: " << inductionSize_ << "; accSize: " << accSize_
00122   //    << "; maxPer: " << maxPeriod_ << "; minPer: " << minPeriod_ << endl;
00123 
00124   triggerInduction_ = ctrl_triggerInduction_->to<mrs_bool>();
00125   if(triggerInduction_)
00126   {
00127     mrs_natural maxPeriod = 0;
00128 
00129     //reset flags
00130     foundPeriods_ = false;
00131     foundPhases_ = false;
00132     if(!dumbInductionRequest_) //if not in dumb induction mode (requested by user)
00133     {
00134       //retrieve Max Period Peak and check if found periods and/or phases
00135       mrs_real maxPeriodPeak = 0.0;
00136       for (int i=0; i < nPeriods_; i++)
00137       {
00138         if(in(0, 2*i+1) > 1) //if found any period (period > 1 because it may appear as decimals meaning 0)
00139           foundPeriods_ = true;
00140 
00141         if(in(0, 2*i) > maxPeriodPeak)
00142           maxPeriodPeak = in(0, 2*i);
00143 
00144         //keep maximum period
00145         if(in(0, 2*i+1) > maxPeriod)
00146           maxPeriod = (mrs_natural)in(0, 2*i+1);
00147 
00148         int z = 0;
00149         //cout << "TH-Phases: " << endl;
00150         for (int j = (i * nPhases_); j < ((i+1) * nPhases_); j++)
00151         {
00152           //cout << "i: " << in(1, 2*z+1) << "; ";
00153           if(in(1, 2*z+1) > 0) //if found any phases
00154             foundPhases_ = true;
00155           //foundPhases_ = false;
00156           z++;
00157         }
00158         //cout << endl;
00159       }
00160 
00161       //cout << "FoundPer: " << foundPeriods_ << "; foundPh: " << foundPhases_ << endl;
00162 
00163       if(foundPeriods_) //if found periods
00164       {
00165         for (int i=0; i < nPeriods_; i++)
00166         {
00167           int z = 0;
00168           for (int j = (i * nPhases_); j < ((i+1) * nPhases_); j++)
00169           {
00170             out(j, 0) = in(0, 2*i+1); //Periods
00171             out(j, 1) = in(1, 2*z+1); //Phases
00172             out(j, 2) = in(0, 2*i);// / maxPeriodPeak; //Normalized period peak magnitudes
00173 
00174             z++;
00175           }
00176         }
00177       }
00178     }
00179 
00180     //if no periods found or in dumb induction mode (requested by user)
00181     if(!foundPeriods_ || dumbInductionRequest_)
00182     {
00183       //Manual assorted values for filling BPM hypotheses vector when none are generated
00184       int manualBPMs_[] = {120, 60, 240, 100, 160, 200, 80, 140, 180, 220, 150};
00185 
00186       if(!foundPeriods_ && !dumbInductionRequest_)
00187         cerr << "\nUnable to find salient periodicities within the given induction window..." << endl;
00188       if(dumbInductionRequest_)
00189         cerr << "\nDumb Induction Mode..." << endl;
00190 
00191       cerr << "...Replacing induction with the following BPMs: ";
00192 
00193       mrs_natural assignedPerCount = 0;
00194       for (unsigned int i=0; i < (sizeof(manualBPMs_) / sizeof(int)); i++)
00195       {
00196         if(assignedPerCount == nPeriods_) break;
00197 
00198         mrs_natural manualPeriod = (mrs_natural) (((mrs_real) 60 / (manualBPMs_[i] * hopSize_)) * (srcFs_));
00199 
00200         //cout << i << "-> manBPM: " << manualBPMs_[i] << "[" << manualPeriod << "] maxPer: "
00201         //  << maxPeriod_ << "; minPer: " << minPeriod_ << "; ASS: " << assignedPerCount << endl;
00202 
00203         //assure that the chosen manual periods are within the user-defined BPM range
00204         if(manualPeriod >= minPeriod_ && manualPeriod <= maxPeriod_)
00205         {
00206           cerr << manualBPMs_[i] << "; ";
00207 
00208           int z = 0;
00209           for (int j = (assignedPerCount * nPhases_); j < ((assignedPerCount+1) * nPhases_); j++)
00210           {
00211             out(j, 0) = manualPeriod; //Periods
00212             out(j, 1) = in(1, 2*z+1); //Phases
00213             out(j, 2) = 1.0; //equal (max) peak sizes to all manual periods
00214             z++;
00215 
00216             if(out(j,0) > maxPeriod) //save maximum manual period
00217               maxPeriod = (mrs_natural) out(j,0);
00218           }
00219 
00220           assignedPerCount++;
00221         }
00222       }
00223 
00224       //request dumbInduction to PhaseLock
00225       ctrl_dumbInduction_->setValue(true);
00226     }
00227 
00228     if(!foundPhases_) //if no phases found
00229     {
00230       //cerr << "\nUnable to find potential phases (onsets) within the given induction window..." << endl;
00231       //cerr << "...Assuming the maximum nr. of possible phases." << endl;
00232 
00233       //calculate minimum spacing between possible phases
00234       mrs_natural spacing = (mrs_natural) ceil(((mrs_real)maxPeriod / (mrs_real)nPhases_));
00235       //start phases on the analysis start point of the given induction window
00236       mrs_natural accBeginning = (accSize_-1-inductionSize_);
00237 
00238       //fill phases vector
00239       mrs_realvec phases(nPhases_);
00240       mrs_natural index = 0;
00241       for(int ph = accBeginning; ph <= accBeginning+maxPeriod+spacing; ph += spacing)
00242       {
00243         if(index == nPhases_) break;
00244 
00245         phases(index) = ph; //Phases
00246         index++;
00247       }
00248 
00249       for (int i=0; i < nPeriods_; i++)
00250       {
00251         int z = 0;
00252         for (int j = (i * nPhases_); j < ((i+1) * nPhases_); j++)
00253         {
00254           out(j, 1) = phases(z); //Phases
00255           z++;
00256         }
00257       }
00258       //MATLAB_PUT(in, "BeatData");
00259       //MATLAB_PUT(out, "TempoHypotheses");
00260     }
00261 
00262     //MATLAB_PUT(out, "TempoHypotheses2");
00263     //MATLAB_PUT(in, "BeatData");
00264     //MATLAB_EVAL("plot(BeatData)");
00265   }
00266 
00267   /*
00268   //FOR TESTING ONSETS IN REPEATED INDUCTION=========================
00269   MATLAB_PUT((mrs_natural)triggerInduction_, "Induction_flag");
00270   MATLAB_EVAL("Induction = Induction2;");
00271   MATLAB_EVAL("Induction(end) = Induction_flag*max(PeakerOnset_in);");
00272   */
00273 }
00274 
00275 
00276 
00277 
00278 
00279 
00280 
00281