Marsyas
0.6.0-alpha
|
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 }