Marsyas  0.6.0-alpha
/usr/src/RPM/BUILD/marsyas-0.6.0/src/marsyas/marsystems/BeatReferee.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 #include "BeatReferee.h"
00020 #include "../common_source.h"
00021 
00022 using namespace std;
00023 using namespace Marsyas;
00024 
00025 #define NONE 0.0
00026 #define BEAT 1.0
00027 #define EVAL 2.0
00028 
00029 #define INNER 3.0
00030 #define OUTTER 4.0
00031 
00032 #define MINIMUMREAL 0.000001 //(0.000001 minimum float recognized)
00033 #define NA -10000.0 //undefined value flag (just a big negative nr)
00034 
00035 BeatReferee::BeatReferee(mrs_string name):MarSystem("BeatReferee", name)
00036 {
00037   addControls();
00038 
00039   bestScore_ = NA; //To allow initial negative scores
00040   bestAgentIndex_ = -1; //-1 by default
00041   timeElapsed_ = 0;
00042   outputCount_ = 0;
00043   triggerCount_ = 0;
00044   lastBeatTime_ = (mrs_natural) NA;
00045   lastBeatPeriod_ = -1;
00046   bestFinalAgent_ = -1;
00047   processInduction_ = false;
00048   triggerInduction_ = false;
00049   startSystem_ = true;
00050   startTracking_ = false;
00051   lostGTBeatsCount_ = 0;
00052   lastGTBeatPos_ = -1;
00053   backtraceEndTime_ = -1;
00054   bestAgentBeforeTrigger_ = -1;
00055   lastGTFalsePos_ = false;
00056   logFile_ = false;
00057   // these will be overwritten later
00058   nrAgents_ = 100;
00059   maxNrBeats_ = 100;
00060   //
00061   initialization();
00062 }
00063 
00064 BeatReferee::BeatReferee(const BeatReferee& a) : MarSystem(a)
00065 {
00066   // For any MarControlPtr in a MarSystem
00067   // it is necessary to perform this getctrl
00068   // in the copy constructor in order for cloning to work
00069   ctrl_mutedAgents_ = getctrl("mrs_realvec/mutedAgents");
00070   ctrl_inductionEnabler_ = getctrl("mrs_realvec/inductionEnabler");
00071   ctrl_firstHypotheses_ = getctrl("mrs_realvec/beatHypotheses");
00072   ctrl_inductionTime_ = getctrl("mrs_natural/inductionTime");
00073   ctrl_hopSize_ = getctrl("mrs_natural/hopSize");
00074   ctrl_srcFs_ = getctrl("mrs_real/srcFs");
00075   ctrl_maxPeriod_ = getctrl("mrs_natural/maxPeriod");
00076   ctrl_minPeriod_ = getctrl("mrs_natural/minPeriod");
00077   ctrl_agentControl_ = getctrl("mrs_realvec/agentControl");
00078   ctrl_beatDetected_ = getctrl("mrs_real/beatDetected");
00079   ctrl_tickCount_ = getctrl("mrs_natural/tickCount");
00080   ctrl_obsoleteFactor_ = getctrl("mrs_real/obsoleteFactor");
00081   ctrl_lostFactor_ = getctrl("mrs_natural/lostFactor");
00082   ctrl_childrenScoreFactor_ = getctrl("mrs_real/childrenScoreFactor");
00083   ctrl_bestFactor_ = getctrl("mrs_real/bestFactor");
00084   ctrl_eqPhase_ = getctrl("mrs_natural/eqPhase");
00085   ctrl_eqPeriod_ = getctrl("mrs_natural/eqPeriod");
00086   ctrl_corFactor_ = getctrl("mrs_real/corFactor");
00087   ctrl_child1Factor_ = getctrl("mrs_real/child1Factor");
00088   ctrl_child2Factor_ = getctrl("mrs_real/child2Factor");
00089   ctrl_child3Factor_ = getctrl("mrs_real/child3Factor");
00090   ctrl_backtrace_ = getctrl("mrs_bool/backtrace");
00091   ctrl_logFile_ = getctrl("mrs_string/logFile");
00092   ctrl_logFileName_= getctrl("mrs_string/logFileName");
00093   ctrl_soundFileSize_= getctrl("mrs_natural/soundFileSize");
00094   ctrl_bestFinalAgentHistory_= getctrl("mrs_realvec/bestFinalAgentHistory");
00095   ctrl_nonCausal_ = getctrl("mrs_bool/nonCausal");
00096   ctrl_triggerInduction_ = getctrl("mrs_bool/triggerInduction");
00097   ctrl_triggerInductionExternalRequest_ = getctrl("mrs_bool/triggerInductionExternalRequest");
00098   ctrl_gtInductionMode_ = getctrl("mrs_string/gtInductionMode");
00099   ctrl_triggerGtTolerance_ = getctrl("mrs_natural/triggerGtTolerance");
00100   ctrl_gtBeatsFile_ = getctrl("mrs_string/gtBeatsFile");
00101   ctrl_curBestScore_ = getctrl("mrs_real/curBestScore");
00102   ctrl_adjustment_ = getctrl("mrs_natural/adjustment");
00103   ctrl_inductionMode_ = getctrl("mrs_string/inductionMode");
00104   ctrl_beatTransitionTol_ = getctrl("mrs_real/beatTransitionTol");
00105   ctrl_destFileName_ = getctrl("mrs_string/destFileName");
00106   ctrl_triggerTimesFile_ = getctrl("mrs_string/triggerTimesFile");
00107   ctrl_resetAfterNewInduction_ = getctrl("mrs_bool/resetAfterNewInduction");
00108   ctrl_resetFeatWindow_ = getctrl("mrs_bool/resetFeatWindow");
00109   ctrl_supervisedTriggerThres_ = getctrl("mrs_real/supervisedTriggerThres");
00110 
00111   beatTransitionTol_ = a.beatTransitionTol_;
00112   considerAgentTransitionBeat_ = a.considerAgentTransitionBeat_;
00113   considerFatherTransitionBeat_ = a.considerFatherTransitionBeat_;
00114   timeElapsed_ = a.timeElapsed_;
00115   lastBeatPeriod_ = a.lastBeatPeriod_;
00116   historyCount_ = a.historyCount_;
00117   historyBeatTimes_ = a.historyBeatTimes_;
00118   lastBeatTime_ = a.lastBeatTime_;
00119   bestScore_ = a.bestScore_;
00120   bestAgentIndex_ = a.bestAgentIndex_;
00121   outputCount_ = a.outputCount_;
00122   initPeriod_ = a.initPeriod_;
00123   corFactor_ = a.corFactor_;
00124   backtrace_ = a.backtrace_;
00125   logFile_ = a.logFile_;
00126   logFileName_ = a.logFileName_;
00127   logFileUnits_ = a.logFileUnits_;
00128   triggerInduction_ = a.triggerInduction_;
00129   triggerInductionExternalRequest_ = a.triggerInductionExternalRequest_;
00130   processInduction_ = a.processInduction_;
00131   triggerInductionTime_ = a.triggerInductionTime_;
00132   inductionMode_ = a.inductionMode_;
00133   startSystem_ = a.startSystem_;
00134   startTracking_ = a.startTracking_;
00135   agentsHistory_ = a.agentsHistory_;
00136   agentsFamilyHist_ = a.agentsFamilyHist_;
00137   lostGTBeatsCount_ = a.lostGTBeatsCount_;
00138   lastGTBeatPos_ = a.lastGTBeatPos_;
00139   lastGTFileBeat_ = a.lastGTFileBeat_;
00140   triggerGtTolerance_ = a.triggerGtTolerance_;
00141   backtraceEndTime_ = a.backtraceEndTime_;
00142   bestAgentBeforeTrigger_ = a.bestAgentBeforeTrigger_;
00143   frames2SecsAdjustment_ = a.frames2SecsAdjustment_;
00144   lastGTFalsePos_ = a.lastGTFalsePos_;
00145   triggerTimes_ = a.triggerTimes_;
00146   transitionTimes_ = a.transitionTimes_;
00147   transitionsConsidered_ = a.transitionsConsidered_;
00148   resetAfterNewInduction_ = a.resetAfterNewInduction_;
00149   supervisedTriggerThres_ = a.supervisedTriggerThres_;
00150 }
00151 
00152 BeatReferee::~BeatReferee()
00153 {
00154 }
00155 
00156 MarSystem*
00157 BeatReferee::clone() const
00158 {
00159   return new BeatReferee(*this);
00160 }
00161 
00162 void
00163 BeatReferee::addControls()
00164 {
00165   //Add specific controls needed by this MarSystem.
00166   addctrl("mrs_realvec/mutedAgents", realvec(), ctrl_mutedAgents_);
00167   addctrl("mrs_realvec/inductionEnabler", realvec(2,2), ctrl_inductionEnabler_);
00168   addctrl("mrs_realvec/beatHypotheses", realvec(), ctrl_firstHypotheses_);
00169   addctrl("mrs_natural/inductionTime", -1, ctrl_inductionTime_);
00170   addctrl("mrs_natural/hopSize", -1, ctrl_hopSize_);
00171   setctrlState("mrs_natural/hopSize", true);
00172   addctrl("mrs_real/srcFs", -1.0, ctrl_srcFs_);
00173   setctrlState("mrs_real/srcFs", true);
00174   addctrl("mrs_natural/maxPeriod", -1, ctrl_maxPeriod_);
00175   setctrlState("mrs_natural/maxPeriod", true);
00176   addctrl("mrs_natural/minPeriod", -1, ctrl_minPeriod_);
00177   setctrlState("mrs_natural/minPeriod", true);
00178   addctrl("mrs_realvec/agentControl", realvec(50,4), ctrl_agentControl_);
00179   addctrl("mrs_real/beatDetected", 0.0, ctrl_beatDetected_);
00180   addctrl("mrs_natural/tickCount", 0, ctrl_tickCount_);
00181   addctrl("mrs_real/obsoleteFactor", 0.8, ctrl_obsoleteFactor_);
00182   setctrlState("mrs_real/obsoleteFactor", true);
00183   addctrl("mrs_natural/lostFactor", 4, ctrl_lostFactor_);
00184   setctrlState("mrs_natural/lostFactor", true);
00185   addctrl("mrs_real/childrenScoreFactor", 0.8, ctrl_childrenScoreFactor_);
00186   setctrlState("mrs_real/childrenScoreFactor", true);
00187   addctrl("mrs_real/bestFactor", 1.1, ctrl_bestFactor_);
00188   setctrlState("mrs_real/bestFactor", true);
00189   addctrl("mrs_natural/eqPhase", 2, ctrl_eqPhase_);
00190   setctrlState("mrs_natural/eqPhase", true);
00191   addctrl("mrs_natural/eqPeriod", 1, ctrl_eqPeriod_);
00192   setctrlState("mrs_natural/eqPeriod", true);
00193   addctrl("mrs_real/corFactor", 0.5, ctrl_corFactor_);
00194   setctrlState("mrs_real/corFactor", true);
00195   addctrl("mrs_real/child1Factor", 2.0, ctrl_child1Factor_);
00196   setctrlState("mrs_real/child1Factor", true);
00197   addctrl("mrs_real/child2Factor", 0.5, ctrl_child2Factor_);
00198   setctrlState("mrs_real/child2Factor", true);
00199   addctrl("mrs_real/child3Factor", 1.0, ctrl_child3Factor_);
00200   setctrlState("mrs_real/child3Factor", true);
00201   addctrl("mrs_bool/backtrace", false, ctrl_backtrace_);
00202   setctrlState("mrs_bool/backtrace", true);
00203   addctrl("mrs_string/logFile", "-1", ctrl_logFile_);
00204   addctrl("mrs_string/logFileName", "log.txt", ctrl_logFileName_);
00205   addctrl("mrs_natural/soundFileSize", 0, ctrl_soundFileSize_);
00206   setctrlState("mrs_natural/soundFileSize", true);
00207   addctrl("mrs_realvec/bestFinalAgentHistory", realvec(), ctrl_bestFinalAgentHistory_);
00208   addctrl("mrs_bool/nonCausal", false, ctrl_nonCausal_);
00209   setctrlState("mrs_bool/nonCausal", true);
00210   addctrl("mrs_bool/triggerInduction", false, ctrl_triggerInduction_);
00211   setctrlState("mrs_bool/triggerInduction", true);
00212   addctrl("mrs_bool/triggerInductionExternalRequest", false, ctrl_triggerInductionExternalRequest_);
00213   setctrlState("mrs_bool/triggerInductionExternalRequest", true);
00214   addctrl("mrs_string/gtInductionMode", "-1", ctrl_gtInductionMode_);
00215   setctrlState("mrs_string/gtInductionMode", true);
00216   addctrl("mrs_natural/triggerGtTolerance", 5, ctrl_triggerGtTolerance_);
00217   setctrlState("mrs_natural/triggerGtTolerance", true);
00218   addctrl("mrs_string/gtBeatsFile", "input.txt", ctrl_gtBeatsFile_);
00219   addctrl("mrs_real/curBestScore", NA, ctrl_curBestScore_);
00220   setctrlState("mrs_real/curBestScore", true);
00221   addctrl("mrs_natural/adjustment", 0, ctrl_adjustment_);
00222   setctrlState("mrs_natural/adjustment", true);
00223   addctrl("mrs_string/inductionMode", "single", ctrl_inductionMode_);
00224   addctrl("mrs_real/beatTransitionTol", 0.6, ctrl_beatTransitionTol_);
00225   addctrl("mrs_string/destFileName", "output", ctrl_destFileName_);
00226   addctrl("mrs_string/triggerTimesFile", "input_trigger.txt", ctrl_triggerTimesFile_);
00227   addctrl("mrs_bool/resetAfterNewInduction", true, ctrl_resetAfterNewInduction_);
00228   setctrlState("mrs_bool/resetAfterNewInduction", true);
00229   addctrl("mrs_bool/resetFeatWindow", true, ctrl_resetFeatWindow_);
00230   setctrlState("mrs_bool/resetFeatWindow", true);
00231   addctrl("mrs_real/supervisedTriggerThres", 0.0, ctrl_supervisedTriggerThres_);
00232 }
00233 
00234 void
00235 BeatReferee::myUpdate(MarControlPtr sender)
00236 {
00237   (void) sender;  //suppress warning of unused parameter(s)
00238   MRSDIAG("BeatReferee.cpp - BeatReferee:myUpdate");
00239 
00240   ctrl_onSamples_->setValue(1, NOUPDATE);
00241   ctrl_onObservations_->setValue(1, NOUPDATE);
00242   ctrl_osrate_->setValue(ctrl_israte_, NOUPDATE);
00243 
00244   lostFactor_ = ctrl_lostFactor_->to<mrs_natural>();
00245   obsoleteFactor_ = ctrl_obsoleteFactor_->to<mrs_real>();
00246   childrenScoreFactor_ = ctrl_childrenScoreFactor_->to<mrs_real>();
00247   bestFactor_ = ctrl_bestFactor_->to<mrs_real>();
00248   eqPhase_ = ctrl_eqPhase_->to<mrs_natural>();
00249   eqPeriod_ = ctrl_eqPeriod_->to<mrs_natural>();
00250   corFactor_ = ctrl_corFactor_->to<mrs_real>();
00251   child1Factor_ = ctrl_child1Factor_->to<mrs_real>();
00252   child2Factor_ = ctrl_child2Factor_->to<mrs_real>();
00253   child3Factor_ = ctrl_child3Factor_->to<mrs_real>();
00254   backtrace_ = ctrl_backtrace_->to<mrs_bool>();
00255   hopSize_ = ctrl_hopSize_->to<mrs_natural>();
00256   srcFs_ = ctrl_srcFs_->to<mrs_real>();
00257   maxPeriod_ = ctrl_maxPeriod_->to<mrs_natural>();
00258   minPeriod_ = ctrl_minPeriod_->to<mrs_natural>();
00259   nonCausal_ = ctrl_nonCausal_->to<mrs_bool>();
00260   inductionMode_ = ctrl_inductionMode_->to<mrs_string>();
00261   gtBeatsFile_ = ctrl_gtBeatsFile_->to<mrs_string>();
00262   triggerGtTolerance_ = ctrl_triggerGtTolerance_->to<mrs_natural>();
00263   frames2SecsAdjustment_ = ctrl_adjustment_->to<mrs_natural>();
00264   beatTransitionTol_ = ctrl_beatTransitionTol_->to<mrs_real>();
00265   triggerTimesFile_ = ctrl_triggerTimesFile_->to<mrs_string>();
00266   resetAfterNewInduction_ = ctrl_resetAfterNewInduction_->to<mrs_bool>();
00267   supervisedTriggerThres_ = ctrl_supervisedTriggerThres_->to<mrs_real>();
00268 
00269   //cout << "TRIGGERTIME @ " << timeElapsed_ << ": " <<  triggerInductionTime_ << endl;
00270   //triggerInductionTime_ = ctrl_triggerInductionTime_->to<mrs_natural>();
00271   //cout << "TRIGGERTIME @ " << timeElapsed_ << ": " <<  triggerInductionTime_ << endl;
00272 
00273   //inObservations_ = number of BeatAgents in the pool
00274   nrAgents_ = inObservations_;
00275   historyCount_.create(nrAgents_); //1index for each agent
00276   agentsJustCreated_.create(nrAgents_); //to know which agents were created on current frame
00277 
00278   soundFileSize_ = ctrl_soundFileSize_->to<mrs_natural>();
00279   //max possible nr. of beats in the analysed sound file (*1.2 - tolerance due to possible limit surpassing)
00280   maxNrBeats_ = (mrs_natural) (ceil(((mrs_real) soundFileSize_) / ((mrs_real) minPeriod_)) * 1.2);
00281 
00282   inductionTime_ = ctrl_inductionTime_->to<mrs_natural>();
00283   inductionEnabler_ = ctrl_inductionEnabler_->to<mrs_realvec>();
00284 
00285   //wait timeBeforeKill secs before considering killing obsolete agents
00286   mrs_real timeBeforeKill = 0.0;
00287   timeBeforeKilling_ = (mrs_natural)(timeBeforeKill*srcFs_/hopSize_);
00288 }
00289 
00290 mrs_bool
00291 BeatReferee::loadTriggerTimes(mrs_string triggerTimesFile)
00292 {
00293   if (fopen(triggerTimesFile.c_str(), "r"))
00294   {
00295     cerr << "TriggerTimes File: " << triggerTimesFile.c_str() << endl;
00296 
00297     ifstream inStream;
00298     mrs_string line;
00299     inStream.open(triggerTimesFile.c_str());
00300     getline (inStream, line);
00301 
00302     mrs_natural countTriggers = 0;
00303     while(strtod(line.c_str(), NULL) > 0.0)
00304     {
00305       getline (inStream, line);
00306       countTriggers++;
00307     }
00308     triggerTimes_.create(countTriggers);
00309     transitionTimes_.create(countTriggers);
00310     transitionsConsidered_.create(countTriggers);
00311     inStream.close();
00312     inStream.open(triggerTimesFile.c_str());
00313     mrs_natural validTriggersCount = 0;
00314     mrs_real indTimeSecs = ((inductionTime_ * hopSize_) - (frames2SecsAdjustment_)) / srcFs_;
00315     for(mrs_natural i = 0; i < countTriggers; i++)
00316     {
00317       getline (inStream, line);
00318       mrs_real triggerTime = strtod(line.c_str(), NULL);
00319       //cout << "triggerTime: " << triggerTime << "; inductionTime: " << indTimeSecs << endl;
00320       if(triggerTime >= indTimeSecs)
00321       {
00322         //sum the size of the induction window to every trigger time
00323         //so the actual trigger is only activated one window after
00324         transitionTimes_(validTriggersCount) = ((mrs_natural) (triggerTime * (srcFs_/hopSize_) + 0.5));
00325         triggerTimes_(validTriggersCount) =  transitionTimes_(validTriggersCount) + inductionTime_;
00326         transitionsConsidered_(validTriggersCount) = 0.0;
00327         validTriggersCount++;
00328       }
00329     }
00330 
00331     //cout << "trigger times (" << countTriggers << "): ";
00332     //for(mrs_natural i = 0; i < triggerTimes_.getSize(); i++)
00333     //{
00334     //  cout << triggerTimes_(i) << " ";
00335     //}
00336     //cout << endl;
00337 
00338     inStream.close();
00339 
00340     return true;
00341   }
00342   else
00343   {
00344     cerr << "Bad or nonexistent transition times file: " << triggerTimesFile.c_str() << "\nPlease specify a supported one." << endl;
00345     return false;
00346   }
00347 }
00348 
00349 mrs_bool
00350 BeatReferee::isGTFileInLine(mrs_string line)
00351 {
00352 
00353   //for beat groundtruth files (in line, separated by spaces):
00354   mrs_natural pos0;
00355   pos0 = (mrs_natural) line.find_first_of(" ", 0); //initial delimiter
00356 
00357   //if pos0 < 0 => one beat time per line
00358   return (pos0 > 0 ? true : false);
00359 }
00360 
00361 //Routine for comparing the current detected beat to the correspondent ground-truth beat-time
00362 //(to be used in trigger induction ground-truth mode):
00363 //0-> beat matches!
00364 //1-> false positive!
00365 //n-> nr. of false negatives
00366 mrs_natural
00367 BeatReferee::checkBeatInGTFile()
00368 {
00369   mrs_natural localBeatErrorCount = 0;
00370   mrs_real fMeasureTol = 0.07; //70ms used in Fmeasure tolerance
00371   mrs_real beatTime = ((timeElapsed_ * hopSize_) - (frames2SecsAdjustment_)) / srcFs_;
00372   //cout << "\nchecking: " << gtBeatsFile_ << "; beatTime: " << beatTime << endl;
00373 
00374   ifstream inStream;
00375   mrs_string line;
00376   inStream.open(gtBeatsFile_.c_str());
00377   getline (inStream, line); //get first line
00378 
00379   //if beat times in gt file are all given in the first line (separated by spaces)
00380   if(isGTFileInLine(line))
00381   {
00382     mrs_bool beatPosFound = false;
00383     mrs_natural curGTBeatPos, firstGTBeatPos;
00384     mrs_real lastGTBeatTime = 0, curGTBeatTime;
00385     mrs_real lastDiffBeats; //just a big number
00386     mrs_real diffBeats = 0;
00387     mrs_real tolWinLft, tolWinRgt;
00388 
00389     //check gtfile for eof at first run
00390     if(lastGTBeatPos_ < 0)
00391     {
00392       std::istringstream iss(line);
00393       char c[10]; //big enough array
00394       while (iss >> c) //space ("") delimiter
00395       {
00396         //last c contains last value in file
00397         lastGTFileBeat_ = atof(c); //save end value
00398       }
00399       iss.clear();
00400     }
00401 
00402     //check if end of file
00403     mrs_real beatTimeCheck = (((timeElapsed_+2) * hopSize_) - (frames2SecsAdjustment_)) / srcFs_; //(timeElapsed_+1 (+1 tolerance) because induction is always called in the next tick)
00404     if(beatTimeCheck >= lastGTFileBeat_)
00405       return 0;
00406 
00407     //cout << "pos1: " << pos1 << "; pos2: " << pos2 << "; pos3: " << pos3 << "bt: " << strtod(line.substr(pos1, pos2).c_str(), NULL) << endl;
00408 
00409     //discard initial induction time if in real-time mode (no backtrace)
00410     if((backtraceEndTime_ == -1 && !backtrace_) || timeElapsed_ > backtraceEndTime_)
00411     {
00412       mrs_real indTimeSecs = ((inductionTime_ * hopSize_) - (frames2SecsAdjustment_)) / srcFs_;
00413       do
00414       {
00415         //cout << "1-lastGTBeatTime: " << lastGTBeatTime << "; indTime: " << indTimeSecs << endl;
00416         curGTBeatPos = (mrs_natural) line.find_first_of(" ", lastGTBeatPos_); //current delimiter
00417         lastGTBeatTime = strtod(line.substr(lastGTBeatPos_+1, curGTBeatPos).c_str(), NULL);
00418 
00419         if(lastGTBeatTime >= indTimeSecs) break;
00420 
00421         lastGTBeatPos_ = (mrs_natural) line.find_first_of(" ", lastGTBeatPos_+1); //current last delimiter
00422 
00423       } while(lastGTBeatTime < indTimeSecs);
00424     }
00425     else //retrieve first gt beat time (starting from previous call) [First iteration must be outside cycle!!]
00426     {
00427       //cout << "1-BeatTime: " << beatTime << "; GTBeatTime: " << lastGTBeatTime << "; lasGTPos: " << lastGTBeatPos_ << endl;
00428 
00429       lastGTBeatPos_ = (mrs_natural) line.find_first_of(" ", lastGTBeatPos_); //current last delimiter
00430       curGTBeatPos = (mrs_natural) line.find_first_of(" ", lastGTBeatPos_+1); //current delimiter
00431       lastGTBeatTime = strtod(line.substr(lastGTBeatPos_+1, curGTBeatPos).c_str(), NULL);
00432     }
00433 
00434     firstGTBeatPos = lastGTBeatPos_; //save current first gt beat position
00435 
00436     //cout << "2-BeatTime: " << beatTime << "; GTBeatTime: " << lastGTBeatTime << "; lasGTPos: " << lastGTBeatPos_ << endl;
00437 
00438     //first match check:
00439     tolWinLft = lastGTBeatTime - fMeasureTol;
00440     tolWinRgt = lastGTBeatTime + fMeasureTol;
00441     if(beatTime >= tolWinLft && beatTime <= tolWinRgt)
00442     {
00443       localBeatErrorCount = 0;
00444       lastGTBeatPos_ = (mrs_natural) line.find_first_of(" ", lastGTBeatPos_+1); //go to next position (for next computed beat)
00445       //cout << "MATCHES1-> B: " << beatTime << "; gtB: " << lastGTBeatTime << "; tolL: " << tolWinLft << "; tolR: " << tolWinRgt << endl;
00446     }
00447     else //if first gt not matches:
00448     {
00449       //FALSE NEGATIVE:
00450       //if last error was a false positive
00451       if(beatTime > tolWinRgt && lastGTFalsePos_)
00452       {
00453         //advance one ground-truth beat (due to transition beat between FP and FN)
00454         lastGTBeatPos_ = (mrs_natural) line.find_first_of(" ", lastGTBeatPos_+1); //current last delimiter
00455         curGTBeatPos = (mrs_natural) line.find_first_of(" ", lastGTBeatPos_+1); //current delimiter
00456         lastGTBeatTime = strtod(line.substr(lastGTBeatPos_+1, curGTBeatPos).c_str(), NULL);
00457         tolWinLft = lastGTBeatTime - fMeasureTol;
00458 
00459         tolWinRgt = lastGTBeatTime + fMeasureTol;
00460 
00461         //cout << "2.2-BeatTime: " << beatTime << "; GTBeatTime: " << lastGTBeatTime << "; lasGTPos: " << lastGTBeatPos_ << endl;
00462 
00463         firstGTBeatPos = lastGTBeatPos_; //update current first gt beat position
00464 
00465         lastGTFalsePos_ = false;
00466       }
00467 
00468       lastDiffBeats = abs(beatTime - lastGTBeatTime);
00469 
00470       //cout << "(1)gtCurBeat: " << lastGTBeatTime << "(" << tolWinRgt << ") beatTime: " << beatTime << endl;
00471       //STILL FALSE NEGATIVE
00472       if(beatTime > tolWinRgt)
00473       {
00474         //start false negative search with current global errors
00475         mrs_natural beatErrorCount = 0;
00476 
00477         //cout << "FALSE_NEG(S)-> ";
00478         //count nr. of false negatives
00479         do {
00480           beatErrorCount++;
00481 
00482           //cout << "bT: " << beatTime << "; lastGTBT: " << lastGTBeatTime << " bE: " << beatErrorCount << " bT: " << triggerGtTolerance_ << endl;
00483 
00484           lastGTBeatPos_ = (mrs_natural) line.find_first_of(" ", lastGTBeatPos_+1); //current last delimiter
00485           curGTBeatPos = (mrs_natural) line.find_first_of(" ", lastGTBeatPos_+1); //current delimiter
00486           lastGTBeatTime = strtod(line.substr(lastGTBeatPos_+1, curGTBeatPos).c_str(), NULL);
00487           tolWinLft = lastGTBeatTime - fMeasureTol;
00488           tolWinRgt = lastGTBeatTime + fMeasureTol;
00489 
00490           //cout << lastGTBeatTime << "; ";
00491 
00492           //when beat-time matches current ground-truth beat-time:
00493           //- clean the global beat error count if < triggerGtTolerance_
00494           //- assign value to global error if surpasses triggerGtTolerance_ (for triggering induction)
00495           if(beatTime >= tolWinLft && beatTime <= tolWinRgt)
00496           {
00497 
00498             if((beatErrorCount + lostGTBeatsCount_) < triggerGtTolerance_)
00499               beatErrorCount = 0;
00500 
00501             //go to next delimiter
00502             lastGTBeatPos_ = (mrs_natural) line.find_first_of(" ", lastGTBeatPos_+1);
00503 
00504             break; //finishes false negative search when beat matches!
00505           }
00506           else if(beatTime <= tolWinRgt) break; //finishes false negative search when beat surpasses gt beat-time!
00507 
00508         } while(beatTime > tolWinRgt);
00509 
00510         localBeatErrorCount = beatErrorCount;
00511         //go to next delimiter
00512         //lastGTBeatPos_ = (mrs_natural) line.find_first_of(" ", lastGTBeatPos_+1);
00513 
00514         //cout << "(" << beatTime << ")" << endl;
00515       }
00516       //FALSE POSITIVE
00517       else
00518       {
00519         //mrs_real keepInitGTBeatTime = lastGTBeatTime; //keep it for printing in FP error
00520         do //check if false postive (reinforcement -> one iteration should be enough)
00521         {
00522           lastGTBeatPos_ = (mrs_natural) line.find_first_of(" ", lastGTBeatPos_+1); //current last delimiter
00523           curGTBeatPos = (mrs_natural) line.find_first_of(" ", lastGTBeatPos_+1); //current delimiter
00524           curGTBeatTime = strtod(line.substr(lastGTBeatPos_+1, curGTBeatPos).c_str(), NULL);
00525 
00526           diffBeats = abs(beatTime - curGTBeatTime);
00527           //cout << "gtCurBeat: " << curGTBeatTime << "; beatTime: " << beatTime << "; diff: " << diffBeats << endl;
00528 
00529           //find min distance between computed and annotated beat time
00530           if(diffBeats > lastDiffBeats) //if current distance bigger than previous => check if computed is correct
00531           {
00532             //computed beat is correct if it matches the annotated beat within a tolerance window
00533             tolWinLft = lastGTBeatTime - fMeasureTol;
00534             tolWinRgt = lastGTBeatTime + fMeasureTol;
00535 
00536             //cout << "tolLft: " << tolWinLft << "; tolRgt: " << tolWinRgt << endl;
00537             if(beatTime >= tolWinLft && beatTime <= tolWinRgt) //for safecheck
00538             {
00539               //beat matches!
00540               localBeatErrorCount = 0;
00541               //cout << "MATCHES2-> B: " << beatTime << "; gtB: " << lastGTBeatTime << "; tolL: " << tolWinLft << "; tolR: " << tolWinRgt << endl;
00542             }
00543             else //false positive!
00544             {
00545               localBeatErrorCount = 1;
00546               //cout << "FALSE_POS-> B: " << beatTime << " (" << keepInitGTBeatTime << ") -> GT: " << lastGTBeatTime << endl;
00547               lastGTBeatPos_ = firstGTBeatPos; //go back to previous beat
00548               lastGTFalsePos_ = true;
00549             }
00550 
00551             beatPosFound = true;
00552             break;
00553           }
00554           lastDiffBeats = diffBeats;
00555           lastGTBeatTime = curGTBeatTime;
00556 
00557         } while(beatPosFound == false);
00558       }
00559     }
00560   }
00561   /*
00562   else //if beat times given in column (one beat times per line)
00563   {
00564 
00565   }
00566   */
00567   /*
00568   //if more than two beatTimes given in the annotation file
00569   //discart initial beatTime (due to inconsistencies in the beggining of some annotation files)
00570   if(pos1 >= 0)
00571   {
00572     gtBeatTime1_ = strtod(line.substr(pos0+1, pos1).c_str(), NULL);
00573     gtBeatTime2_ = strtod(line.substr(pos1+1, pos2).c_str(), NULL);
00574     gtAfter2ndBeat_ = true;
00575   }
00576   else //if only two beatTimes given keep them as they are
00577   {
00578     gtBeatTime1_ = strtod(line_.substr(0, pos1).c_str(), NULL);
00579     gtBeatTime2_ = strtod(line_.substr(pos0+1, pos1).c_str(), NULL);
00580   }
00581 
00582   //==========================================================
00583 
00584   //to assure that it could read from file => beatFile in column (ifnot => beatFile in row)
00585   if(gtBeatTime1_ == gtBeatTime2_ || gtBeatTime2_ == 0.0 || gtBeatTime2_ > 40)
00586   {
00587     gtBeatTime1_ = atof(line_.c_str());
00588     getline (inStream_, line_);
00589     gtBeatTime2_ = atof(line_.c_str());
00590 
00591     //if more than two beatTimes given in the annotation file
00592     //discart initial beatTime (due to inconsistencies in the beggining of some annotation files)
00593     if(getline (inStream_, line_) > 0)
00594     {
00595         gtBeatTime1_ = gtBeatTime2_;
00596         gtBeatTime2_ = atof(line_.c_str());
00597         gtAfter2ndBeat_ = true;
00598     }
00599   }
00600   */
00601   //for printing:
00602   //mrs_natural curGTBeatPos = (mrs_natural) line.find_first_of(" ", lastGTBeatPos_+1); //current delimiter
00603   //mrs_real lastGTBeatTime = strtod(line.substr(lastGTBeatPos_+1, curGTBeatPos).c_str(), NULL);
00604   //cout << "nextGTBeatTime: " << lastGTBeatTime << endl;
00605   //cout << "beatError: " << localBeatErrorCount << endl;
00606   return localBeatErrorCount;
00607 }
00608 
00609 void
00610 BeatReferee::grantPoolSpaceForTriggerAgents(mrs_realvec triggerAgentsHypotheses)
00611 {
00612   mrs_real agentInitScore;
00613   for(int a = 0; a < triggerAgentsHypotheses.getRows(); a++)
00614   {
00615     agentInitScore = triggerAgentsHypotheses(a, 2);
00616     grantPoolSpace(-1, agentInitScore);
00617 
00618     //cout << timeElapsed_ << ": CHECKING POOL SPACE for score: " << agentInitScore << endl;
00619 
00620 
00621 
00622   }
00623 }
00624 
00625 //define clusters of similar periods
00626 //(like IBI histograms -> Dixon2001)
00627 mrs_realvec
00628 BeatReferee::clusterIBIs()
00629 {
00630   mrs_natural similarityTol = 2; //(2frames tol => ~23ms with hopSize = 512 && srcFr = 44100)
00631   mrs_real minPerDiff = MAXREAL;
00632   mrs_natural cluster = -1;
00633   mrs_realvec periodClusters(nrAgents_, nrAgents_); //(agents belonging to that cluster, per cluster index)
00634   mrs_realvec periodClustersInfo(nrAgents_, 2); //(nr. of cluster members, per cluster index; mean Period of each cluster, per cluster index)
00635   mrs_real agentPeriod;
00636   mrs_natural nrClusterMembers;
00637   mrs_real clusterPerMean;
00638 
00639   for(int a = 0; a < nrAgents_; a++) //for all agents
00640   {
00641     //if(!mutedAgentsTmp_(a)) //if agent exists
00642     //only consider alive agents, which existed before (not created in this frame - to avoid adoption between brothers of the same generation)
00643     if(!mutedAgentsTmp_(a) && !agentsJustCreated_(a) && agentsFamilyHist_(a, ((mrs_natural) beatCounter_(a)-1)) == a)
00644     {
00645       agentPeriod = lastPeriods_(a);
00646 
00647       //cout << "AGENT " << a << ": PERIOD: " << agentPeriod << endl;
00648 
00649       for(int c = 0; c < nrAgents_; c++) //for all clusters
00650       {
00651         nrClusterMembers = (mrs_natural)periodClustersInfo(c, 0);
00652         clusterPerMean = periodClustersInfo(c, 1);
00653 
00654         //cout << "\nCluster: " << c << "; nrMembers: " << nrClusterMembers << "; perMean: " << clusterPerMean;
00655 
00656         if(nrClusterMembers > 0) //if cluster already have members
00657         {
00658           //calc diff between period and cluster current mean
00659           mrs_real perDiff = fabs(agentPeriod - clusterPerMean);
00660 
00661           //cout << "; perDiff: " << perDiff << "; minDiff: " << minPerDiff << endl;
00662 
00663           if(perDiff <= similarityTol) //check if diff respects tolerance
00664           {
00665             //check minimum difference to assign period to that cluster
00666             if(perDiff < minPerDiff)
00667             {
00668               minPerDiff = perDiff;
00669               cluster = c; //keep cluster index which presents minimum difference
00670 
00671               //cout << "Agent " << a << " tmp assigned to " << cluster << endl;
00672             }
00673           } //if not below tolerance keepon searching for a similar cluster
00674         }
00675       }
00676 
00677       if(cluster >= 0) //if cluster exists => assign agent and its period to chosen cluster
00678       {
00679         mrs_natural selectedClusterNrMembers = (mrs_natural)periodClustersInfo(cluster, 0);
00680         mrs_real selectedClusterMean = 0.0;
00681 
00682         periodClusters(cluster, selectedClusterNrMembers) = a; //save agent in free cluster index
00683 
00684         selectedClusterNrMembers++;
00685         //calculate cluster mean period
00686         for(int m = 0; m < selectedClusterNrMembers; m++)
00687         {
00688           selectedClusterMean += lastPeriods_((mrs_natural)periodClusters(cluster, m));
00689           //if(timeElapsed_ == 3898)
00690           //    cout << "curClMean: " << selectedClusterMean << "; curPer: " << lastPeriods_((mrs_natural)periodClusters(cluster, m))
00691           //        << " from " << periodClusters(cluster, m) << endl;
00692         }
00693         selectedClusterMean = selectedClusterMean / selectedClusterNrMembers;
00694 
00695         //if(timeElapsed_ == 3898)
00696         //  cout << "\nAgent " << a << "(" << periodClusters(cluster, selectedClusterNrMembers-1) << ") ASSIGNED TO "
00697         //      << cluster << "; newPer: " << agentPeriod << "; lastMean: " << periodClustersInfo(cluster, 1)
00698         //      << "; updMembers: " << selectedClusterNrMembers << "; updClPerMean: " << selectedClusterMean << endl;
00699 
00700         periodClustersInfo(cluster, 0) = selectedClusterNrMembers;
00701         periodClustersInfo(cluster, 1) = selectedClusterMean;
00702 
00703         minPerDiff = MAXREAL;
00704         cluster = -1; //reset selected cluster
00705       }
00706       else //if not -> create new cluster with this agent as first member
00707       {
00708         //cout << "NEW CLUSTER FOR AGENT " << a << endl;
00709 
00710         for(int c = 0; c < nrAgents_; c++) //for all clusters -> select first empty
00711         {
00712           nrClusterMembers = (mrs_natural)periodClustersInfo(c, 0);
00713           if(nrClusterMembers == 0) //if cluster is empty
00714           {
00715             periodClusters(c, nrClusterMembers) = a;
00716             periodClustersInfo(c, 0) = 1;
00717             periodClustersInfo(c, 1) = agentPeriod; //initial cluster mean period
00718 
00719             //cout << "Agent " << a << "(" << periodClusters(c, nrClusterMembers) << ") ASSIGNED TO NEW: " << c
00720             //  << "; updMembers: " << periodClustersInfo(c, 0) << "; updClPerMean: " << periodClustersInfo(c, 1) << endl;
00721 
00722             break;
00723           }
00724         }
00725       }
00726     }
00727   }
00728 
00729   //MATLAB_PUT(periodClusters, "clustersPer1");
00730   //MATLAB_PUT(periodClustersInfo, "clustersPerInfo1");
00731 
00732   //in the end cluster similar clusters due to cluster period mean being constantly updated during search above
00733   //(use same tolerance to cluster them)
00734   mrs_natural nrClusterMembers1, nrClusterMembers2, nrClusterMembersTot;
00735   mrs_real clusterPerMean1, clusterPerMean2;
00736   mrs_real clusterPerMeanTot = 0.0;
00737   for(int c = 0; c < nrAgents_; c++) //for all clusters
00738   {
00739     nrClusterMembers1 = (mrs_natural)periodClustersInfo(c, 0);
00740 
00741     //cout << "\nVERIFYING cluster1: " << c << "; memb1: " << nrClusterMembers1;
00742 
00743     if(nrClusterMembers1 > 0) //if cluster exists
00744     {
00745       clusterPerMean1 = periodClustersInfo(c, 1);
00746 
00747       //cout << "; perMean1: " << clusterPerMean1;
00748 
00749       for(int cc = 0; cc < nrAgents_; cc++) //for all other clusters
00750       {
00751         nrClusterMembers2 = (mrs_natural)periodClustersInfo(cc, 0);
00752 
00753         //cout << "\nCOMP with2: " << cc << "; meb2: " << nrClusterMembers2;
00754 
00755         if(cc != c && nrClusterMembers2 > 0) //if 2nd cluster is different than first, and it also exists
00756         {
00757           clusterPerMean2 = periodClustersInfo(cc, 1);
00758 
00759           //cout << "; perMean2: " << clusterPerMean2 << endl;
00760 
00761           //if both clusters are considered similar
00762           if(fabs(clusterPerMean1 - clusterPerMean2) <= similarityTol)
00763           {
00764             //transfer all info from second cluster to first and erase second
00765             nrClusterMembersTot = nrClusterMembers1 + nrClusterMembers2;
00766             for(int i = 0; i < nrClusterMembers2; i++)
00767             {
00768               periodClusters(c, nrClusterMembers1+i) = periodClusters(cc, i);
00769               periodClusters(cc, i) = 0.0;
00770             }
00771 
00772             //calculate cluster mean period
00773             for(int m = 0; m < nrClusterMembersTot; m++)
00774               clusterPerMeanTot += lastPeriods_((mrs_natural)periodClusters(c, m));
00775 
00776             clusterPerMeanTot = clusterPerMeanTot / nrClusterMembersTot;
00777 
00778             //update first cluster info
00779             periodClustersInfo(c, 0) = nrClusterMembersTot;
00780             periodClustersInfo(c, 1) = clusterPerMeanTot;
00781             //erase second cluster info
00782             periodClustersInfo(cc, 0) = 0.0;
00783             periodClustersInfo(cc, 1) = 0.0;
00784 
00785             //cout << "CLUSTER2: " << cc << " CLUSTERED WITH1: " << c << endl;
00786           }
00787         }
00788       }
00789     }
00790   }
00791 
00792   //MATLAB_PUT(periodClusters, "clustersPer2");
00793   //MATLAB_PUT(periodClustersInfo, "clustersPerInfo2");
00794 
00795   //cout << "\n===================!!OK!!====================" << endl;
00796 
00797   //return all clusters members, per cluster index (per line); and last two columns with nrElems; meanPer of each cluster
00798   mrs_realvec completedClustersPer(nrAgents_, nrAgents_+2);
00799   //copy periodClusters realvec
00800   for(int i = 0; i < nrAgents_; i++)
00801   {
00802     for(int j = 0; j < nrAgents_; j++)
00803     {
00804       completedClustersPer(i, j) = periodClusters(i, j);
00805       //cout << "copied " << i << " + " << j << "; completedClustersPer: " << completedClustersPer(i, j) << endl;
00806     }
00807 
00808     //add column with mean periods of each cluster
00809     completedClustersPer(i, nrAgents_) = periodClustersInfo(i, 0);
00810     completedClustersPer(i, nrAgents_+1) = periodClustersInfo(i, 1);
00811 
00812     //MATLAB_PUT(completedClustersPer, "completedClustersPerTMP");
00813 
00814     //cout << "copied " << i << " + " << nrAgents_ << ": " << completedClustersPer(i, nrAgents_) << "; info: " << periodClustersInfo(i, 1) << endl;
00815   }
00816 
00817   //cout << "\n===================!!OKTOTAL!!====================" << endl;
00818 
00819   //MATLAB_PUT(completedClustersPer, "completedClustersPer");
00820 
00821   return completedClustersPer;
00822 }
00823 
00824 //Get best similar agent to selected -> pick the best agent from the most similar period cluster
00825 mrs_natural
00826 BeatReferee::getBestSimilarAgent3(mrs_natural newAgentPeriod, mrs_realvec completedClustersPer)
00827 {
00828   //if(timeElapsed_ == 3583)
00829   //    MATLAB_PUT(completedClustersPer, "ClusterPerBestSimilar");
00830 
00831   //if(timeElapsed_ == 3583)
00832   //    cout << "GET BEST SIMILAR FOR PERIOD " << newAgentPeriod << endl;
00833 
00834   //check to each period cluster belongs the new agent
00835   mrs_real minPerDiff = MAXREAL;
00836   mrs_natural selectedCluster = -1;
00837   for(int c = 0; c < nrAgents_; c++) //for all clusters
00838   {
00839     if(completedClustersPer(c, nrAgents_) > 0.0) //if cluster exists
00840     {
00841       mrs_real clusterPeriod = completedClustersPer(c, nrAgents_+1);
00842       mrs_real perDiff = fabs(newAgentPeriod - clusterPeriod);
00843 
00844       //cout << "\nCLUSTER " << c << "; clusterPer: " << clusterPeriod << "; perDiff: " << perDiff << "; minDiff: " << minPerDiff << endl;
00845 
00846       //check min diff between with all clusters
00847       if(perDiff < minPerDiff)
00848       {
00849         minPerDiff = perDiff;
00850         selectedCluster = c;
00851 
00852         //cout << "Tmp assigned to cluster " << selectedCluster << " with diff: " << perDiff << endl;
00853       }
00854     }
00855   }
00856 
00857   //pick best agent from selected period cluster
00858   mrs_real bestClusterScore = NA;
00859   mrs_natural bestClusterAgent = -1;
00860   mrs_natural clusterAgent;
00861   mrs_natural nrSelectedClusterMembers = (mrs_natural) completedClustersPer(selectedCluster, nrAgents_);
00862 
00863   //if(timeElapsed_ == 3898)
00864   //    cout << "\nASSIGNED TO CLUSTER " << selectedCluster << " WITH " << nrSelectedClusterMembers
00865   //        << " ELEMENTS and " << completedClustersPer(selectedCluster, nrAgents_+1)
00866   //        << " PERIOD for Agentperiod: " << newAgentPeriod << endl;
00867 
00868   for(int a = 0; a < nrSelectedClusterMembers; a++)
00869   {
00870     clusterAgent = (mrs_natural) completedClustersPer(selectedCluster, a);
00871 
00872     //cout << "From Cluster " << selectedCluster << "; agent: " << clusterAgent << "; Score: " << score_(clusterAgent)
00873     //  << "; bestClSc: " << bestClusterScore << endl;
00874 
00875     if(!mutedAgents_(clusterAgent) && (clusterAgent) > bestClusterScore) //verify if agent really exists
00876     {
00877       bestClusterScore = score_(clusterAgent);
00878       bestClusterAgent = clusterAgent;
00879 
00880       //cout << "Tmp Best Similar: " << bestClusterAgent << "; bestClSc: " << bestClusterScore << endl;
00881     }
00882   }
00883 
00884   //if(timeElapsed_ == 3100)
00885   //    cout << "BEST CLUSTER AGENT: " << bestClusterAgent << " WITH SCORE: " << bestClusterScore << "(" << score_(clusterAgent) << ")" << endl;
00886 
00887   return bestClusterAgent;
00888 }
00889 
00890 //Get best similar agent to selected -> based on heuristics
00891 //[CHANGE -> IGNORE PHASE IN HEURISTICS -> transition phase is handled by handleAgentsTansition()!!!]
00892 mrs_natural
00893 BeatReferee::getBestSimilarAgent(mrs_natural newAgentPeriod, mrs_natural newAgentInitPhase, mrs_real newAgentScore)
00894 {
00895   mrs_real bestSimilarScore = NA; //just a big negative nr
00896   mrs_natural bestSimilarAgent = -1;
00897   mrs_natural period, phaseRaw, phase, k;
00898   mrs_realvec periodDiffs(nrAgents_);
00899   mrs_realvec phaseDiffs(nrAgents_);
00900   mrs_realvec bestSimilarity(nrAgents_);
00901   mrs_real fraction;
00902 
00903   //if(timeElapsed_ == 2461 && newAgentPeriod == 57)
00904   //    cout << "NEW AGENT-> period: " << newAgentPeriod << "; phase: " << newAgentInitPhase << endl;
00905 
00906   //Grant available space in the pool, by removing the worst agent, if needed
00907   grantPoolSpace(-1, newAgentScore);
00908 
00909   //calculate maximum possible difference (for normalizing the best similarity heuristics)
00910   //maximum difference occur when one agent has the maxPeriod and other the minPeriod
00911   //=> maximum phase difference for this period difference = minPeriod
00912   mrs_real maxHypDiff = (3 * (maxPeriod_ - minPeriod_) + minPeriod_);
00913   //save all period and phase differences with each agent
00914   for(int a = 0; a < nrAgents_; a++)
00915   {
00916     //only consider alive agents, which existed before (not created in this frame - to avoid adoption between brothers of the same generation)
00917     //if(!mutedAgentsTmp_(a) && !agentsJustCreated_(a))
00918     if(!mutedAgentsTmp_(a) && !agentsJustCreated_(a) && agentsFamilyHist_(a, ((mrs_natural) beatCounter_(a)-1)) == a)
00919     {
00920       //cout << "Agent " << a << " ok: " << agentsFamilyHist_(a, ((mrs_natural) beatCounter_(a)-1)) << endl;
00921       period = (mrs_natural) lastPeriods_(a);
00922       phaseRaw = (mrs_natural) lastPhases_(a);
00923 
00924       //transpose compared agent phase to new agent phase location
00925       k = (mrs_natural) (((mrs_real)(newAgentInitPhase - phaseRaw) / period) + 0.5);
00926       phase = phaseRaw + k * period;
00927 
00928       periodDiffs(a) = abs(newAgentPeriod - period);
00929       phaseDiffs(a) = abs(newAgentInitPhase - phase);
00930 
00931       //heuristics for calculating degree of best similarity with each agent
00932       //compared agent's score proportion of (3*periodDiff + 1*phaseDiff) [give 3x more relevance to period than phase]
00933       //bestSimilarity(a) = ((1/(3*periodDiffs(a))) + (1/phaseDiffs(a))) * score_(a);
00934       fraction = (1 - ((3*periodDiffs(a) + phaseDiffs(a)) / maxHypDiff));
00935 
00936       if(score_(a) > 0) //to avoid bestScore inversions
00937         bestSimilarity(a) = fraction * score_(a);
00938       else
00939         bestSimilarity(a) = score_(a) / fraction;
00940 
00941       //check who's best similar based on heuristics above
00942       if(bestSimilarity(a) > bestSimilarScore)
00943       {
00944         //if(timeElapsed_ == 2461 && newAgentPeriod == 57)
00945         //  cout << "============ curBestSimilarScore: " << bestSimilarScore << "; new from " << a << ": " << bestSimilarity(a) << endl;
00946         bestSimilarScore = bestSimilarity(a);
00947         bestSimilarAgent = a;
00948       }
00949 
00950       //if(timeElapsed_ == 2461 && newAgentPeriod == 57)
00951       //    cout << "Agent " << a << "; period: " << period << "; phaseRaw: " << phaseRaw << "; phase: " << phase << "(" << k
00952       //        << "); perDiff: " << periodDiffs(a) << "; phDiff: " << phaseDiffs(a) << "; fraction: " << fraction
00953       //        << "; score: " << score_(a) << "; simSc: " << bestSimilarity(a) << " (" << bestSimilarScore << "->"
00954       //        << bestSimilarAgent << ")" << endl;
00955     }
00956   }
00957 
00958   //if(timeElapsed_ == 2461 && newAgentPeriod == 57)
00959   //    cout << "BEST SIMILAR AGENT: " << bestSimilarAgent << endl;
00960 
00961   return bestSimilarAgent;
00962 }
00963 
00964 /*
00965 //get similar existing agent with best score
00966 //[MAYBE CHANGE THIS TO (1/PERIODDIFF)*SCORE]
00967 mrs_natural
00968 BeatReferee::getBestSimilarAgent2(mrs_natural newAgentPeriod, mrs_natural newAgentInitPhase)
00969 {
00970     mrs_natural nrSimilar = 3; //nr of considered most simlar agents
00971     mrs_real bestSimilarScore = NA;
00972     mrs_natural bestSimilarAgent = -1;
00973     mrs_natural period;
00974     mrs_natural minPerDiff = 1000; //just a big number
00975     mrs_natural mostSimilarAgent = -1;
00976     mrs_realvec periodDiffs(nrAgents_);
00977 
00978     //save all period differences with each agent
00979     for(int a = 0; a < nrAgents_; a++)
00980     {
00981         period = (mrs_natural) lastPeriods_(a);
00982         periodDiffs(a) = abs(newAgentPeriod - period);
00983     }
00984 
00985     //cout << "NewAgent!" << endl;
00986 
00987     //sort periodDiffs realvec
00988     mrs_realvec periodDiffsSorted = periodDiffs;
00989     periodDiffsSorted.sort();
00990     mrs_natural maxPeriodDiff = (mrs_natural) periodDiffsSorted(nrSimilar);
00991 
00992     //check nrSimilar most similar agents
00993     for(int a = 0; a < nrAgents_; a++)
00994     {
00995         //cout << "Diff " << a << ": " << periodDiffsSorted(a) << "; UnSort: " << periodDiffs(a) << "; Score: " << score_(a) << endl;
00996         if((mrs_natural) periodDiffs(a) <= maxPeriodDiff) //only consider nrSimilar most similar agents
00997         {
00998             //check who's best
00999             if(score_(a) > bestSimilarScore)
01000             {
01001                 bestSimilarScore = score_(a);
01002                 bestSimilarAgent = a;
01003 
01004                 //cout << "BestSimilar: " << bestSimilarAgent << "; Score: " << bestSimilarScore << endl;
01005             }
01006         }
01007     }
01008 
01009     return bestSimilarAgent;
01010 }
01011 */
01012 
01013 //Routine for backtracing the first beat of the first created agents (for backtrace mode)
01014 mrs_natural
01015 BeatReferee::calcFirstBacktracedBeat(mrs_natural initPeriod, mrs_natural initPhase)
01016 {
01017   mrs_natural count = - (mrs_natural) ((initPhase / (mrs_real)initPeriod)-MINIMUMREAL);
01018   mrs_natural firstBeat = (initPhase + initPeriod * count);
01019 
01020   //cout << "Period: " << initPeriod << "; Phase: " << initPhase << "; firstBeat: " << firstBeat << endl;
01021   return firstBeat;
01022 }
01023 
01024 //Routine for calculating the first beat time of the first created agents (after induction):
01025 //(for continuous signal - no backtracing (induction window offset -> first beat must occur after the induction stage)):
01026 /*
01027 mrs_natural
01028 BeatReferee::calcFirstBeat(mrs_natural initPeriod, mrs_natural initPhase)
01029 {
01030     mrs_natural count = (mrs_natural) ceil((inductionTime_ - initPhase) /  (mrs_real)initPeriod);
01031     mrs_natural firstBeat = (initPhase + initPeriod * count);
01032 
01033     //Due to the compensation bellow we must grant that nextBeat is bigger than inductionTime_
01034     //If it is equal than we must postpone the nextBeat to a period after
01035     if(firstBeat == inductionTime_)
01036     {
01037         firstBeat += initPeriod;
01038     }
01039 
01040     //cout << "initPeriod:" << initPeriod << "; initPhase:" << initPhase << "; firstBeat:" << firstBeat << endl;
01041 
01042     return firstBeat;
01043 }
01044 */
01045 
01046 mrs_natural
01047 BeatReferee::existEqualBetterAgents(mrs_natural agentIndex, mrs_natural agentPeriod, mrs_natural agentPhase, mrs_real newAgentScore)
01048 {
01049   //cout << timeElapsed_ << ": isEqualAgents? period: " << agentPeriod  << "; phase: " << agentPhase << endl;
01050 
01051   mrs_natural firstEqualBetterAgent = -1;
01052   mrs_realvec equalAgents = getEqualAgents(agentIndex, agentPeriod, agentPhase);
01053 
01054   for(mrs_natural a = 0; a < nrAgents_; a++)
01055   {
01056     if((mrs_natural) equalAgents(a) == 1)
01057     {
01058       if(score_(a) >= newAgentScore)
01059       {
01060         firstEqualBetterAgent = a;
01061         break;
01062       }
01063     }
01064   }
01065 
01066   return firstEqualBetterAgent;
01067 }
01068 
01069 //return -1 if no existing equal agents or index of first equal agent
01070 mrs_natural
01071 BeatReferee::existEqualAgents(mrs_natural agentIndex, mrs_natural agentPeriod, mrs_natural agentPhase)
01072 {
01073   //cout << timeElapsed_ << ": isEqualAgents? period: " << agentPeriod  << "; phase: " << agentPhase << endl;
01074 
01075   mrs_natural firstEqualAgent = -1;
01076   mrs_realvec equalAgents = getEqualAgents(agentIndex, agentPeriod, agentPhase);
01077 
01078   for(mrs_natural a = 0; a < nrAgents_; a++)
01079   {
01080     if((mrs_natural) equalAgents(a) == 1)
01081     {
01082       firstEqualAgent = a;
01083       break;
01084     }
01085   }
01086 
01087   return firstEqualAgent;
01088 }
01089 
01090 //get a vector with all agents equal to agentIndex
01091 mrs_realvec
01092 BeatReferee::getEqualAgents(mrs_natural agentIndex, mrs_natural agentPeriod, mrs_natural agentPhase)
01093 {
01094   mrs_realvec equalAgents(nrAgents_);
01095 
01096   for(mrs_natural a = 0; a < nrAgents_; a++)
01097   {
01098     //if considered agent is not equal to the agent we want to compare
01099     //&& if the angent we want to compare is alive (i.e. exists) => then procede with comparison
01100     //(agenIndex == -1 => call after trigger induction)
01101     if(agentIndex == -1 || (agentIndex != a && !mutedAgentsTmp_(a)))
01102     {
01103       //2 agents are considered equal if their periods don't differ
01104       //more than 10ms (eq. 1frame) and their phases no more than 20ms (eq. 2frames)
01105       mrs_real phaseDiff = abs((agentPhase - lastPhases_(a)) / agentPeriod);
01106       mrs_natural periodDiff = abs(agentPeriod - (mrs_natural)lastPeriods_(a));
01107 
01108       //if(timeElapsed_ == 3949 || timeElapsed_ == 3968)
01109       //    cout << "Comparing " << agentIndex << " w/ per: " << agentPeriod << " & ph: " << agentPhase << " with Agent "
01110       //        << a << "; period: " << lastPeriods_(a) << "; phase: " << lastPhases_(a)
01111       //        << "; periodDiff: " << periodDiff << "(" << eqPeriod_ << "); phaseDiff:" << (phaseDiff - floor(phaseDiff))
01112       //        << "(" << ((mrs_real)eqPhase_/(mrs_real)agentPeriod) << ")" << endl;
01113 
01114       if((periodDiff <= eqPeriod_) && ((phaseDiff - floor(phaseDiff)) <= ((mrs_real)eqPhase_/(mrs_real)agentPeriod)
01115                                        || (phaseDiff - floor(phaseDiff)) >= (1-((mrs_real)eqPhase_/(mrs_real)agentPeriod))))
01116       {
01117         equalAgents(a) = 1; //set agent index as true if equal
01118 
01119         //if(timeElapsed_ == 3949)
01120         //  cout << "====================" << timeElapsed_ << ": Agent " << agentIndex << " has EQUAL: " << a << endl;
01121       }
01122     }
01123   }
01124 
01125   return equalAgents;
01126 }
01127 
01128 //checks and kill the worse from all existing equal agents to agentIndex
01129 void
01130 BeatReferee::checkAndKillEqualAgents(mrs_natural agentIndex)
01131 {
01132   //if(timeElapsed_ == 3949)
01133   //    cout << timeElapsed_ << ": REGULARLY CHECKING EQUAL AGENTS" << endl;
01134 
01135   mrs_realvec equalAgents = getEqualAgents(agentIndex, (mrs_natural) lastPeriods_(agentIndex), (mrs_natural) lastPhases_(agentIndex));
01136 
01137   for(mrs_natural a = 0; a < nrAgents_; a++)
01138   {
01139     if((mrs_natural)equalAgents(a) == 1) //if equal agent
01140     {
01141       //cout << "EQ!: " << agentIndex << "=" << a << endl;
01142       //From the two equal agents kill the one with lower score (if it isn't the current best agent)
01143       //(always kill the equal agents created at triggered inductions)
01144       ostringstream motif;
01145       if(score_(agentIndex) >= score_(a))
01146       {
01147         if(a != bestAgentIndex_)
01148         {
01149           motif << "EQ";
01150           killAgent(a, motif.str(), agentIndex);
01151 
01152           //cout << "1-KILL Agent " << a << " (" << score_(a) << ") EQUAL TO Agent " << agentIndex
01153           //    << " (" << score_(agentIndex) << ")" << endl;
01154         }
01155         else //if in trigger induction always kill just created agent (agentIndex), if equal to existing
01156         {
01157           motif << "EQ";
01158           killAgent(agentIndex, motif.str(), a);
01159           break; //in this case breaks because considered agent no longer exists.
01160 
01161           //cout << timeElapsed_ << ": 2-KILL Agent " << agentIndex << " (" << score_(agentIndex)
01162           //    << ") EQUAL TO Agent " << a << " (" << score_(a) << ")" << endl;
01163         }
01164       }
01165       else
01166       {
01167         if(agentIndex != bestAgentIndex_)
01168         {
01169           motif << "EQ";
01170           killAgent(agentIndex, motif.str(), a);
01171           break; //in this case breaks because considered agent no longer exists.
01172 
01173           //cout << "3-KILL Agent " << agentIndex << " (" << score_(agentIndex) << ") EQUAL TO Agent "
01174           //    << a << " (" << score_(a) << ")" << endl;
01175         }
01176         else
01177         {
01178           motif << "EQ";
01179           killAgent(a, motif.str(), agentIndex);
01180 
01181           //cout << "1-KILL Agent " << a << " (" << score_(a) << ") EQUAL TO Agent "
01182           //    << agentIndex << " (" << score_(agentIndex) << ")" << endl;
01183         }
01184       }
01185     }
01186   }
01187 }
01188 
01189 //returns true if agent created at trigered induction is killed due to be equal to existing agent
01190 /*
01191 mrs_bool
01192 BeatReferee::checkAndKillEqualAgents(mrs_natural agentIndex, mrs_bool triggerInductionCheck)
01193 {
01194     mrs_bool killedAgentIndex = false;
01195     for(mrs_natural a = 0; a < nrAgents_; a++)
01196     {
01197         //if considered agent is not equal to the agent we want to compare
01198         //&& if the angent we want to compare is alive (i.e. exists) => then procede with comparison
01199         if(agentIndex != a && !mutedAgentsTmp_(a))
01200         {
01201             //2 agents are considered equal if their periods don't differ
01202             //more than 10ms (eq. 1frame) and their phases no more than 20ms (eq. 2frames)
01203             if((abs(lastPeriods_(agentIndex) - lastPeriods_(a)) <= eqPeriod_) &&
01204                (abs((lastPhases_(agentIndex) - lastPhases_(a)) / lastPeriods_(agentIndex)) <= (eqPhase_/lastPeriods_(agentIndex))))
01205             {
01206                 //cout << "EQ!: " << agentIndex << "=" << a << endl;
01207                 //From the two equal agents kill the one with lower score (if it isn't the current best agent)
01208                 //(always kill the equal agents created at triggered inductions)
01209                 ostringstream motif;
01210                 if(score_(agentIndex) >= score_(a))
01211                 {
01212                     //if(a != bestAgentIndex_)
01213                     if(a != bestAgentIndex_ && !triggerInductionCheck)
01214                     {
01215                         motif << "EQ";
01216                         killAgent(a, motif.str(), agentIndex);
01217                         killedAgentIndex = false;
01218 
01219                         //cout << "1-KILL Agent " << a << " (" << score_(a) << ") EQUAL TO Agent " << agentIndex
01220                         //  << " (" << score_(agentIndex) << ")" << endl;
01221                     }
01222                     else //if in trigger induction always kill just created agent (agentIndex), if equal to existing
01223                     {
01224                         motif << "EQ";
01225                         killAgent(agentIndex, motif.str(), a);
01226                         killedAgentIndex = true;
01227                         break; //in this case breaks because considered agent no longer exists.
01228 
01229                         //if(triggerInductionCheck)
01230                         //  cout << timeElapsed_ << ": 2-KILL Agent " << agentIndex << " (" << score_(agentIndex)
01231                         //      << ") EQUAL TO Agent " << a << " (" << score_(a) << ")" << endl;
01232                     }
01233                 }
01234                 else
01235                 {
01236                     if(agentIndex != bestAgentIndex_)
01237                     {
01238                         motif << "EQ";
01239                         killAgent(agentIndex, motif.str(), a);
01240                         killedAgentIndex = true;
01241                         break; //in this case breaks because considered agent no longer exists.
01242 
01243                         //cout << "3-KILL Agent " << agentIndex << " (" << score_(agentIndex) << ") EQUAL TO Agent "
01244                             //  << a << " (" << score_(a) << ")" << endl;
01245                     }
01246                     else
01247                     {
01248                         motif << "EQ";
01249                         killAgent(a, motif.str(), agentIndex);
01250                         killedAgentIndex = false;
01251 
01252                         //cout << "1-KILL Agent " << a << " (" << score_(a) << ") EQUAL TO Agent "
01253                             //  << agentIndex << " (" << score_(agentIndex) << ")" << endl;
01254                     }
01255                 }
01256             }
01257         }
01258     }
01259     return killedAgentIndex;
01260 }
01261 */
01262 
01263 mrs_natural
01264 BeatReferee::getFirstAliveAgent()
01265 {
01266   mrs_natural firstAlive = 0;
01267   for(mrs_natural a = 0; a < nrAgents_; a++)
01268   {
01269     if(!mutedAgentsTmp_(a))
01270     {
01271       firstAlive = a;
01272       break;
01273     }
01274   }
01275   return firstAlive;
01276 }
01277 
01278 //Get the current worst agent of the pool:
01279 mrs_natural
01280 BeatReferee::getWorstAgent(mrs_natural callAgent)
01281 {
01282   //By default lowest score = score from first agent
01283   //mrs_natural firstAlive= getFirstAliveAgent();
01284   //mrs_real lowestScore = score_(firstAlive);
01285 
01286   mrs_real lowestScore = MAXREAL;
01287   mrs_natural lowestIndex = 0;
01288 
01289   //if(timeElapsed_ == 3100)
01290   //    cout << "Getting Worst Agent - FIRST: " << lowestIndex << "; sc: " << lowestScore << "; mutedAgentsTmp: " << mutedAgentsTmp_(lowestIndex);
01291 
01292   for(mrs_natural a = lowestIndex; a < nrAgents_; a++)
01293   {
01294     //never kill bestAgentBeforeTrigger && verify that agent really exists and it's not the call agent
01295     if(a != bestAgentBeforeTrigger_ && !mutedAgentsTmp_(a) && a != callAgent && score_(a) < lowestScore)
01296     {
01297       lowestScore = score_(a);
01298       lowestIndex = a;
01299 
01300       //if(timeElapsed_ == 876)
01301       //    cout << "; Actual: " << lowestIndex << "; sc: " << lowestScore << "; Agent: " << a
01302       //        << "; bestAgentBeforeTrigger: " << bestAgentBeforeTrigger_ << endl;
01303     }
01304   }
01305 
01306   //if(timeElapsed_ == 3100)
01307   //    cout << endl;
01308 
01309   //return worst agent
01310   return lowestIndex;
01311 }
01312 
01313 mrs_realvec
01314 BeatReferee::calculateNewHypothesis(mrs_natural agentIndex, mrs_natural oldPeriod, mrs_natural prevBeat, mrs_natural error)
01315 {
01316   (void) agentIndex; // [!] what was this supposed to do?
01317   mrs_natural newPeriod;
01318   mrs_natural nextBeat;
01319   /*
01320   //To avoid too small or big periods, or too distanced from agent's initial period:
01321   if(newPeriod > minPeriod_ && newPeriod < maxPeriod_ &&
01322   fabs(initPeriod_(agentIndex) - newPeriod) < 0.1*initPeriod_(agentIndex))
01323   */
01324 
01325   newPeriod =  oldPeriod + ((mrs_natural) ((error*corFactor_) + ((error/abs(error)) * 0.5)));
01326 
01327   //To avoid too small or big periods
01328   if(newPeriod < minPeriod_ || newPeriod > maxPeriod_)
01329     newPeriod = oldPeriod;
01330 
01331   nextBeat = prevBeat + newPeriod + ((mrs_natural) ((error*corFactor_) + ((error/abs(error))) * 0.5));
01332 
01333 
01334   /*
01335     newPeriod = oldPeriod + error;
01336     if(newPeriod < minPeriod_ || newPeriod > maxPeriod_)
01337     newPeriod = oldPeriod;
01338     nextBeat = prevBeat + newPeriod;
01339   */
01340   //if(agentIndex == bestAgentIndex_)
01341   //    cout << "Agent" << agentIndex << ": Error:" << error << "; AgentPeriod:" << newPeriod << endl;
01342 
01343   //cout << "Agent " << agentIndex << "; oldPeriod: " << oldPeriod << "; NewPeriod: " << newPeriod <<
01344   //    "; NextBeat: "  << nextBeat << "; Error: " << error << "; Correction: " << correction << endl;
01345   //cout << "Agent " << agentIndex << " History: " << historyCount_(agentIndex) << endl;
01346 
01347   mrs_realvec newHypothesis(2);
01348   newHypothesis(0) = newPeriod;
01349   newHypothesis(1) = nextBeat;
01350 
01351   return newHypothesis;
01352 }
01353 
01354 mrs_natural
01355 BeatReferee::calcNewPeriod(mrs_natural oldPeriod, mrs_natural error, mrs_real beta)
01356 {
01357   //cout << "error: " << error << "; beta: " << beta << endl;
01358   mrs_natural newPeriod = oldPeriod + ((mrs_natural) ((error * beta) + (error/abs(error)) * 0.5));
01359 
01360   if(newPeriod < minPeriod_ || newPeriod > maxPeriod_)
01361     newPeriod = oldPeriod;
01362 
01363   //cout << "oldPeriod: " << oldPeriod << "; newPeriod: " << newPeriod << "; Error: " << error <<
01364   //    "; Beta: " << beta << "; maxPer: " << maxPeriod_ << "; minPer: " << minPeriod_ << endl;
01365 
01366   return newPeriod;
01367 }
01368 
01369 mrs_realvec
01370 BeatReferee::calcChildrenHypothesis(mrs_natural oldPeriod, mrs_natural prevBeat, mrs_natural error)
01371 {
01372   mrs_natural nextBeat1 = -100, nextBeat2 = -100, nextBeat3 = -100;
01373   mrs_natural newPeriod1 = -100, newPeriod2 = -100, newPeriod3 = -100;
01374   mrs_realvec newHypotheses(3,3); //for 3 children
01375 
01376   //cout << "ChildFactor1:" << child1Factor_ << "; ChildFactor2:" << child2Factor_ << "; ChildFactor3:" << child3Factor_ << endl;
01377 
01378   //(if childiFactor = -1.0 then only phase adjusted)
01379   if(child1Factor_ == 2.0)
01380   {
01381     newPeriod1 = oldPeriod;
01382     nextBeat1 = prevBeat + newPeriod1 + error;
01383   }
01384   else
01385   {
01386     newPeriod1 = calcNewPeriod(oldPeriod, error, child1Factor_);
01387     //if newPeriod surprasses bpm interval then do only full phase adjustment
01388     //if(newPeriod < minPeriod_ || newPeriod > maxPeriod_)
01389     //  nextBeat = prevBeat + oldPeriod + error;
01390     //else
01391     nextBeat1 = prevBeat + newPeriod1 + ((mrs_natural) ((error*child1Factor_) + ((error/abs(error))) * 0.5));
01392     //nextBeat = prevBeat + newPeriod;
01393   }
01394   newHypotheses(0,0) = newPeriod1;
01395   newHypotheses(0,1) = nextBeat1;
01396   newHypotheses(0,2) = 1;
01397 
01398   if(child2Factor_ == 2.0)
01399   {
01400     newPeriod2 = oldPeriod;
01401     nextBeat2 = prevBeat + newPeriod2 + error;
01402   }
01403   else
01404   {
01405     /*
01406       newPeriod = oldPeriod + error;
01407       if(newPeriod < minPeriod_ || newPeriod > maxPeriod_)
01408       newPeriod = oldPeriod;
01409       nextBeat = prevBeat + newPeriod;
01410     */
01411 
01412     newPeriod2 = calcNewPeriod(oldPeriod, error, child2Factor_);
01413     //if newPeriod surprasses bpm interval then do only full phase adjustment
01414     //if(newPeriod < minPeriod_ || newPeriod > maxPeriod_)
01415     //  nextBeat = prevBeat + oldPeriod + error;
01416     //else
01417     nextBeat2 = prevBeat + newPeriod2 + ((mrs_natural) ((error*child2Factor_) + ((error/abs(error))) * 0.5));
01418   }
01419   newHypotheses(1,0) = newPeriod2;
01420   newHypotheses(1,1) = nextBeat2;
01421 
01422   //To avoid creating equal agents:
01423   if(abs(newPeriod2 - newPeriod1) <= eqPeriod_ && abs(nextBeat2 - nextBeat1) <= eqPhase_)
01424     newHypotheses(1,2) = 0;
01425   else newHypotheses(1,2) = 1;
01426 
01427   if(child3Factor_ == 2.0)
01428   {
01429     newPeriod3 = oldPeriod;
01430     nextBeat3 = prevBeat + newPeriod3 + error;
01431   }
01432   else
01433   {
01434     newPeriod3 = calcNewPeriod(oldPeriod, error, child3Factor_);
01435     //if newPeriod surprasses bpm interval then do only full phase adjustment
01436     //if(newPeriod < minPeriod_ || newPeriod > maxPeriod_)
01437     //  nextBeat = prevBeat + oldPeriod + error;
01438     //else
01439     nextBeat3 = prevBeat + newPeriod3 + ((mrs_natural) ((error*child3Factor_) + ((error/abs(error))) * 0.5));
01440   }
01441   newHypotheses(2,0) = newPeriod3;
01442   newHypotheses(2,1) = nextBeat3;
01443 
01444   //To avoid creating equal agents:
01445   if((abs(newPeriod3 - newPeriod1) <= eqPeriod_ && abs(nextBeat3 - nextBeat1) <= eqPhase_)
01446       || (abs(newPeriod3 - newPeriod2) <= eqPeriod_ && abs(nextBeat3 - nextBeat2) <= eqPhase_))
01447     newHypotheses(2,2) = 0;
01448   else newHypotheses(2,2) = 1;
01449 
01450   //cout << "oldPeriod: " << oldPeriod << "; newPeriod: " << newPeriod << "; Error: " << error <<
01451   //    "; prevBeat: " << prevBeat << "; nextBeat: " << nextBeat << endl;
01452 
01453   return newHypotheses;
01454 }
01455 
01456 //Routine for creating new agents from existent one
01457 void
01458 BeatReferee::createChildren(mrs_natural agentIndex, mrs_natural oldPeriod, mrs_natural prevBeat, mrs_natural error,
01459                             mrs_real agentScore, mrs_real beatCount)
01460 {
01461   //mrs_real deltaS = fabs(childrenScoreFactor_ * agentScore);
01462   //mrs_real newScore = agentScore - deltaS;
01463 
01464   //if(timeElapsed_ == 687)
01465   //    cout << "CREATE AGENTS FROM: " << agentIndex << "; error: " << error << "; per: " << oldPeriod << "; ph: " << prevBeat << endl;
01466 
01467   mrs_real newScore;
01468   if(agentScore >= 0.0)
01469     newScore = agentScore * childrenScoreFactor_;
01470   else
01471     newScore = agentScore / childrenScoreFactor_;
01472 
01473   mrs_realvec newHypotheses = calcChildrenHypothesis(oldPeriod, prevBeat, error);
01474 
01475   //mrs_realvec newHypothesis = calculateNewHypothesis(agentIndex, oldPeriod, prevBeat, error);
01476   //setNewHypothesis(agentIndex, (mrs_natural) newHypothesis(0), (mrs_natural) newHypothesis(1));
01477 
01478   if(child1Factor_ != -1.0)
01479     createNewAgent((mrs_natural) newHypotheses(0,0), (mrs_natural) newHypotheses(0,1), newScore, beatCount, agentIndex);
01480   if(child2Factor_ != -1.0 && newHypotheses(1,2) == 1)
01481     createNewAgent((mrs_natural) newHypotheses(1,0), (mrs_natural) newHypotheses(1,1), newScore, beatCount, agentIndex);
01482   if(child3Factor_ != -1.0 && newHypotheses(2,2) == 1)
01483     createNewAgent((mrs_natural) newHypotheses(2,0), (mrs_natural) newHypotheses(2,1),  newScore, beatCount, agentIndex);
01484 
01485   //Display Created BeatAgent:
01486   //if(timeElapsed_ == 2046)
01487   //    cout << "NEW AGENT(" << timeElapsed_ << "-" << ((timeElapsed_ * hopSize_) - (hopSize_/2)) / srcFs_ << ") (reqBy:" << agentIndex <<
01488   //        ") -> PrevBeat:" << prevBeat << " Period:" << oldPeriod << " NextBeat1:" << newHypotheses(0,1) << " NewPeriod1:" <<
01489   //        newHypotheses(0,0) << " NextBeat2:" << newHypotheses(1,1) << " NewPeriod2:" << newHypotheses(1,0) <<
01490   //        " NextBeat3:" << newHypotheses(2,1) << " NewPeriod3:" << newHypotheses(2,0) <<
01491   //        " Error:" << error << " Score:" << newScore << endl;
01492 }
01493 
01494 //Routine for updating existent agent hypothesis
01495 //(Used when beat of agent is found inside its inner tolerance with some error):
01496 void
01497 BeatReferee::updateAgentHypothesis(mrs_natural agentIndex, mrs_natural oldPeriod,
01498                                    mrs_natural prevBeat, mrs_natural error)
01499 {
01500   //if agent effectively exists (for safechecking)
01501   if(!mutedAgentsTmp_(agentIndex))
01502   {
01503     mrs_realvec newHypothesis = calculateNewHypothesis(agentIndex, oldPeriod, prevBeat, error);
01504     setNewHypothesis(agentIndex, (mrs_natural) newHypothesis(0), (mrs_natural) newHypothesis(1));
01505   }
01506 
01507   //Display Updated BeatAgent:
01508   //cout << "UPDATING AGENT" << agentIndex <<" (" << timeElapsed_ << ")" << " -> oldPeriod: " << oldPeriod <<
01509   //    " newPeriod: " << newHypothesis(0) << " prevBeat: " << prevBeat << " nextBeat: " << newHypothesis(1) <<
01510   //    " Error: " << error << endl;
01511 }
01512 
01513 //Define new Hypothesis in indexed AgentControl Matrix:
01514 void
01515 BeatReferee::setNewHypothesis(mrs_natural agentIndex, mrs_natural newPeriod, mrs_natural nextBeat)
01516 {
01517   agentControl_(agentIndex, 0) = 1.0; //is New or Updated
01518   agentControl_(agentIndex, 1) = newPeriod;
01519   agentControl_(agentIndex, 2) = nextBeat;
01520   agentControl_(agentIndex, 3) = timeElapsed_;
01521 
01522   updControl(ctrl_agentControl_, agentControl_);
01523 
01524   lastPeriods_(agentIndex) = newPeriod;
01525 }
01526 
01527 //grantPoolSpace given the nr of elements in the newAgentsScore realvec
01528 void
01529 BeatReferee::grantPoolSpace2(mrs_natural callAgent, mrs_natural nrRequired, mrs_realvec newAgentsScore)
01530 
01531 {
01532 
01533   //if(timeElapsed_ == 3100)
01534   //{
01535   //    for(int i = 0; i < nrRequired; i++)
01536   //        cout << "NEW " << i << "-> Agents Score: " << newAgentsScore(i) << "; elems: " << nrRequired << endl;
01537   //}
01538 
01539   mrs_natural nrAvailable = 0;
01540   for(int a = 0; a < mutedAgentsTmp_.getSize(); a++)
01541   {
01542     if(mutedAgentsTmp_(a))
01543       nrAvailable++;
01544   }
01545 
01546   //if(timeElapsed_ == 3100)
01547   //    cout << "t: " << timeElapsed_ << ": AVAILABLE POOLSPACE: " << nrAvailable << "; required: " << nrRequired << endl;
01548 
01549   nrRequired = nrRequired - nrAvailable; //updated nr of required spaces given the ammount of free ones
01550 
01551   //if there are no free agents -> remove worsts!
01552   while(nrRequired > 0)
01553   {
01554     mrs_natural agentInd2Kill = getWorstAgent(callAgent);
01555 
01556     //if(timeElapsed_ == 3100)
01557     //  cout << "t: " << timeElapsed_ << ": KillWorstAgent: " << agentInd2Kill << "; newAgentSc: " << newAgentsScore(nrRequired-1) << "; worstScore: " << score_(agentInd2Kill) << endl;
01558 
01559     //only kills current worst agent in the pool if its score is smaller than the new agent score
01560     if(score_(agentInd2Kill) <= newAgentsScore(nrRequired-1))
01561       killAgent(agentInd2Kill, "POOL", callAgent);
01562 
01563     nrRequired--;
01564   }
01565 }
01566 
01567 void
01568 BeatReferee::grantPoolSpace(mrs_natural callAgent, mrs_real newAgentScore)
01569 {
01570   mrs_bool isAvailable = false;
01571 
01572   for(int a = 0; a < mutedAgentsTmp_.getSize(); a++)
01573   {
01574     //if(timeElapsed_ == 876)
01575     //      cout << "t: " << timeElapsed_ << ": CHECKING POOLSPACE @: " << a << "; newAgentSc: " << newAgentScore << endl;
01576 
01577     if(mutedAgentsTmp_(a))
01578     {
01579       //if(timeElapsed_ == 876)
01580       //    cout << "t: " << timeElapsed_ << ": FREE POOLSPACE @: " << a << "; newAgentSc: " << newAgentScore << endl;
01581 
01582       isAvailable = true;
01583       break;
01584     }
01585   }
01586 
01587   //if there are no free agents -> remove worst!
01588   if(!isAvailable)
01589   {
01590     mrs_natural agentInd2Kill = getWorstAgent(callAgent);
01591 
01592     //if(timeElapsed_ == 876)
01593     //  cout << "t: " << timeElapsed_ << ": KillWorstAgent: " << agentInd2Kill << "; newAgentSc: " << newAgentScore << "; worstScore: " << score_(agentInd2Kill) << endl;
01594 
01595     //only kills current worst agent in the pool if its score is smaller than the new agent score
01596     if(score_(agentInd2Kill) <= newAgentScore)
01597       killAgent(agentInd2Kill, "POOL", callAgent);
01598     //else if(logFile_)
01599     //  debugAddEvent("NO_POOL", callAgent, -1, -1, newAgentScore, score_(agentInd2Kill), agentInd2Kill);
01600   }
01601 }
01602 
01603 //routine for checking and recovering beat at transition bewteen father and son (for non-causal mode)
01604 void
01605 BeatReferee::handleAgentsTansition(mrs_natural agent)
01606 {
01607   /*if(agent == 8 && timeElapsed_ >= 900)
01608   {
01609     cout << timeElapsed_ << "-> FLAG- ";
01610     for(int j = 0; j < considerFatherTransitionBeat_.getCols(); j++)
01611         cout << j << ": " << considerFatherTransitionBeat_(agent, j) << "; ";
01612 
01613     cout << endl;
01614   }*/
01615 
01616   mrs_natural fatherAgent, sonAgent;
01617   if(considerAgentTransitionBeat_(agent) == -1) //unconsider first beat from agent
01618   {
01619     sonAgent = agent;
01620 
01621     //if(sonAgent == 19 && timeElapsed_ >= 2461)
01622     //if(timeElapsed_ == 3946)
01623     //{
01624     //  cout << timeElapsed_ << ": TRANS_REM from " << sonAgent << "-> BEAT " << (beatCounter_(sonAgent)) << ": "
01625     //      << agentsHistory_(sonAgent, (mrs_natural) (beatCounter_(sonAgent))) << "("
01626     //      << (((agentsHistory_(sonAgent, (mrs_natural) (beatCounter_(sonAgent))) * hopSize_) - frames2SecsAdjustment_) / srcFs_)
01627     //      << ") by: " << agentsFamilyHist_(sonAgent, (mrs_natural) (beatCounter_(sonAgent))) << endl;
01628     //  cout << timeElapsed_ << ": BEAT COUNT " << sonAgent << " = " << beatCounter_(sonAgent) << endl;
01629     //}
01630 
01631     agentsHistory_(sonAgent, (mrs_natural) beatCounter_(sonAgent)) = -1;
01632     agentsFamilyHist_(agent, (mrs_natural) beatCounter_(sonAgent)) = -1;
01633 
01634     beatCounter_(sonAgent)--; //decrement one count because it is incremented just after
01635 
01636     considerAgentTransitionBeat_(agent) = NA; //clean flag
01637   }
01638 
01639   fatherAgent = agent;
01640   //process all array to account for every sons' request
01641   for(int j = 0; j < considerFatherTransitionBeat_.getCols(); j++)
01642   {
01643     if(considerFatherTransitionBeat_(agent, j) >= 0) //consider all valid positions in father's flag array
01644     {
01645       sonAgent = (mrs_natural) considerFatherTransitionBeat_(agent, j);
01646 
01647       agentsHistory_(sonAgent, (mrs_natural) beatCounter_(sonAgent))
01648       = agentsHistory_(fatherAgent, (mrs_natural) beatCounter_(fatherAgent));
01649       agentsFamilyHist_(sonAgent, (mrs_natural) beatCounter_(sonAgent))
01650       = agentsFamilyHist_(fatherAgent, (mrs_natural) beatCounter_(fatherAgent));
01651 
01652       //if(sonAgent == 27 && fatherAgent == 8)
01653       //if(timeElapsed_ == 3946)
01654       //{
01655       //    cout << timeElapsed_ << ": TRANS_ADD to "<< sonAgent << "-> BEAT " << (beatCounter_(sonAgent)) << ": "
01656       //        << agentsHistory_(sonAgent, (mrs_natural) (beatCounter_(sonAgent))) << "("
01657       //        << (((agentsHistory_(sonAgent, (mrs_natural) (beatCounter_(sonAgent))) * hopSize_) - frames2SecsAdjustment_) / srcFs_)
01658       //        << ") by: " << agentsFamilyHist_(sonAgent, (mrs_natural) (beatCounter_(sonAgent))) << endl;
01659       //    cout << timeElapsed_ << ": BEAT COUNT " << sonAgent << " = " << beatCounter_(sonAgent)+1 << endl;
01660       //}
01661 
01662       beatCounter_(sonAgent)++;
01663 
01664       considerFatherTransitionBeat_(agent, j) = NA; //clean flag
01665     }
01666   }
01667 }
01668 //clean agent's transition flag and its call in its father's flag
01669 void
01670 BeatReferee::cleanAgentAndFatherTransitionFlags(mrs_natural agentIndex)
01671 {
01672   //if(agentIndex == 17 && timeElapsed_ == 1416)
01673   //    cout << "Agent: " << agentIndex << "; agentFlag: " << considerAgentTransitionBeat_(agentIndex) << endl;
01674 
01675   if(considerAgentTransitionBeat_(agentIndex) >= 0) //if it already has an assigned father whom requested its flag
01676   {
01677     mrs_natural fatherRequested = (mrs_natural) considerAgentTransitionBeat_(agentIndex);
01678 
01679     //if(agentIndex == 17 && timeElapsed_ == 1416)
01680     //  cout << timeElapsed_ << ": Agent: " << agentIndex << " CHECKING fatherAgentFLAG: " << fatherRequested << endl;
01681 
01682     //look in its father array for cleaning
01683     for(int j = 0; j < considerFatherTransitionBeat_.getCols(); j++)
01684     {
01685       if(considerFatherTransitionBeat_(fatherRequested, j) == agentIndex)
01686       {
01687         //if(timeElapsed_ == 3946)
01688         //if(agentIndex == 17 && timeElapsed_ == 1416)
01689         //  cout << timeElapsed_ << ": CLEANED agent " << agentIndex << "; from FATHER: " << fatherRequested << endl;
01690 
01691         considerFatherTransitionBeat_(fatherRequested, j) = NA;
01692         break;
01693       }
01694     }
01695   }
01696   considerAgentTransitionBeat_(agentIndex) = NA;
01697 }
01698 
01699 
01700 //Generic routine for creating new agents given their hypotheses:
01701 mrs_natural
01702 BeatReferee::createNewAgent(mrs_natural newPeriod, mrs_natural firstBeat,
01703                             mrs_real newScore, mrs_real beatCount, mrs_natural fatherAgent)
01704 {
01705   //if father agent died in the same timestep as it requests a son creation then this request is unconsidered
01706   if(fatherAgent >= 0 && mutedAgentsTmp_(fatherAgent) == 1.0)
01707   {
01708     if(logFile_)
01709       debugAddEvent("CREATE_REF_KF", -1, newPeriod, firstBeat, newScore, bestScore_, fatherAgent);
01710     return -1;
01711   }
01712   //or if the score of the new agent is obsolete the newAgent request is also unconsidered
01713   else if (timeElapsed_ > timeBeforeKilling_ && newScore < bestScore_ && fabs(bestScore_-newScore) > 0.1
01714            && fabs(bestScore_ - newScore) > fabs(bestScore_ * obsoleteFactor_))
01715   {
01716     if(logFile_)
01717       debugAddEvent("CREATE_REF_SCORE", -1, newPeriod, firstBeat, newScore, bestScore_, fatherAgent);
01718     return -1;
01719   }
01720 
01721   //if(timeElapsed_ == 876)
01722   //    cout << " CREATED: Agent at: " << timeElapsed_ << "; Pe: " << newPeriod << "; Ph: " << firstBeat << endl;
01723 
01724   //Grant available space in the pool, by removing the worst agent, if needed
01725   grantPoolSpace(fatherAgent, newScore);
01726 
01727   mrs_natural returnCreatedAgent = -1;
01728   for(int a = 0; a < mutedAgentsTmp_.getSize(); a++)
01729   {
01730     //Look for first disabled agent (in temporary vector):
01731     if(mutedAgentsTmp_(a))
01732     {
01733       //Activate new agent
01734       //mutedAgents_(a) = 0.0;
01735       //updControl(ctrl_mutedAgents_, mutedAgents_);
01736 
01737       mutedAgentsTmp_(a) = 0.0;
01738       updControl(ctrl_mutedAgents_, mutedAgentsTmp_);
01739 
01740       //Diplay Created BeatAgent:
01741       //if(timeElapsed_ == 876)
01742       //    cout << " CREATED: Agent " << a << " at: " << timeElapsed_ << "; Pe: " << newPeriod << "; Ph: " << firstBeat << endl;
01743 
01744       //Defines new hypothesis for this agent:
01745       setNewHypothesis(a, newPeriod, firstBeat);
01746 
01747       //Update score:
01748       score_(a) =  newScore;
01749 
01750       //if(timeElapsed_ == 3100)
01751       //    cout << "t: " << timeElapsed_ << "; CREATED AGENT: " << a << "; beatCountBef: " << beatCounter_(a) << "; bc4Bef: " << beatCounter_(4);
01752 
01753       //beatCounter of this agent equals beatCounter of its father
01754       beatCounter_(a) = beatCount;
01755 
01756       //if(timeElapsed_ > 3707)
01757       //    cout <<  "; beatCountAfter: " << beatCounter_(a) << "; bc4After: " << beatCounter_(4) << endl;
01758 
01759       //Update Agents' Periods and Phases (for equality checking)
01760       lastPeriods_(a) = newPeriod; //(Periods in frames)
01761       //lastPhases_(a) = firstBeat; //(Phases in frames
01762       lastPhases_(a) = (firstBeat - newPeriod); //(assuem last phase equal to first beat - agentPeriod)
01763 
01764       initPeriod_(a) = newPeriod; //save agent's initial IBI
01765       missedBeatsCount_(a) = 0.0; //reset missed beats counter
01766 
01767       //statsPeriods_(a, timeElapsed_) = newPeriod;
01768       //statsPhases_(a, timeElapsed_) = firstBeat;
01769 
01770       //statsAgentsLifeCycle_(a, timeElapsed_) = 1.0;
01771 
01772       //force timing update when agent is created
01773       //(don't know why when a new agent is created its time, in agentControl, keeps
01774       //the time of the previous tick)
01775       agentControl_(a, 3) = timeElapsed_+1;
01776       updControl(ctrl_agentControl_, agentControl_);
01777 
01778       returnCreatedAgent = a;
01779 
01780       agentsJustCreated_(a) = 1.0;
01781 
01782       if(logFile_)
01783         debugAddEvent("CREATE", a, newPeriod, firstBeat, score_(a), bestScore_, fatherAgent);
01784 
01785       //in nonCausalAnalysis keep agents history till the end of the analysis
01786       if(nonCausal_)
01787       {
01788         //if(timeElapsed_ == 1382 || timeElapsed_ == 1441)
01789         //  cout << "============t: " << timeElapsed_ << " - created new agent: " << a << " from: " << fatherAgent << endl;
01790 
01791         if(fatherAgent >= 0)
01792         {
01793           mrs_natural lastFlagInd = 0;
01794 
01795           //if(timeElapsed_ == 3946)
01796           //if(a == 9 && fatherAgent == 8 && timeElapsed_ == 3946)
01797           //    cout << "firstBeat: " << firstBeat << "; fatherAgent: " << fatherAgent << "; agent: "
01798           //        << a << "; lastFPh: " << lastPhases_(fatherAgent) << "; FPer: " << lastPeriods_(fatherAgent)
01799           //        << "; transFlag: " << considerFatherTransitionBeat_(a, 0) << "; agentTrans: "
01800           //        << considerAgentTransitionBeat_(a) << endl;
01801 
01802           //clean agent's transition flag and its call in its father's flag
01803           //(just to be sure since it could be updated within the same frame)
01804           cleanAgentAndFatherTransitionFlags(a);
01805 
01806           //check beat at transition between father and son:
01807           //if(((firstBeat - lastPhases_(fatherAgent)) / lastPeriods_(fatherAgent)) < -1.6)
01808           //if((abs(firstBeat - lastPhases_(fatherAgent)) / lastPeriods_(fatherAgent)) < 0.6)
01809           if((abs(firstBeat - lastPhases_(fatherAgent)) / lastPeriods_(fatherAgent)) < beatTransitionTol_)
01810           {
01811             //last beat from father and first beat from son are too close (in comparison to last father's ibi)
01812             //unconsider less than 60% difference => unconsider first son's beat
01813             //(set considerTransitionBeatFlag to -1)
01814             considerAgentTransitionBeat_(a) = -1;
01815 
01816             if(logFile_)
01817               debugAddEvent("TRANSITION_REM", a, (mrs_natural) lastPeriods_(a),
01818                             (mrs_natural) (firstBeat), score_(a), bestScore_, fatherAgent);
01819 
01820 
01821             //cout << timeElapsed_ << ": REQUEST UNCONSIDER: " << a << "; firstBeat: " << firstBeat << "; lastPhFather: " << lastPhases_(fatherAgent)
01822             //  << " (" << (abs(firstBeat - lastPhases_(fatherAgent))) << "); lastPerFather: " << lastPeriods_(fatherAgent)
01823             //  << "(" << (0.7 * lastPeriods_(fatherAgent)) << "); Flag: " << considerAgentTransitionBeat_(a) << endl;
01824           }
01825           //last beat from father and first beat from son are too far (in comparison to last father's ibi)
01826           //consider more than 60% difference => consider next father's beat as first son's beat
01827           //(set considerTransitionBeatFlag to agent's index onto his father's index)
01828           //if(((firstBeat - lastPhases_(fatherAgent)) / lastPeriods_(fatherAgent)) > 1.6)
01829           else if((abs(firstBeat - lastPhases_(fatherAgent)) / lastPeriods_(fatherAgent)) > (1+beatTransitionTol_))
01830           {
01831             //considerFatherTransitionBeat_(fatherAgent) = a;
01832             //retrieve first available position in the flag
01833             lastFlagInd = 0;
01834             for(int j = 0; j < considerFatherTransitionBeat_.getCols(); j++)
01835             {
01836               if(considerFatherTransitionBeat_(fatherAgent, j) < 0)
01837               {
01838                 //if(a == 27 && fatherAgent == 8 && timeElapsed_ == 933)
01839                 //  cout << timeElapsed_ << ": FREE FATHER " << fatherAgent << " w/ Flag @ ind: " << j << endl;
01840 
01841                 lastFlagInd = j;
01842                 break;
01843               }
01844             }
01845             considerFatherTransitionBeat_(fatherAgent, lastFlagInd) = a;
01846 
01847             considerAgentTransitionBeat_(a) = fatherAgent; //register son's call
01848 
01849             if(logFile_)
01850               debugAddEvent("TRANSITION_ADD", a, (mrs_natural) lastPeriods_(a),
01851                             (mrs_natural) (firstBeat+lastPeriods_(a)), score_(a), bestScore_, fatherAgent);
01852 
01853             //if(a == 27 && fatherAgent == 8 && timeElapsed_ == 933)
01854             //  cout << timeElapsed_ << ": REQUEST RECONSIDER: " << a << " from Father: " << fatherAgent << "; firstBeat: " << firstBeat
01855             //      << "; lastPhFather: " << lastPhases_(fatherAgent) << " (" << (abs(firstBeat - lastPhases_(fatherAgent)))
01856             //      << "); lastPerFather: " << lastPeriods_(fatherAgent) << "(" << (1.9 * lastPeriods_(fatherAgent))
01857             //      << "); FatherFlag: " << considerFatherTransitionBeat_(fatherAgent, lastFlagInd) << "; sonFlag: "
01858             //      << considerAgentTransitionBeat_(a) << endl;
01859           }
01860 
01861           //pass history (beats and family) of father agent to created one
01862           for(int i = 0; i < beatCount; i++)
01863           {
01864             agentsHistory_(a, i) = agentsHistory_(fatherAgent, i); //beats history
01865             agentsFamilyHist_(a, i) = agentsFamilyHist_(fatherAgent, i);
01866 
01867             //if((a == 1 && fatherAgent == 2 && timeElapsed_ == 1382) || (a == 0 && fatherAgent == 1 && timeElapsed_ == 1441))
01868             //if(a == 27 && fatherAgent == 8 && timeElapsed_ == 933)
01869             //if(timeElapsed_ == 3946)
01870             //{
01871             //  cout << timeElapsed_ << ": Agent " << a << " created by " << fatherAgent << "-> BEAT " << i << ": "
01872             //      << (agentsHistory_(a, i)) << " by: " << agentsFamilyHist_(a, i) << endl;
01873             //  cout << "t: " << timeElapsed_ << "-BEAT " << i << ": " << (((agentsHistory_(a, i) * hopSize_) - hopSize_/2) / srcFs_)
01874             //      << " by: " << agentsFamilyHist_(a, i) << endl;
01875             //  cout << "Diff btw " << a << " and Father " << fatherAgent << ": " << (abs(firstBeat - lastPhases_(fatherAgent)) / lastPeriods_(fatherAgent)) << endl;
01876             //}
01877           }
01878 
01879           //if((a == 1 && fatherAgent == 2 && timeElapsed_ == 1382) || (a == 0 && fatherAgent == 1 && timeElapsed_ == 1441))
01880           //if(timeElapsed_ == 3946)
01881           //if(a == 9 && fatherAgent == 8 && timeElapsed_ == 3946)
01882           //    cout << "2-BEAT " << beatCount << ": " << (((agentsHistory_(a, beatCount) * hopSize_) - hopSize_/2) / srcFs_)
01883           //        << " by: " << agentsFamilyHist_(a, beatCount) << "; TRANSFLAG: " << considerFatherTransitionBeat_(a, 0)
01884           //        << "; fatherTRANSFLAG: " << considerFatherTransitionBeat_(fatherAgent, lastFlagInd) << "; AgentFlag: "
01885           //        << considerAgentTransitionBeat_(a) << endl;
01886         }
01887       }
01888 
01889       break;
01890     }
01891   }
01892 
01893   return returnCreatedAgent;
01894 }
01895 
01896 //Routine for killing all agents -> reseting the system
01897 void
01898 BeatReferee::resetSystem(mrs_natural saveAgent)
01899 {
01900   //kill all agents
01901   for(int a = 0; a < mutedAgentsTmp_.getSize(); a++)
01902   {
01903     if(a != saveAgent) killAgent(a, "RESET");
01904   }
01905 
01906   //reset best score
01907   bestScore_ = NA; //To allow initial negative scores
01908 
01909   if(logFile_)
01910     debugAddEvent("RESET_SYSTEM", -1, -1, -1, -1, bestScore_, saveAgent);
01911 }
01912 
01913 //Generic routine for killing agents:
01914 void
01915 BeatReferee::killAgent(mrs_natural agentIndex, mrs_string motif, mrs_natural callAgent)
01916 {
01917   //Never kill a best agent or a best before trigger agent (for enforcing security) -> a best agent must live until being replaced by a better one
01918   //&& verify that agent effectively exists (for safechecking)
01919   if(strcmp(motif.c_str(), "RESET") == 0 || (agentIndex != bestAgentBeforeTrigger_ && agentIndex != bestAgentIndex_ && !mutedAgentsTmp_(agentIndex)))
01920   {
01921     //Diplay killed BeatAgent:
01922     //if(timeElapsed_ == 1416)
01923     //  cout << "KILLED AGENT " << agentIndex << " (" << motif << ") With Score: " << score_(agentIndex) << " / " << bestScore_ << endl;
01924 
01925     if(logFile_)
01926     {
01927       ostringstream killMotif;
01928       killMotif << "KILL_" << motif;
01929       debugAddEvent(killMotif.str(), agentIndex, (mrs_natural) lastPeriods_(agentIndex),
01930                     (mrs_natural) lastPhases_(agentIndex), score_(agentIndex), bestScore_, callAgent);
01931     }
01932 
01933     //mutedAgents_(agentIndex) = 1.0;
01934     //updControl(ctrl_mutedAgents_, mutedAgents_);
01935     mutedAgentsTmp_(agentIndex) = 1.0;
01936     updControl(ctrl_mutedAgents_, mutedAgentsTmp_);
01937 
01938     score_(agentIndex) = NA;
01939     beatCounter_(agentIndex) = 0.0;
01940 
01941     //statsAgentsLifeCycle_(agentIndex, timeElapsed_) = -1;
01942     lastPeriods_(agentIndex) = 0.0; //(Periods in frames)
01943     lastPhases_(agentIndex) = 0.0; //(Phases in frames)
01944 
01945     missedBeatsCount_(agentIndex) = 0.0; //reset missed beats counter
01946 
01947     //erase transition flags from this agent -> to be sure it is no longer considered
01948     cleanAgentAndFatherTransitionFlags(agentIndex);
01949     for (int j = 0; j < considerFatherTransitionBeat_.getCols(); j++)
01950       considerFatherTransitionBeat_(agentIndex, j) = NA;
01951 
01952     //if(timeElapsed_ == 1416)
01953     //  cout << "Killed Agent " << agentIndex << "; muted: " << mutedAgentsTmp_(agentIndex) << "; sc: " << score_(agentIndex)
01954     //      << "; bc: " << beatCounter_(agentIndex) << "; lper: " << lastPeriods_(agentIndex) << "; lph: " << lastPhases_(agentIndex)
01955     //      << "; mbc: " << missedBeatsCount_(agentIndex) << endl;
01956   }
01957   else if(logFile_)
01958   {
01959     ostringstream killMotif;
01960     killMotif << "BESTKILL_" << motif;
01961     debugAddEvent(killMotif.str(), agentIndex, (mrs_natural) lastPeriods_(agentIndex),
01962                   (mrs_natural) lastPhases_(agentIndex), score_(agentIndex), bestScore_, callAgent);
01963   }
01964 }
01965 
01966 void
01967 BeatReferee::calcAbsoluteBestScore()
01968 {
01969   mrs_natural firstAliveAgent = getFirstAliveAgent();
01970   mrs_real bestLocalScore = score_(firstAliveAgent);
01971   mrs_natural bestLocalAgent = firstAliveAgent;
01972   for (mrs_natural o = firstAliveAgent+1; o < nrAgents_; o++)
01973   {
01974     //Only consider alive agents:
01975     if(!mutedAgentsTmp_(o))
01976     {
01977       if(score_(o) > bestLocalScore)
01978       {
01979         bestLocalScore = score_(o);
01980         bestLocalAgent = o;
01981       }
01982     }
01983   }
01984 
01985   if((bestScore_ >= 0 && bestLocalScore > bestFactor_ * bestScore_) ||
01986       (bestScore_ < 0 && bestLocalScore > bestScore_ / bestFactor_))
01987   {
01988     if(logFile_)
01989       debugAddEvent("BEST", bestLocalAgent, (mrs_natural) lastPeriods_(bestLocalAgent),
01990                     (mrs_natural) lastPhases_(bestLocalAgent), bestLocalScore, bestScore_);
01991 
01992     bestScore_ = bestLocalScore;
01993     bestAgentIndex_ = bestLocalAgent;
01994     bestFinalAgent_ = bestAgentIndex_;
01995   }
01996   //cout << "Absolute Best Agent: " << bestAgentIndex_ << " BestScore: " << bestScore_ << endl;
01997 }
01998 
01999 void
02000 BeatReferee::debugCreateFile()
02001 {
02002   mrs_string beatTrackingMode, triggerGTTol;
02003   if(nonCausal_)
02004     beatTrackingMode = "non-causal";
02005   else beatTrackingMode = "causal";
02006   if(strcmp(inductionMode_.c_str(), "groundtruth") == 0)
02007   {
02008     stringstream tmp;
02009     tmp << triggerGtTolerance_;
02010     triggerGTTol = tmp.str();
02011   }
02012   else triggerGTTol = "NA";
02013 
02014   fstream outStream;
02015   outStream.open(logFileName_.c_str(), ios::out|ios::trunc);
02016   outStream << "Beat-Tracking: " << beatTrackingMode << "; Induction-Mode: " << inductionMode_ << "; TriggerGtTol: "
02017             << triggerGTTol << "; Induction: " << ctrl_gtInductionMode_->to<mrs_string>() << "; Induction-Time: " << inductionTime_ << "<<"
02018             << (((inductionTime_ * hopSize_) - frames2SecsAdjustment_) / srcFs_) << ">>" << endl;
02019   cerr << "Log File in " << logFileUnits_ << ": " << logFileName_ << endl;
02020   outStream.close();
02021 }
02022 
02023 void
02024 BeatReferee::debugAddEvent(mrs_string ibtEvent, mrs_natural agentIndex,
02025                            mrs_natural period, mrs_natural lastBeat, mrs_real score, mrs_real bestScore, mrs_natural callAgent)
02026 {
02027   //event is appended in the end of the file
02028   fstream outStream;
02029   outStream.open(logFileName_.c_str(), ios::out|ios::app);
02030 
02031   if(strcmp(logFileUnits_.c_str(), "frames") == 0) //timesteps in frames
02032   {
02033     outStream << ibtEvent << "|" << timeElapsed_ << "|" << agentIndex << "|" << period << "|" << lastBeat
02034               << "|" << score << "|" << bestScore << "|" << callAgent << endl;
02035   }
02036   else if(strcmp(logFileUnits_.c_str(), "seconds") == 0) //timesteps in seconds
02037     outStream << ibtEvent << "|" << (((timeElapsed_ * hopSize_) - frames2SecsAdjustment_) / srcFs_) << "|" << agentIndex << "|"
02038               << period << "|" << (((lastBeat * hopSize_) - frames2SecsAdjustment_) / srcFs_) << "|" << score << "|"
02039               << bestScore << "|" << callAgent << endl;
02040   else if(strcmp(logFileUnits_.c_str(), "frames+seconds") == 0) //timesteps in frames + seconds
02041     outStream << ibtEvent << "|" << timeElapsed_ << "<<" << (((timeElapsed_ * hopSize_) - frames2SecsAdjustment_) / srcFs_) << ">>|"
02042               << agentIndex << "|" << period << "|" << lastBeat << "<<" << (((lastBeat * hopSize_) - frames2SecsAdjustment_) / srcFs_)
02043               << ">>|" << score << "|" << bestScore << "|" << callAgent << endl;
02044 
02045   //cout << ibtEvent << "|" << timeElapsed_ << "|" << agentIndex << "|" << period << "|" << lastBeat
02046   //    << "|" << score << "|" << bestScore << "|" << callAgent << endl;
02047 
02048   outStream.close();
02049 }
02050 
02051 void
02052 BeatReferee::debugAddMsg(mrs_string ibtMsg)
02053 {
02054   fstream outStream;
02055   outStream.open(logFileName_.c_str(), ios::out|ios::app);
02056 
02057   if(strcmp(logFileUnits_.c_str(), "frames") == 0) //timesteps in frames
02058     outStream << ibtMsg << "|" << timeElapsed_ << endl;
02059   else if(strcmp(logFileUnits_.c_str(), "seconds") == 0) //timesteps in seconds
02060     outStream << ibtMsg << "|" << (((timeElapsed_ * hopSize_) - frames2SecsAdjustment_) / srcFs_) << endl;
02061   else if(strcmp(logFileUnits_.c_str(), "frames+seconds") == 0) //timesteps in frames + seconds
02062     outStream << ibtMsg << "|" << timeElapsed_ << "<<" << (((timeElapsed_ * hopSize_) - frames2SecsAdjustment_) / srcFs_) << ">>" << endl;
02063 
02064   outStream.close();
02065 
02066 }
02067 
02068 void //system intialization (at absolute t=0)
02069 BeatReferee::initialization()
02070 {
02071   agentsHistory_.create(nrAgents_, maxNrBeats_);
02072   agentsFamilyHist_.create(nrAgents_, maxNrBeats_);
02073   generationCount_.create(nrAgents_); //1index for each agent
02074   score_.create(nrAgents_); //1index for each agent
02075   lastPeriods_.create(nrAgents_); //1index for each agent
02076   lastPhases_.create(nrAgents_); //1index for each agent
02077   mutedAgents_.create(nrAgents_);//1index for each agent
02078   mutedAgentsTmp_.create(nrAgents_);//1index for each agent
02079   beatCounter_.create(nrAgents_);//1index for each agent
02080   initPeriod_.create(nrAgents_);//1index for each agent
02081   missedBeatsCount_.create(nrAgents_);//1index for each agent
02082   considerAgentTransitionBeat_.create(nrAgents_);//1index for each agent
02083   considerFatherTransitionBeat_.create(nrAgents_,10);//10 indexes (would be enough) for each agent
02084 
02085   //Agent control indexed matrix
02086   //Each line(observation) accounts for an agent
02087   //[New/Update_Flag|Period|Phase|Timming]
02088   agentControl_.create(nrAgents_, 4);
02089   updControl(ctrl_agentControl_, agentControl_);
02090 
02091   //intialize mutedAgents vectors
02092   for(int i = 0; i < nrAgents_; i++)
02093   {
02094     mutedAgents_(0, i) = 1.0; //initially all agents are muted
02095     mutedAgentsTmp_(0, i) = 1.0; //initially all agents are muted
02096 
02097     //by default consider every beat at transition bewteen father and son (for non-causal)
02098     for (int j = 0; j < considerFatherTransitionBeat_.getCols(); j++)
02099       considerFatherTransitionBeat_(i, j) = NA;
02100 
02101     considerAgentTransitionBeat_(i) = NA;
02102   }
02103   updControl(ctrl_mutedAgents_, mutedAgents_); //initially deactivate all agents
02104 
02105   inductionEnabler_ = ctrl_inductionEnabler_->to<mrs_realvec>();
02106   //in the new vesion of IBT onsets are no more considered in the induction process (so deactivate this!!)
02107   //(deactivated instead of removed for not changing the overall network structure)
02108   inductionEnabler_(1, 0) = 1.0; //diable = muted
02109 
02110   //initially deactivate induction's period estimation (ACF) -> computer expensive
02111   inductionEnabler_(0, 0) = 1.0; //diable = muted
02112   updControl(ctrl_inductionEnabler_, inductionEnabler_);
02113 
02114   if(!strcmp(ctrl_logFile_->to<mrs_string>().c_str(), "-1") == 0 &&
02115       !strcmp(ctrl_logFile_->to<mrs_string>().c_str(), "trigger") == 0)
02116   {
02117     logFileName_ = ctrl_logFileName_->to<mrs_string>();
02118     logFileUnits_ = ctrl_logFile_->to<mrs_string>();
02119     logFile_ = true;
02120     debugCreateFile();
02121   }
02122 
02123   //if induction in "givetransitions" mode -> load groundtruth transition times
02124   if(strcmp(inductionMode_.c_str(), "givetransitions") == 0)
02125     loadTriggerTimes(triggerTimesFile_);
02126   else if(strcmp(inductionMode_.c_str(), "supervised") == 0)
02127   {
02128     supervisedBestScores_.resize(1); //minimum size
02129     supervisedBestScoresMeans_.resize(1); //minimum size
02130     lastTriggerInductionTime_ = 0;
02131     lastBestScoreMeanDiff_ = supervisedTriggerThres_;
02132   }
02133 
02134   triggerInductionTime_ = inductionTime_; //initially assume first induction time
02135 }
02136 
02137 void
02138 BeatReferee::myProcess(realvec& in, realvec& out)
02139 {
02140   //run initialization at the very begining of the analysis
02141   if(startSystem_)
02142   {
02143     initialization();
02144     startSystem_ = false;
02145   }
02146 
02147   //if(timeElapsed_ == 3100)
02148   //    cout << "BR: " << timeElapsed_ << "; beatTransTol: " << beatTransitionTol_ << endl;
02149 
02150   //cout << "BR: " << timeElapsed_ << "; triggerInd: " << triggerInduction_ << "; backtrace: " << backtrace_
02151   //    << "; maxPer: " << maxPeriod_ << "; minPer: " << minPeriod_ << endl;
02152 
02153   //while no best beat detected => outputs 0 (no beat)
02154   out.setval(0.0);
02155   ctrl_beatDetected_->setValue(0.0);
02156 
02157   agentControl_ = ctrl_agentControl_->to<mrs_realvec>();
02158   //always updates every agents' timming to equalize referee's (+1 for considering next time frame)
02159   for(mrs_natural i = 0; i < agentControl_.getRows(); i++)
02160   {
02161     agentControl_(i, 3) = timeElapsed_+1;
02162     updControl(ctrl_agentControl_, agentControl_);
02163     agentsJustCreated_(i) = 0.0; //reset at all frames
02164   }
02165   //also pass timer value to the other MarSystems (+1 for considering next time frame)
02166   ctrl_tickCount_->setValue(timeElapsed_+1);
02167 
02168   //cout << "BRef: " << timeElapsed_ << "; Ind: " << inductionTime_ << "; Sc: " << bestScore_ << "; BA: " << bestAgentIndex_ << endl;
02169 
02170   //realvec with the enable flag of all the BeatAgents in the pool
02171   //(0 -> agent active; 1 -> agent desactivated)
02172   mutedAgents_ = ctrl_mutedAgents_->to<mrs_realvec>();
02173   //created tmp agents vector for just updating mutedAgents_ vector in the next tick
02174   mutedAgentsTmp_ = ctrl_mutedAgents_->to<mrs_realvec>();
02175 
02176   /*
02177   if(timeElapsed_ >= inductionTime_-1)
02178   {
02179     //Display Input from BeatAgents:
02180     cout << "INPUT (" << timeElapsed_ << "): ";
02181     for(mrs_natural a = 0; a < nrAgents_; a++)
02182     //cout << "\n" << a << "-> " << in(a, 0) << " | " << in(a, 1) << " | " << in(a, 2) << " | " << in(a, 3);
02183         cout << "\n" << a << "-> " << lastPeriods_(a) << " | " << lastPhases_(a) << " | " << score_(a) << " | " << bestScore_;
02184     cout << endl;
02185   }
02186   */
02187 
02188   //Start beat-tracking after 1st induction:
02189   if(startTracking_)
02190   {
02191     //INPUT: [Beat/Eval/None|Period|PrevBeat|Inner/Outter|Error|Score] -> inSamples_ = 6
02192     mrs_real agentFlag;
02193     mrs_natural agentPeriod;
02194     mrs_natural agentPrevBeat;
02195     mrs_real agentTolerance;
02196     mrs_natural agentError;
02197     mrs_real agentDScore;
02198 
02199     //Process all the agent pool for score, tempo and phase updates:
02200     for (mrs_natural o = 0; o < nrAgents_; o++)
02201     {
02202       agentFlag = in(o, 0);
02203 
02204       //statsPeriods_(o, timeElapsed_) = lastPeriods_(o);
02205       //statsPhases_(o, timeElapsed_) = lastPhases_(o);
02206       //statsAgentsScore_(o, timeElapsed_) = score_(o);
02207       //statsMuted_(o, timeElapsed_) = mutedAgents_(o);
02208 
02209       //Only consider alive agents that send new evaluation:
02210       //(Remind that each ouputed beat by the agents is only
02211       //evaluated at the end of its beat position + outterWindow tolerance)
02212       if(!mutedAgents_(o) && !mutedAgentsTmp_(o) && agentFlag == EVAL)
02213       {
02214         agentDScore = in(o, 5);
02215         agentPeriod = (mrs_natural) in(o, 1);
02216         agentPrevBeat = (mrs_natural) in(o, 2);
02217 
02218         //Update Agents' Periods and Phases (for equality checking)
02219         lastPeriods_(o) = agentPeriod; //(Periods in frames)
02220         lastPhases_(o) = agentPrevBeat; //(Phases in frames)
02221 
02222         //statsPeriods_(o, timeElapsed_) = agentPeriod;
02223         //statsPhases_(o, timeElapsed_) = agentPrevBeat;
02224 
02225         //Update Agents' Score
02226         score_(o) += agentDScore;
02227 
02228         //if(o == bestAgentIndex_)
02229         //  cout << "Agent" << o << "-dScore:" << agentDScore << "; agentScore:" << score_(o)
02230         //  << "(" << bestScore_ << ")" << endl;
02231 
02232         //If the bestAgent drops or increases its score the BestScore has to drop correspondingly
02233         //if((score_(bestAgentIndex_) < bestScore_) || (score_(bestAgentIndex_) > bestScore_))
02234         if(score_(bestAgentIndex_) != bestScore_)
02235         {
02236           //cout << "t:" << timeElapsed_ << "; Updating bestScore: " << "OLD: " << bestScore_
02237           //    << " from Agent" << bestAgentIndex_ << "-NEW: " << score_(bestAgentIndex_) << endl;
02238           bestScore_ = score_(bestAgentIndex_);
02239           //calcAbsoluteBestScore();
02240         }
02241         //Kill agent if it is overly erroneous (many consecutive beats found outside the predicted tolerance inner window)
02242         if(missedBeatsCount_(o) >= lostFactor_)
02243         {
02244           killAgent(o, "LOST");
02245         }
02246         //Kill Agent if its score is bellow minimum (wait 5seconds before taking it into consideration)
02247         else if(timeElapsed_ > timeBeforeKilling_ && score_(o) < bestScore_ && fabs(bestScore_-score_(o)) > 0.1
02248                 && fabs(bestScore_ - score_(o)) > fabs(bestScore_ * obsoleteFactor_))
02249         {
02250           //cout << "Agent " << o << " Killed: Score below minimum (" << score_(o) << "\\" << bestScore_ << ")" << endl;
02251           killAgent(o, "OBS");
02252         }
02253         else //Checks if there are equal agents to current EVALuated one
02254           checkAndKillEqualAgents(o);
02255 
02256         //statsAgentsScore_(o, timeElapsed_) = score_(o);
02257 
02258         //Display Scores from BeatAgents:
02259         /*  cout << "SCORES(" << timeElapsed_ << ") (reqBy:" << o << "): " << endl;
02260             for(mrs_natural a = 0; a < nrAgents_; a++)
02261             cout << a << "-> " << score_(a) << " ";
02262             cout << endl;
02263         */
02264 
02265 
02266       }
02267     }
02268 
02269     //Process all the agent pool for testing best beat and consider
02270     //the generation of new beats or the killing of existent ones
02271     for (mrs_natural o = 0; o < nrAgents_; o++)
02272     {
02273       //Only consider alive agents that send new evaluation:
02274       //(unconsider agents created in the current frame)
02275       if(!mutedAgents_(o) && !mutedAgentsTmp_(o) && !agentsJustCreated_(o))
02276       {
02277         agentFlag = in(o, 0);
02278 
02279         if(agentFlag == EVAL)
02280         {
02281           agentPeriod = (mrs_natural) in(o, 1);
02282           agentPrevBeat = (mrs_natural) in(o, 2);
02283           agentTolerance = in(o, 3);
02284           agentError = (mrs_natural) in(o, 4);
02285           agentDScore = in(o, 5);
02286 
02287           //if(o == 21)
02288           //    cout << "T: " << timeElapsed_ << " EVAL - Agent: " << o << "; ERROR: " << agentError << endl;
02289 
02290           //If a beat of an agent is inside its Inner tolerance but it has an error:
02291           //Update agent phase and period hypotheses:
02292           if(agentTolerance == INNER)
02293           {
02294             if(logFile_)
02295               debugAddEvent("UPDATE", o, agentPeriod, agentPrevBeat, score_(o), bestScore_, o);
02296 
02297             missedBeatsCount_(o) = 0.0; //reset (consecutive) missed beats counter for this agent
02298 
02299             if(abs(agentError) > 0)
02300             {
02301               updateAgentHypothesis(o, agentPeriod, agentPrevBeat, agentError);
02302             }
02303           }
02304 
02305           //If a beat of an agent is detected outside its Inner tolerance window:
02306           //Is created another agent that keeps this agent hypothesis, and updates its phase
02307           //and period to account for the given error:
02308           if(agentTolerance == OUTTER)
02309           {
02310             if(logFile_)
02311               debugAddEvent("UPD_OUTTER", o, agentPeriod, agentPrevBeat, score_(o), bestScore_, o);
02312 
02313             //CREATE NEW AGENT WITH THIS NEW HYPOTHESIS KEEPING THE SCORE OF o-delta:
02314             //(the agent that generates a new one keeps its original hypothesis);
02315             //New agent must look for a new beat on the next (updated) period
02316             createChildren(o, agentPeriod, agentPrevBeat, agentError, score_(o), beatCounter_(o));
02317             //statsAgentsLifeCycle_(o, timeElapsed_) = 2;
02318 
02319             missedBeatsCount_(o)++; //increment missed beats counter for this agent
02320           }
02321         }
02322 
02323         if(agentFlag == BEAT)
02324         {
02325           //in nonCausal analysis keep agents' beat history
02326           if(nonCausal_)
02327           {
02328             agentsHistory_(o, (mrs_natural) beatCounter_(o)) = timeElapsed_; //save beat-time
02329             agentsFamilyHist_(o, (mrs_natural) beatCounter_(o)) = o; //save agent whose beat-time is
02330 
02331             //if(o == 26 && timeElapsed_ >= 4546)
02332             //  cout << "=========t: " << timeElapsed_ << "; BC: " << beatCounter_(o) << "; BEAT: " << agentsHistory_(o, (mrs_natural) beatCounter_(o)) << endl;
02333 
02334             handleAgentsTansition(o);
02335           }
02336 
02337           //if(timeElapsed_ >= 4196 && (o == 15 || o == 24))
02338           //    cout << "t:" << timeElapsed_ << "-BEAT CHECK " << beatCounter_(o) << ": " << (((agentsHistory_(o, beatCounter_(o)) * hopSize_) - hopSize_/2) / srcFs_)
02339           //        << " by: " << agentsFamilyHist_(o, beatCounter_(o)) << endl;
02340 
02341           //Increment beat counter of each agent
02342           beatCounter_(o)++;
02343 
02344           //update agent's last phase
02345           lastPhases_(o) = timeElapsed_; //(Phases in frames)
02346 
02347           //Display Beats from BeatAgents:
02348           //if(o == 8)
02349           //    cout << "t: " << timeElapsed_ << "; BEAT - Agent " << o << "(" << ((timeElapsed_ * hopSize_) - (hopSize_/2)) / srcFs_
02350           //        << ") -> AgentPeriod: " << lastPeriods_(o) << "; AgentScore: " << score_(o) << " BestAgent: "
02351           //        << bestAgentIndex_ << " BestScore: " << bestScore_ << " BeatCount: " << beatCounter_(o) << endl;
02352 
02353           //if best agent sends beat => outputs best beat
02354           if(o == bestAgentIndex_)
02355           {
02356             //beat transition safecheck-> to avoid beats given by different agents distanced less than a tolerance (60% of current ibi)
02357             //(ignore this requirement in the beat just after reseting the system, with trigger induction)
02358             //if((timeElapsed_ - lastBeatTime_) >= 0.6*lastBeatPeriod_)
02359             if((timeElapsed_ - lastBeatTime_) >= beatTransitionTol_*lastBeatPeriod_)
02360             {
02361               //Display Outputted Beat:
02362               //cout << "OUTPUT(" << timeElapsed_ << "-" << ((timeElapsed_ * hopSize_) - (hopSize_/2)) / srcFs_ << "):Beat from Agent " << bestAgentIndex_ <<
02363               //    " BestScore:" << bestScore_ << " (" << score_(bestAgentIndex_) << ")";
02364               //cout << ":" << (60.0 / (timeElapsed_ - lastBeatTime_)) * (ctrl_srcFs_->to<mrs_real>() / ctrl_hopSize_->to<mrs_natural>()) << "BPM" << endl;
02365               //cout << "BEST_AgentPeriod: " << lastPeriods_(bestAgentIndex_) << "(" << (timeElapsed_ - lastBeatTime_) << ")" << endl;
02366 
02367               //SEND BEAT COMMAND!
02368               ctrl_beatDetected_->setValue(1.0);
02369               out.setval(1.0);
02370 
02371               //Updates agent history, which accounts for the total number
02372               //of the detected best (considered) beats of each agent:
02373               historyCount_(o)++;
02374               //historyBeatTimes_(o, outputCount_) = timeElapsed_;
02375               outputCount_ ++;
02376               lastBeatTime_ = timeElapsed_;
02377               lastBeatPeriod_ = (mrs_natural) lastPeriods_(o);
02378 
02379               if(logFile_)
02380                 debugAddEvent("==========> BEAT", o, (mrs_natural) lastPeriods_(o),
02381                               (mrs_natural) lastPhases_(o), score_(o), bestScore_);
02382 
02383               //if trigger mode defined as ground_truth
02384               if(strcmp(inductionMode_.c_str(), "groundtruth") == 0)
02385               {
02386                 //check beat-time distance to ground-truth (check if any false positive or negative)
02387                 mrs_natural localBeatError = checkBeatInGTFile();
02388                 localBeatError == 0 ? lostGTBeatsCount_ = 0 : lostGTBeatsCount_+=localBeatError;
02389                 //cout << "lostBeatsCount: " << lostGTBeatsCount_ << endl;
02390 
02391                 //while beat error count = 0 -> assign bestAgentBeforeTrigger as current best agent
02392                 if(lostGTBeatsCount_ == 0)
02393                 {
02394                   bestAgentBeforeTrigger_ = bestAgentIndex_;
02395 
02396                   if(logFile_)
02397                     debugAddEvent("BEST_TRIGGER", bestAgentBeforeTrigger_, (mrs_natural) lastPeriods_(bestAgentBeforeTrigger_),
02398                                   (mrs_natural) lastPhases_(bestAgentBeforeTrigger_), score_(bestAgentBeforeTrigger_), bestScore_);
02399 
02400                   //cout << timeElapsed_ << "=======: bestAgentBeforeTrigger: " << bestAgentBeforeTrigger_
02401                   //    << "; bestAgent: " << bestAgentBeforeTrigger_ << endl;
02402                 }
02403 
02404                 //request new induction if detected more consecutive beat misses than the tolerated
02405                 if(lostGTBeatsCount_ >= triggerGtTolerance_)
02406                 {
02407                   //cout << "LOST req TRIGGER at: " << timeElapsed_ << " (" << ((timeElapsed_ * hopSize_) - (hopSize_/2)) / srcFs_ << ")" << endl;
02408                   lostGTBeatsCount_ = 0; //reset beat error count
02409                   triggerInductionExternalRequest_ = true;
02410 
02411                   //cout << "2: " << ctrl_logFile_->to<mrs_string>().c_str() << endl;
02412 
02413                   //trigger logfile:
02414                   if(strcmp(ctrl_logFile_->to<mrs_string>().c_str(), "trigger") == 0)
02415                   {
02416                     triggerCount_++; //counts the number of triggers for the trigger logfile
02417                     ostringstream oss;
02418                     oss << ctrl_destFileName_->to<mrs_string>() << "_logTrigger.txt";
02419                     ofstream trigCountStream;
02420                     trigCountStream.open(oss.str().c_str(), ios::out|ios::trunc);
02421                     trigCountStream << triggerCount_ << endl;
02422                     trigCountStream.close();
02423                   }
02424                 }
02425               }
02426               else if(strcmp(inductionMode_.c_str(), "repeated") == 0 ||
02427                       (strcmp(inductionMode_.c_str(), "random") == 0) ||
02428                       (strcmp(inductionMode_.c_str(), "supervised") == 0))
02429               {
02430                 //in trigger modes other than "groundtruth" assign the bestAgentBeforeTrigger as the bestAgent at every estimated beat
02431                 bestAgentBeforeTrigger_ = bestAgentIndex_;
02432 
02433                 if(logFile_)
02434                   debugAddEvent("BEST_TRIGGER", bestAgentBeforeTrigger_, (mrs_natural) lastPeriods_(bestAgentBeforeTrigger_),
02435                                 (mrs_natural) lastPhases_(bestAgentBeforeTrigger_), score_(bestAgentBeforeTrigger_), bestScore_);
02436               }
02437               //in triggertimes trigger mode consider the bestAgentBeforeTrigger as the best agent at the last beat-time before the effective transitions
02438               else if(strcmp(inductionMode_.c_str(), "givetransitions") == 0 &&
02439                       (timeElapsed_ + (mrs_natural)lastPeriods_(bestAgentIndex_)) >= transitionTimes_(triggerCount_) && transitionsConsidered_(triggerCount_) == 0.0)
02440               {
02441                 bestAgentBeforeTrigger_ = bestAgentIndex_;
02442                 resetSystem(bestAgentBeforeTrigger_); //kill everyone except the bestAgent before trigger
02443                 transitionsConsidered_(triggerCount_) = 1;
02444 
02445                 if(logFile_)
02446                   debugAddEvent("BEST_TRIGGER", bestAgentBeforeTrigger_, (mrs_natural) lastPeriods_(bestAgentBeforeTrigger_),
02447                                 (mrs_natural) lastPhases_(bestAgentBeforeTrigger_), score_(bestAgentBeforeTrigger_), bestScore_);
02448               }
02449             }
02450             else if(logFile_)
02451               debugAddEvent("BEAT CANCEL", o, (mrs_natural) lastPeriods_(o),
02452                             (mrs_natural) lastPhases_(o), score_(o), bestScore_);
02453 
02454             //redo agents' scores calculation
02455             calcAbsoluteBestScore();
02456           }
02457         }
02458       }
02459     }
02460   }
02461 
02462   //Create the first BeatAgents with new hypotheses just after Tseconds of induction:
02463   if(processInduction_)
02464   {
02465     if(logFile_)
02466       debugAddMsg("=========== INDUCTION ===========");
02467 
02468     firstHypotheses_ = ctrl_firstHypotheses_->to<mrs_realvec>();
02469 
02470     //update values for eventual forced periods in induction stage
02471     maxPeriod_ = ctrl_maxPeriod_->to<mrs_natural>();
02472     minPeriod_ = ctrl_minPeriod_->to<mrs_natural>();
02473     //max possible nr. of beats in the analysed sound file (*1.7 - tolerance due to possible limit surpassing)
02474     maxNrBeats_ = (mrs_natural) (ceil(((mrs_real) soundFileSize_) / ((mrs_real) minPeriod_)) * 1.7);
02475     agentsHistory_.stretch(nrAgents_, maxNrBeats_);
02476     agentsFamilyHist_.stretch(nrAgents_, maxNrBeats_);
02477 
02478     mrs_natural newAgentPeriod;
02479     mrs_natural newAgentPhase;
02480     mrs_real newAgentScore;
02481 
02482     if(strcmp(inductionMode_.c_str(), "givetransitions") == 0)
02483       bestAgentBeforeTrigger_ = bestAgentIndex_;
02484     if(startTracking_ && resetAfterNewInduction_)
02485     {
02486       resetSystem(bestAgentBeforeTrigger_); //kill everyone except the bestAgent at transition
02487       lastBeatPeriod_ = 0; //reset lastBeatPeriod to avoid BEAT_CANCEL int the first beat after a system reset
02488     }
02489 
02490     //cout << "TRIGGER AGENTS @ " << timeElapsed_ << endl;
02491 
02492     //before getting IBI clusters we need to make sure which agents will be killed
02493     //for don't consider them as possible fathers to adopt trigger agents
02494     mrs_realvec newAgentsScore(firstHypotheses_.getRows());
02495     mrs_natural count = 0;
02496     for(int i = 0; i < firstHypotheses_.getRows(); i++)
02497     {
02498       if((mrs_natural) firstHypotheses_(i,0) > 0) //only consider valid hypothesis:
02499       {
02500         //firstHypotheses_ -> matrix with i generated beat hypotheses + score, in the induction stage
02501         //[ BPMi | Beati | Score i ]
02502         newAgentPeriod = (mrs_natural) firstHypotheses_(i,0);
02503         newAgentPhase = (mrs_natural) firstHypotheses_(i,1);
02504         newAgentScore = firstHypotheses_(i,2);
02505 
02506         if(!resetAfterNewInduction_) //only consider below in non RESET trigger mode
02507         {
02508           //only considered agents which aren't replicated
02509           if(existEqualBetterAgents(-1, newAgentPeriod, newAgentPhase, newAgentScore) == -1)
02510           {
02511             newAgentsScore(count) = newAgentScore;
02512 
02513             //if(timeElapsed_ == 3100)
02514             //  cout << "NEW1 " << i << "-> Agents Score: " << newAgentsScore(count) << "; period: "
02515             //  << newAgentPeriod << "; elems: " << count << endl;
02516 
02517             count++;
02518           }
02519           else //if existed equal agents erase hypotheses (so this agent is not considered for creation)
02520           {
02521             firstHypotheses_(i,0) = 0.0;
02522             firstHypotheses_(i,1) = 0.0;
02523             firstHypotheses_(i,2) = 0.0;
02524 
02525             if(logFile_)
02526               debugAddEvent("EQ_TRIGGER", -1, newAgentPeriod, newAgentPhase, newAgentScore,
02527                             bestScore_, existEqualAgents(-1, newAgentPeriod, newAgentPhase));
02528           }
02529         }
02530       }
02531 
02532 
02533       grantPoolSpace2(-1, count, newAgentsScore); //grant pool space for all needed agents to be created
02534     }
02535 
02536     //Updating initial bestScore and creating first agents:
02537     //(nr of initial agents equals nr of bpm hypotheses)
02538     for(mrs_natural i = 0; i < firstHypotheses_.getRows(); i++)
02539     {
02540       if((mrs_natural) firstHypotheses_(i,0) > 0) //only consider valid hypothesis:
02541       {
02542         //firstHypotheses_ -> matrix with i generated beat hypotheses + score, in the induction stage
02543         //[ BPMi | Beati | Score i ]
02544         newAgentPeriod = (mrs_natural) firstHypotheses_(i,0);
02545         newAgentPhase = (mrs_natural) firstHypotheses_(i,1);
02546         newAgentScore = firstHypotheses_(i,2);
02547 
02548         //cout << "t: " << timeElapsed_ << "; nAP: " << newAgentPeriod << "; nAPh: " << newAgentPhase << "; Score" << i << ": " << newAgentScore << endl;
02549 
02550         //create new agent
02551         mrs_natural createdAgent = -1;
02552         if(startTracking_)
02553         {
02554           //after first induction, at each trigger all agents derive from last best good agent
02555           createdAgent = createNewAgent(newAgentPeriod, newAgentPhase, newAgentScore, beatCounter_(bestAgentBeforeTrigger_), bestAgentBeforeTrigger_);
02556         }
02557         else //at first induction all agents are created as first generation
02558           createdAgent = createNewAgent(newAgentPeriod, newAgentPhase, newAgentScore, 0, -1);
02559 
02560         //cout << "t: " << timeElapsed_ << "; BESTAGENT: " << bestAgentIndex_ << endl;
02561 
02562         //only if agent is actually created it is considered for best check
02563         if(createdAgent >= 0)
02564         {
02565           if(newAgentScore > bestScore_)
02566           {
02567             bestScore_ = newAgentScore;
02568             bestAgentIndex_ = createdAgent;
02569             bestFinalAgent_ = bestAgentIndex_;
02570 
02571             //at the initial induction the best agent before trigger is assigned as the best initial agent
02572             if(!startTracking_)
02573             {
02574               bestAgentBeforeTrigger_ = bestAgentIndex_;
02575 
02576               if(logFile_)
02577                 debugAddEvent("BEST_TRIGGER", bestAgentBeforeTrigger_, (mrs_natural) lastPeriods_(bestAgentBeforeTrigger_),
02578                               (mrs_natural) lastPhases_(bestAgentBeforeTrigger_), score_(bestAgentBeforeTrigger_), bestScore_);
02579             }
02580 
02581             if(logFile_)
02582               debugAddEvent("BEST", bestAgentIndex_, newAgentPeriod, newAgentPhase, newAgentScore, bestScore_);
02583           }
02584         }
02585         //else cout << timeElapsed_ << ": AGENT " << createdAgent << " KILLED BY EQUAL CHECK!" << endl;
02586 
02587         if(i == nrAgents_-1)
02588         {
02589           MRSWARN("Last hypotheses discarted because the nr. of hypotheses surpasses the nr. of BeatAgents");
02590           break;
02591         }
02592 
02593         if(newAgentPeriod == 0)
02594         {
02595           MRSWARN("Last hypotheses discarted because no more periods considered");
02596           break;
02597         }
02598       }
02599 
02600       //multiplied by sqrt(period) for disinflating the faster agents (with smaller periods)
02601       //bestScore_ *= sqrt((mrs_real)maxPeriod_);
02602 
02603       //reset supervisedBestScores buffers at every induction
02604       if(strcmp(inductionMode_.c_str(), "supervised") == 0)
02605       {
02606         supervisedBestScores_.resize(1); //minimum size
02607         supervisedBestScoresMeans_.resize(1); //minimum size
02608         lastTriggerInductionTime_ = timeElapsed_; //keep last induction time
02609         lastBestScoreMeanDiff_ = supervisedTriggerThres_;
02610       }
02611 
02612     }
02613 
02614     //if backtrace restart tick counter
02615     //(timing updated here, for backtracing, for being contablized in the log file)
02616     if(backtrace_)
02617     {
02618       backtraceEndTime_ = timeElapsed_; //save end time as time when backtrace requested
02619 
02620       //retrocede all MarSystem's timer by inductionTime:
02621       for(mrs_natural i = 0; i < agentControl_.getRows(); i++)
02622       {
02623         agentControl_(i, 3) = timeElapsed_-inductionTime_;
02624         updControl(ctrl_agentControl_, agentControl_);
02625       }
02626       ctrl_tickCount_->setValue(timeElapsed_-inductionTime_);
02627 
02628       timeElapsed_ = timeElapsed_-inductionTime_-1; //-1 because timer is updated by the end of the cycle (so next cycle is the actual 0)
02629       //cout << "Back: " << timeElapsed_ << "; newT: " << timeElapsed_ << "with ind: " << inductionTime_ << endl;
02630 
02631       //disable backtrace after first induction (for non-causal mode)
02632       updControl(ctrl_backtrace_, false);
02633     }
02634     //incremented for counting inductionTime_ after induction before enabling obsolete killing
02635     else
02636       timeBeforeKilling_+=inductionTime_;
02637 
02638     //After finnishing induction deactivate induction's period estimation (ACF) -> computer expensive
02639     inductionEnabler_(0, 0) = 1.0; //diable = muted
02640     updControl(ctrl_inductionEnabler_, inductionEnabler_);
02641 
02642     if(startTracking_ && resetAfterNewInduction_)
02643     {
02644       killAgent(bestAgentBeforeTrigger_, "RESET", -1); //kill bestAgent at transition
02645       calcAbsoluteBestScore();
02646     }
02647 
02648     processInduction_ = false;
02649     startTracking_ = true; //start tracking (after first induction, tracking keeps on running)
02650     updControl(ctrl_triggerInduction_, false); //deactivate trigger induction!!
02651 
02652   }
02653 
02654   //MATLAB_PUT(agentsHistory_, "agentsHistory");
02655   //MATLAB_PUT(bestFinalAgent_, "bestFinalAgent");
02656 
02657   //clean first half of the feature window buffer before every new induction
02658   if(timeElapsed_ > backtraceEndTime_ && ((ctrl_triggerInductionExternalRequest_->to<mrs_bool>() || timeElapsed_ == triggerInductionTime_-2)
02659                                           || (strcmp(inductionMode_.c_str(), "givetransitions") == 0 && timeElapsed_ == triggerTimes_(triggerCount_)-2)))
02660   {
02661     updControl(ctrl_resetFeatWindow_, true);
02662 
02663     if(ctrl_triggerInductionExternalRequest_->to<mrs_bool>())
02664     {
02665       triggerInductionExternalRequest_ = false;
02666       triggerInduction_ = true;
02667     }
02668 
02669   }
02670   //just before the induction triggering activate periodicity estimation (via ACF peaks)
02671   //(don't call this wihtin backtrace window)
02672   else if(timeElapsed_ > backtraceEndTime_ && ((triggerInduction_ || timeElapsed_ == triggerInductionTime_-1)
02673           || (strcmp(inductionMode_.c_str(), "givetransitions") == 0 && timeElapsed_ == triggerTimes_(triggerCount_)-1)))
02674   {
02675     mrs_real outTmp = out(0,0); //[!!] don't know why when calling updControl() out is reset
02676 
02677     //cout << "Trigger Mode: " << inductionMode_ << endl;
02678 
02679     //activate periodicity estimation (via ACF peaks)
02680     inductionEnabler_(0, 0) = 0.0; //enable = unmuted
02681     updControl(ctrl_inductionEnabler_, inductionEnabler_);
02682     //cout << "Induction triggered at: " << timeElapsed_ << endl;
02683 
02684     //cout << "triggerInd: " << triggerInduction_ << "@" << timeElapsed_
02685     //  << "; bestAgent: " << bestAgentBeforeTrigger_ << endl;
02686 
02687     //send current and inductionTime before best agents score to new induction stage
02688     if(startTracking_)
02689     {
02690       if(resetAfterNewInduction_) bestScore_ = NA;
02691       else //update current best score before trigger
02692       {
02693         calcAbsoluteBestScore();
02694       }
02695     }
02696 
02697     updControl(ctrl_curBestScore_, bestScore_);
02698 
02699     updControl(ctrl_triggerInduction_, true); //request induction!!
02700 
02701     processInduction_ = true; //update system with new induction values
02702     triggerInduction_ = false;
02703 
02704     //recover value above
02705     out.setval(outTmp);
02706 
02707     if(startTracking_)
02708       triggerCount_++; //counts the number of triggers
02709 
02710     if(strcmp(inductionMode_.c_str(), "repeated") == 0 ||
02711         strcmp(inductionMode_.c_str(), "random") == 0 ||
02712         strcmp(inductionMode_.c_str(), "supervised") == 0)
02713     {
02714       if(strcmp(inductionMode_.c_str(), "repeated") == 0) //repeat induction mode (repeated every induction time)
02715         triggerInductionTime_ += 100; //for testing repeated induction x in x secs
02716       else if(strcmp(inductionMode_.c_str(), "random") == 0)
02717       {
02718         mrs_natural minTriggerRep = maxPeriod_;
02719         mrs_natural maxTriggerRep = inductionTime_ * 3;
02720         srand((mrs_natural)(timeElapsed_+time(NULL))); //just a random seed
02721 
02722         mrs_natural randTriggerRep = (mrs_natural) ((rand() % (maxTriggerRep-minTriggerRep)) + minTriggerRep);
02723 
02724         //cout << "lastIndTime:" << triggerInductionTime_;
02725 
02726         triggerInductionTime_ += randTriggerRep;
02727       }
02728 
02729       //trigger logfile:
02730       if(strcmp(ctrl_logFile_->to<mrs_string>().c_str(), "trigger") == 0)
02731       {
02732         ostringstream oss;
02733         oss << ctrl_destFileName_->to<mrs_string>() << "_logTrigger.txt";
02734         ofstream trigCountStream;
02735         trigCountStream.open(oss.str().c_str(), ios::out|ios::trunc);
02736         trigCountStream << triggerCount_ << endl;
02737         trigCountStream.close();
02738       }
02739 
02740     }
02741     else triggerInductionTime_ = -1; //avoid another induction by time when backtracing
02742   }
02743 
02744   //if in nonCausalMode save last best agent history as the final output
02745   if(nonCausal_)
02746   {
02747     soundFileSize_ = ctrl_soundFileSize_->to<mrs_natural>();
02748 
02749     //cout << "T: " << timeElapsed_ << "; soundFileSize: " << soundFileSize_ << endl;
02750 
02751     //by the end of the audio analysis:
02752     if(timeElapsed_ == soundFileSize_-1) //[! -1 for acouting on time of timing reset on backtrace mode]
02753     {
02754       mrs_natural bestAgentHistorySize = (mrs_natural) beatCounter_(bestFinalAgent_);
02755       bestFinalAgentHistory_.create(bestAgentHistorySize);
02756 
02757       if(logFile_)
02758         debugAddMsg("=========== NON-CAUSAL BEAT-TIMES ===========");
02759 
02760       for(int i = 0; i < bestAgentHistorySize; i++)
02761       {
02762         //cout << "I: " << i << "; History: " << agentsHistory_(bestFinalAgent_, i) << endl;
02763         bestFinalAgentHistory_(i) = agentsHistory_(bestFinalAgent_, i); //Output Vector
02764 
02765         if(logFile_)
02766         {
02767           //prints non-causal beat-times
02768           mrs_natural agent = (mrs_natural) agentsFamilyHist_(bestFinalAgent_, i);
02769           debugAddEvent("BEAT", agent, -1, (mrs_natural) bestFinalAgentHistory_(i), -1, -1);
02770         }
02771       }
02772 
02773       if(logFile_)
02774         debugAddMsg("==========================");
02775 
02776       /*
02777       cout << "BEST FAMILY: " << endl;
02778       for(int i = 0; i < bestAgentHistorySize; i++)
02779       {
02780         cout << agentsFamilyHist_(bestFinalAgent_, i) << "; ";
02781       }
02782       */
02783 
02784       if(bestAgentHistorySize == 0) //if no beats detected [to avoid crash]
02785       {
02786         bestFinalAgentHistory_.create(1);
02787         bestFinalAgentHistory_(0) = -1.0;
02788       }
02789 
02790       updControl(ctrl_bestFinalAgentHistory_, bestFinalAgentHistory_);
02791     }
02792   }
02793 
02794   //in supervised induction mode:
02795   //1- keep a buffer with all bestScore values since previous induction
02796   //2- do a mean of all bestScores in a window with the size of the induction at 1sec increments
02797   //3- subtract every mean of bestScores with the previous:
02798   //   if difference < supervisedTriggerThres -> request new induction
02799   if(strcmp(inductionMode_.c_str(), "supervised") == 0)
02800   {
02801     mrs_natural smoothResolution = 3; //3secs resolution
02802     smoothResolution = (mrs_natural) (smoothResolution * (srcFs_/hopSize_));
02803     //supervision logfile:
02804     ofstream diffBS, meanBS, rawBS;
02805     if(strcmp(ctrl_logFile_->to<mrs_string>().c_str(), "trigger") == 0)
02806     {
02807       ostringstream ossDiff, ossMean, ossBS;
02808       ossDiff << ctrl_destFileName_->to<mrs_string>() << "_diffBestScore.txt";
02809       ossMean << ctrl_destFileName_->to<mrs_string>() << "_meanBestScore.txt";
02810       ossBS << ctrl_destFileName_->to<mrs_string>() << "_bestScore.txt";
02811 
02812       if(timeElapsed_ == 0)
02813       {
02814         diffBS.open(ossDiff.str().c_str(), ios::out|ios::trunc);
02815         meanBS.open(ossMean.str().c_str(), ios::out|ios::trunc);
02816         rawBS.open(ossBS.str().c_str(), ios::out|ios::trunc);
02817       }
02818       else
02819       {
02820         diffBS.open(ossDiff.str().c_str(), ios::out|ios::app);
02821         meanBS.open(ossMean.str().c_str(), ios::out|ios::app);
02822         rawBS.open(ossBS.str().c_str(), ios::out|ios::app);
02823       }
02824 
02825       rawBS << bestScore_ << endl;
02826       rawBS.close();
02827     }
02828 
02829     if(bestScore_ == NA)
02830       supervisedBestScores_.push_back(0.0);
02831     else supervisedBestScores_.push_back(bestScore_);
02832 
02833     //cout << "time: " << timeElapsed_ << "; BS: " << supervisedBestScores_.at(supervisedBestScores_.size()-1)
02834     //   << "; Size: " << supervisedBestScores_.size() << endl;
02835 
02836     //wait the first induction time to fill the supervisedBestScores buffer
02837     if(timeElapsed_ >= lastTriggerInductionTime_ + inductionTime_)
02838     {
02839       mrs_natural stepTime = timeElapsed_ - (lastTriggerInductionTime_ + inductionTime_);
02840       mrs_natural stepSize = 1; // 1 second
02841       stepSize = (mrs_natural) (stepSize * (srcFs_/hopSize_));
02842       if(!(stepTime % stepSize))
02843       {
02844         mrs_real sum = 0.0;
02845         for(mrs_natural s = (mrs_natural) (supervisedBestScores_.size()-smoothResolution); s < (mrs_natural) supervisedBestScores_.size(); s++)
02846           sum += supervisedBestScores_.at(s);
02847         mrs_real mean = sum /= smoothResolution;
02848         supervisedBestScoresMeans_.push_back(mean);
02849 
02850         mrs_real bestScoreMeanDiff = 0.1;
02851         if(supervisedBestScoresMeans_.size() > 1)
02852 
02853 
02854           bestScoreMeanDiff = supervisedBestScoresMeans_.at(supervisedBestScoresMeans_.size()-1)-supervisedBestScoresMeans_.at(supervisedBestScoresMeans_.size()-2);
02855 
02856         //cout << "AKI @ " << timeElapsed_ << "; stepTime: " << stepTime << "; min: "
02857         //<< (supervisedBestScores_.size()-inductionTime_) << "; max: " << supervisedBestScores_.size() //<< "; BSMeanDiff: " << bestScoreMeanDiff
02858         //<< "; thisMean: " << supervisedBestScoresMeans_.at(supervisedBestScoresMeans_.size()-1)
02859         //<< "; lastMean: " << supervisedBestScoresMeans_.at(supervisedBestScoresMeans_.size()-2) << endl;
02860         //<< "; thisDiff: " << bestScoreMeanDiff << "; lastDiff: " << lastBestScoreMeanDiff_ << endl;
02861 
02862         if(strcmp(ctrl_logFile_->to<mrs_string>().c_str(), "trigger") == 0)
02863         {
02864           diffBS << bestScoreMeanDiff << endl;
02865           diffBS.close();
02866           meanBS << supervisedBestScoresMeans_.at(supervisedBestScoresMeans_.size()-1) << endl;
02867           meanBS.close();
02868         }
02869 
02870         //trigger induction time after signalization
02871         if((bestScoreMeanDiff < (supervisedTriggerThres_*supervisedBestScoresMeans_.at(supervisedBestScoresMeans_.size()-1)))
02872             && (lastBestScoreMeanDiff_ > (supervisedTriggerThres_*supervisedBestScoresMeans_.at(supervisedBestScoresMeans_.size()-2))))
02873         {
02874           //save lastTriggerInductionTime for plotting
02875           //mrs_natural lastTriggerInductionTime = triggerInductionTime_;
02876 
02877           triggerInductionTime_ = timeElapsed_ + 3; //trigger new induction now (sum needed 3 frames)
02878 
02879           //supervision logfile:
02880           if(strcmp(ctrl_logFile_->to<mrs_string>().c_str(), "trigger") == 0)
02881           {
02882             ostringstream oss;
02883             oss << ctrl_destFileName_->to<mrs_string>() << "_triggerTimes.txt";
02884             ofstream triggerBS;
02885             if(lastTriggerInductionTime_ == inductionTime_)
02886               triggerBS.open(oss.str().c_str(), ios::out|ios::trunc);
02887             else triggerBS.open(oss.str().c_str(), ios::out|ios::app);
02888 
02889             triggerBS << triggerInductionTime_ << endl;
02890             triggerBS.close();
02891           }
02892 
02893           //cout << "TRIGGER @ " << timeElapsed_ << "; TT: " << triggerInductionTime_ << endl;
02894           //cout << "THRES: " << supervisedTriggerThres_ << endl;
02895         }
02896 
02897         lastBestScoreMeanDiff_ = bestScoreMeanDiff;
02898       }
02899       else if(strcmp(ctrl_logFile_->to<mrs_string>().c_str(), "trigger") == 0) //DEBUGGING
02900       {
02901         diffBS << NA << endl;
02902         diffBS.close();
02903         meanBS << NA << endl;
02904         meanBS.close();
02905       }
02906     }
02907     else if(strcmp(ctrl_logFile_->to<mrs_string>().c_str(), "trigger") == 0) //DEBUGGING
02908     {
02909       diffBS << NA << endl;
02910       diffBS.close();
02911       meanBS << NA << endl;
02912       meanBS.close();
02913     }
02914   }
02915 
02916 
02917   //MATLAB_PUT(statsAgentsScore_, "agentsScore");
02918   //MATLAB_PUT(in, "BeatAgents");
02919 
02920   //MATLAB_PUT(out, "BeatReferee");
02921   /*
02922     MATLAB_PUT(historyBeatTimes_, "HistoryBeatTimes");
02923     MATLAB_PUT(historyCount_, "HistoryCount");
02924     MATLAB_PUT(statsPeriods_, "statsPeriods");
02925     MATLAB_PUT(statsAgentsLifeCycle_, "statsAgentsLifeCycle");
02926 
02927     MATLAB_PUT(bestScore_, "bestScore");
02928     MATLAB_EVAL("bestAgentScore = [bestAgentScore bestScore];");
02929   */
02930   //MATLAB_EVAL("FinalBeats = [FinalBeats, BeatReferee];");
02931 
02932   //MATLAB_EVAL("hold on;");
02933   //MATLAB_EVAL("plot(BeatAgentsTS)");
02934   //MATLAB_EVAL("stem(t, 1, 'r');");
02935   //MATLAB_EVAL("hold off;");
02936 
02937   timeElapsed_++; //increment timer by the end of each cycle
02938 
02939 }