Marsyas  0.6.0-alpha
/usr/src/RPM/BUILD/marsyas-0.6.0/src/marsyas/marsystems/TimelineLabeler.cpp
Go to the documentation of this file.
00001 /*
00002 ** Copyright (C) 1998-2006 George Tzanetakis <gtzan@cs.uvic.ca>
00003 **
00004 ** This program is free software; you can redistribute it and/or modify
00005 ** it under the terms of the GNU General Public License as published by
00006 ** the Free Software Foundation; either version 2 of the License, or
00007 ** (at your option) any later version.
00008 **
00009 ** This program is distributed in the hope that it will be useful,
00010 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 ** GNU General Public License for more details.
00013 **
00014 ** You should have received a copy of the GNU General Public License
00015 ** along with this program; if not, write to the Free Software
00016 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00017 */
00018 
00019 #include "TimelineLabeler.h"
00020 #include "../common_source.h"
00021 #include <fstream>
00022 #include <sstream>
00023 
00024 using namespace std;
00025 using namespace Marsyas;
00026 
00027 TimelineLabeler::TimelineLabeler(mrs_string name):MarSystem("TimelineLabeler", name)
00028 {
00029   addControls();
00030   labelFiles_ = ",";
00031   numClasses_ = 0;
00032   selectedLabel_ = "init";
00033   curRegion_ = 0;
00034   foundNextRegion_ = false;
00035   noLabelFile_ = false;
00036   myAdvance_ = false;
00037 }
00038 
00039 TimelineLabeler::TimelineLabeler(const TimelineLabeler& a) : MarSystem(a)
00040 {
00041   ctrl_labelFiles_ = getctrl("mrs_string/labelFiles");
00042   ctrl_currentLabelFile_ = getctrl("mrs_real/currentLabelFile");
00043   ctrl_labelNames_ = getctrl("mrs_string/labelNames");
00044   ctrl_lexiconLabelNames_ = getctrl("mrs_string/lexiconLabelNames");
00045   ctrl_lexiconNLabels_ = getctrl("mrs_natural/lexiconNLabels");
00046 
00047   ctrl_currentLabel_ = getctrl("mrs_real/currentLabel");
00048   ctrl_previousLabel_ = getctrl("mrs_real/previousLabel");
00049   ctrl_nLabels_ = getctrl("mrs_natural/nLabels");
00050   ctrl_selectLabel_ = getctrl("mrs_string/selectLabel");
00051   ctrl_advance_ = getctrl("mrs_natural/advance");
00052   ctrl_pos_ = getctrl("mrs_natural/pos");
00053   ctrl_playRegionsOnly_ = getctrl("mrs_bool/playRegionsOnly");
00054   ctrl_useLexicon_ = getctrl("mrs_bool/useLexicon");
00055 
00056 
00057 
00058   labelFiles_ = ",";
00059   numClasses_ = 0;
00060   selectedLabel_ = "init";
00061   curRegion_ = 0;
00062   foundNextRegion_ = false;
00063   noLabelFile_ = false;
00064   myAdvance_ = false;
00065 }
00066 
00067 TimelineLabeler::~TimelineLabeler()
00068 {
00069 }
00070 
00071 MarSystem*
00072 TimelineLabeler::clone() const
00073 {
00074   return new TimelineLabeler(*this);
00075 }
00076 
00077 void
00078 TimelineLabeler::addControls()
00079 {
00080   addctrl("mrs_string/labelFiles", ",", ctrl_labelFiles_);
00081   ctrl_labelFiles_->setState(true);
00082 
00083   addctrl("mrs_real/currentLabelFile", 0.0, ctrl_currentLabelFile_);
00084   ctrl_currentLabelFile_->setState(true);
00085 
00086   addctrl("mrs_string/selectLabel", "", ctrl_selectLabel_);
00087   ctrl_selectLabel_->setState(true);
00088 
00089   addctrl("mrs_natural/advance", 0, ctrl_advance_);
00090   addctrl("mrs_natural/pos", 0, ctrl_pos_);
00091 
00092   addctrl("mrs_bool/playRegionsOnly", true, ctrl_playRegionsOnly_);
00093   addctrl("mrs_bool/useLexicon", false, ctrl_useLexicon_);
00094   ctrl_useLexicon_->setState(true);
00095 
00096 
00097   addctrl("mrs_string/labelNames", ",", ctrl_labelNames_);
00098   addctrl("mrs_string/lexiconLabelNames", ",", ctrl_lexiconLabelNames_);
00099 
00100   addctrl("mrs_real/currentLabel", -1.0, ctrl_currentLabel_);
00101   addctrl("mrs_real/previousLabel", -1.0, ctrl_previousLabel_);
00102   addctrl("mrs_natural/nLabels", 0, ctrl_nLabels_);
00103   addctrl("mrs_natural/lexiconNLabels", 0, ctrl_lexiconNLabels_);
00104 }
00105 
00106 mrs_bool
00107 TimelineLabeler::load_next_region_file()
00108 {
00110   //load currentLabelFile into the internal timeline memory (if not already loaded)
00112   mrs_bool newTimeline = false;
00113   // round
00114   mrs_natural curLabelFile = (mrs_natural) (ctrl_currentLabelFile_->to<mrs_real>() + 0.5);
00115 
00116   if(curLabelFile < (mrs_natural)labelFilesVec_.size()) //sanity check to avoid out of boundaries in vector
00117   {
00118     mrs_string fname = labelFilesVec_[curLabelFile];
00120     // check this is a different label file than the one currently loaded
00122     if(fname != timeline_.filename() && fname != "" && !noLabelFile_)
00123     {
00124 
00125       //It is different - try to read the timeline into memory
00126 
00127 
00128       if(timeline_.load(fname,ctrl_lexiconLabelNames_->to<mrs_string>()))
00129       {
00130         timeline_.setSampleRate(israte_);
00131         newTimeline = true;
00132         //get the number of classes in the currently loaded timeline
00133         numClasses_ = (mrs_natural)timeline_.numClasses();
00134         ctrl_nLabels_->setValue(numClasses_, NOUPDATE);
00135 
00136         //get the labels of the classes in the currently loaded timeline
00137         ostringstream sstr;
00138         vector<mrs_string> classNames = timeline_.getRegionNames();
00139         for(mrs_natural i=0; i < numClasses_; ++i)
00140           sstr << classNames[i] << ",";
00141         ctrl_labelNames_->setValue(sstr.str(), NOUPDATE);
00142 
00143         curRegion_ = 0;
00144         foundNextRegion_ = true;
00145       }
00146       else //some problem occurred when reading the timeline file...
00147       {
00148         MRSWARN("TimelineLabeler::myUpdate() - error reading label file " << labelFilesVec_[(mrs_natural) (ctrl_currentLabelFile_->to<mrs_real>()+0.5)]);
00149         noLabelFile_ = true;
00150         numClasses_ = 0;
00151         ctrl_nLabels_->setValue(numClasses_, NOUPDATE);
00152         ctrl_labelNames_->setValue(",", NOUPDATE);
00153         timeline_.clear();
00154       }
00155     }
00156   }
00157   else //out of boundaries for labelFilesVec...
00158   {
00159     numClasses_ = 0;
00160     ctrl_nLabels_->setValue(numClasses_, NOUPDATE);
00161     ctrl_labelNames_->setValue(",", NOUPDATE);
00162     timeline_.clear();
00163   }
00164 
00165   return newTimeline;
00166 }
00167 
00168 void
00169 TimelineLabeler::myUpdate(MarControlPtr sender)
00170 {
00171 
00172   MRSDIAG("TimelineLabeler.cpp - TimelineLabeler:myUpdate");
00173 
00174   MarSystem::myUpdate(sender);
00175 
00177   //fill labelFilesVec with all timeline filenames
00179   mrs_string newLabelFiles = ctrl_labelFiles_->to<mrs_string>();
00180   if (newLabelFiles == EMPTYSTRING) {
00181     return;
00182   }
00183   if((labelFiles_ != newLabelFiles) && (newLabelFiles != "" || newLabelFiles != ","))
00184   {
00185     labelFiles_ = newLabelFiles;
00186     std::string::size_type i;
00187     labelFilesVec_.clear();
00188     while(newLabelFiles.length() != 0 )
00189     {
00190       i = newLabelFiles.find(",");
00191       labelFilesVec_.push_back(newLabelFiles.substr(0, i).c_str());
00192       newLabelFiles = newLabelFiles.substr(i+1 , newLabelFiles.length()-i-1);
00193     }
00194   }
00195 
00196   mrs_bool newTimeline = load_next_region_file();
00197 
00198   // override labelNames and nLabels using lexicon
00199   if (ctrl_useLexicon_->to<mrs_bool>())
00200   {
00201     ctrl_nLabels_->setValue(ctrl_lexiconNLabels_->to<mrs_natural>());
00202     ctrl_labelNames_->setValue(ctrl_lexiconLabelNames_->to<mrs_string>());
00203   }
00204 
00205 
00206   // ensure that the timeline has the right sr
00207   if(timeline_.setSampleRate(israte_)) {
00208     // something changed
00209     newTimeline = true;
00210   }
00211 
00212 
00214   // Fast forward to first region start sample, if set to do so
00216   if(timeline_.numRegions() > 0 &&
00217       ((ctrl_selectLabel_->to<mrs_string>() != selectedLabel_) || newTimeline))
00218   {
00219     selectedLabel_ = ctrl_selectLabel_->to<mrs_string>();
00220 
00221     if(ctrl_playRegionsOnly_->to<mrs_bool>())
00222     {
00223       //fast forward to the start of first region (which my not start at the
00224       //beginning of the audio file) with a label corresponding to the one specified
00225       //by ctrl_selectLabel_
00226       if(selectedLabel_ == "") //i.e. any label is accepted
00227       {
00228         //fast forward to first region in timeline
00229         ctrl_pos_->setValue(timeline_.regionStart(0)*timeline_.lineSize(), NOUPDATE);
00230         curRegion_ = 0;
00231         foundNextRegion_ = true;
00232       }
00233       else //look for the first region with the selected label...
00234       {
00235         curRegion_ = 0;
00236         foundNextRegion_ = true;
00237         for(mrs_natural i=0; i < timeline_.numRegions(); ++i)
00238         {
00239           if(timeline_.regionName(i) == selectedLabel_)
00240           {
00241             //fast forward to found region
00242             ctrl_pos_->setValue(timeline_.regionStart(i), NOUPDATE);
00243             curRegion_ = i;
00244             //foundNextRegion_ = true;
00245             break;
00246           }
00247         }
00248       }
00249     }
00250   }
00251 }
00252 
00253 void
00254 TimelineLabeler::myProcess(realvec& in, realvec& out)
00255 {
00256 
00257   //bypass audio input to output
00258   out = in;
00259 
00260   if (myAdvance_) {
00261     load_next_region_file();
00262   }
00263 
00264   if (noLabelFile_) {
00265     ctrl_currentLabel_->setValue(-2.0); //no labels defined...
00266     return;
00267   }
00268   if(timeline_.numRegions() == 0)
00269   {
00270     MRSWARN("TimelineLabeler::myProcess() - no regions/labels exist in loaded timeline: " << timeline_.filename());
00271     ctrl_currentLabel_->setValue(-2.0); //no labels defined...
00272     return;
00273   }
00274 
00275   timeline_.setSampleRate(israte_);
00276 
00277 
00278   //get the sample position in the audio file of the last sample in
00279   //current frame (as set by SoundFileSource)
00280   mrs_natural samplePos = ctrl_pos_->to<mrs_natural>();
00281 
00282   //get current region boundaries
00283   mrs_natural regionStart = timeline_.regionStart(curRegion_)*timeline_.lineSize(); //region start sample
00284   mrs_natural regionEnd = timeline_.regionEnd(curRegion_)*timeline_.lineSize(); //region end sample
00285 
00287   //check if this audio frame belongs to current region or to the next one
00288   //(i.e. if at least half of the current audio frame belongs to the current region)
00290   if(samplePos == 0)
00291     samplePos += inSamples_/2; //UGLY HACK because of the way SoundFileSource and CollectionFileSource are implemented...
00292   else
00293     samplePos -= inSamples_/2;
00294 
00295   //cout<<samplePos<<"\t"<<regionStart<<"\t"<<regionEnd<<"\t";
00296   //cout<<endl;
00297   if (samplePos >= regionStart && samplePos<= regionEnd)
00298   {
00299     if(timeline_.regionName(curRegion_) == selectedLabel_ ||
00300         selectedLabel_ == "" ||
00301         selectedLabel_ == "init")
00302     {
00303       ctrl_currentLabel_->setValue(timeline_.regionClass(curRegion_));
00304 
00305     }
00306     else
00307       ctrl_currentLabel_->setValue(-2.0);
00308 
00309     // prepare to move to the next region if the next sample
00310     // would fall outside of the current region
00311     if (samplePos + getctrl("mrs_natural/inSamples")->to<mrs_natural>()
00312         < regionEnd) {
00313       foundNextRegion_ = true;
00314       //cout<<endl;
00315       //ctrl_advance_->setValue(1, NOUPDATE);
00316     } else {
00317       //cout<<"trigger"<<endl;
00318 //          foundNextRegion_ = false;
00320       //look for the next region in this timeline
00322       if(selectedLabel_ == "" || selectedLabel_ == "init")//i.e. just move to next region, whatever label
00323         curRegion_++;
00324       else // look for and move to next region with a specific label
00325       {
00326         curRegion_++;
00327         while(timeline_.regionName(curRegion_)!= selectedLabel_ && curRegion_ < timeline_.numRegions())
00328         {
00329           curRegion_++;
00330         }
00331       }
00332       foundNextRegion_ = true;
00334       //check if we found a new/subsequent region in the current timeline...
00336       if(curRegion_ < timeline_.numRegions())
00337       {
00338         //yeap, we found a new region in the current timeline!
00339         //update region boundaries
00340         regionStart = timeline_.regionStart(curRegion_)*timeline_.lineSize(); //region start sample
00341         regionEnd = timeline_.regionEnd(curRegion_)*timeline_.lineSize(); //region end sample
00342 
00343         //check if current frame is inside the new current region
00344         if(samplePos >= regionStart && samplePos <= regionEnd)
00345         {
00346           //yes it is... just output its label
00347           ctrl_currentLabel_->setValue(timeline_.regionClass(curRegion_));
00348         }
00349         else //current frame not inside the new current window...
00350         {
00351           //...should we fast forward to the new region (at next tick)?
00352           if(ctrl_playRegionsOnly_->to<mrs_bool>())
00353           {
00354             //output silence (i.e. discard current frame, since most of it does not
00355             //belong to the now past region, neither to the now current, region...)
00356             //out.setval(0.0); //[?] should we play this frame as is or just output silence?!
00357 
00358             //fast forward to next region (at next tick)
00359             ctrl_pos_->setValue(regionStart);
00360           }
00361         }
00362       }
00363       else //no more regions in this timeline...
00364       {
00365         //Should we ask for another audiofile/timeline ot just play the current file till its end?
00366         if(ctrl_playRegionsOnly_->to<mrs_bool>())
00367         {
00368           //output silence (i.e. discard current frame, since most of it does not
00369           //belong to the now past region)
00370           //out.setval(0.0); //[?] should we play this frame as is or just output silence?!
00371 
00372         }
00373         //fast forward to next region (at next tick)
00374         ctrl_advance_->setValue(1);
00375         myAdvance_ = true;
00376       }
00377     }
00378   }
00379   else//out of the current region...
00380   {
00381     //check if next region was already found
00382     if(!foundNextRegion_)
00383     {
00385       //look for the next region in this timeline
00387       if(selectedLabel_ == "" || selectedLabel_ == "init")//i.e. just move to next region, whatever label
00388         curRegion_++;
00389       else // look for and move to next region with a specific label
00390       {
00391         curRegion_++;
00392         while(timeline_.regionName(curRegion_)!= selectedLabel_ && curRegion_ < timeline_.numRegions())
00393         {
00394           curRegion_++;
00395         }
00396       }
00397       foundNextRegion_ = true;
00398     }
00399 
00401     //check if we found a new/subsequent region in the current timeline...
00403     if(curRegion_ < timeline_.numRegions())
00404     {
00405       //yeap, we found a new region in the current timeline!
00406       //update region boundaries
00407       regionStart = timeline_.regionStart(curRegion_)*timeline_.lineSize(); //region start sample
00408       regionEnd = timeline_.regionEnd(curRegion_)*timeline_.lineSize(); //region end sample
00409 
00410       //check if current frame is inside the new current region
00411       if(samplePos >= regionStart && samplePos <= regionEnd)
00412       {
00413         //yes it is... just output its label
00414         ctrl_currentLabel_->setValue(timeline_.regionClass(curRegion_));
00415       }
00416       else //current frame not inside the new current window...
00417       {
00418         //...should we fast forward to the new region (at next tick)?
00419         if(ctrl_playRegionsOnly_->to<mrs_bool>())
00420         {
00421           //output silence (i.e. discard current frame, since most of it does not
00422           //belong to the now past region, neither to the now current, region...)
00423           //out.setval(0.0); //[?] should we play this frame as is or just output silence?!
00424 
00425           //fast forward to next region (at next tick)
00426           ctrl_pos_->setValue(regionStart);
00427         }
00428         //i.e. outside a region: signal that no label is defined for this audio frame
00429         ctrl_currentLabel_->setValue(-2.0);
00430       }
00431     }
00432     else //no more regions in this timeline...
00433     {
00434       //Should we ask for another audiofile/timeline ot just play the current file till its end?
00435       if(ctrl_playRegionsOnly_->to<mrs_bool>())
00436       {
00437         //output silence (i.e. discard current frame, since most of it does not
00438         //belong to the now past region)
00439         //out.setval(0.0); //[?] should we play this frame as is or just output silence?!
00440       }
00441       //fast forward to next region (at next tick)
00442       ctrl_advance_->setValue(1);
00443       myAdvance_ = true;
00444       ctrl_currentLabel_->setValue(-2.0); //i.e. no region/label defined for this audio frame
00445     }
00446   }
00447   //cout<<"\t"<<ctrl_advance_->to<mrs_natural>();
00448   //cout<<"\t"<<ctrl_currentLabel_->to<mrs_real>();
00449   //cout<<endl;
00450 }