Marsyas  0.5.0-beta1
/Users/jleben/code/marsyas/src/marsyas/TimeLine.cpp
Go to the documentation of this file.
00001 /*
00002 ** Copyright (C) 1998-2004 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 <marsyas/TimeLine.h>
00020 #include <marsyas/common_source.h>
00021 #include <cstddef>
00022 
00023 using namespace std;
00024 using namespace Marsyas;
00025 
00026 TimeLine::TimeLine()
00027 {
00028   srate_ = 22050.0;
00029   psrate_ = 0.0;
00030   lineSize_ = 0;
00031   size_ = 0;
00032   filename_ = "";
00033   numRegions_ = 0;
00034 }
00035 
00036 TimeLine::~TimeLine()
00037 {
00038 }
00039 
00040 void
00041 TimeLine::clear()
00042 {
00043   filename_ = "";
00044   srate_ = 22050.0;
00045   psrate_ = 0.0;
00046 
00047   lineSize_ = 0;
00048   size_ = 0;
00049   regions_.clear();
00050   numRegions_ = 0;
00051 }
00052 
00053 mrs_bool
00054 TimeLine::setSampleRate(mrs_real srate)
00055 {
00056   srate_ = srate;
00057 
00058   if ((srate_ != 22050.0)&&(srate_ != psrate_)) // not the default
00059   {
00060     // readjust
00061     for (mrs_natural i=0; i < numRegions_; ++i)
00062     {
00063       regions_[i].start = (mrs_natural) (regions_[i].start * (srate_ / 22050.0));
00064       regions_[i].end   = (mrs_natural) (regions_[i].end * (srate_ / 22050.0));
00065     }
00066     psrate_ = srate;
00067     return true;
00068   } else {
00069     return false;
00070   }
00071 
00072 }
00073 
00074 
00075 void
00076 TimeLine::regular(mrs_natural spacing, mrs_natural size, mrs_natural lineSize)
00077 {
00078   if (size_ != 0)
00079   {
00080     MRSERR("TimeLine::regular() - TimeLine has data already!");
00081     return;
00082   }
00083 
00084   size_ = size;
00085   mrs_natural reg_index = 0;
00086   mrs_natural i;
00087   lineSize_ = lineSize;
00088   if ((size_ % spacing) != 0)
00089     numRegions_ = (size_ / spacing) + 1;
00090   else
00091     numRegions_ = (size_ / spacing);
00092 
00093   for (i=0; i < numRegions_; ++i)
00094   {
00095     TimeRegion region;
00096     regions_.push_back(region);
00097   }
00098 
00099   for (i=0; i<size_; ++i)
00100   {
00101     if ((i % spacing) == 0)
00102     {
00103       if (reg_index > 0)
00104         regions_[reg_index-1].end = i-1;
00105       regions_[reg_index].start = i;
00106       regions_[reg_index].classId = 0;
00107       reg_index++;
00108     }
00109   }
00110   regions_[numRegions_-1].end = size_;
00111   regions_[reg_index-1].end = size_;
00112 }
00113 
00114 void
00115 TimeLine::segment(realvec segmentation, mrs_natural lineSize)
00116 {
00117   mrs_natural i;
00118   mrs_natural peakCount=0;
00119 
00120   if (size_ != 0)
00121   {
00122     MRSERR("TimeLine::scan() - TimeLine has data already!");
00123     return;
00124   }
00125 
00126   size_ = segmentation.getSize();
00127   for (i=0; i<size_; ++i)
00128   {
00129     if (segmentation(i) == 1)
00130       peakCount++;
00131   }
00132 
00133   numRegions_ = peakCount-1; //[?]
00134   lineSize_ = lineSize;
00135 
00136   for (i=0; i < numRegions_; ++i)
00137   {
00138     TimeRegion region;
00139     regions_.push_back(region);
00140   }
00141 
00142   mrs_natural reg_index = 0;
00143   for (i=0; i<size_; ++i)
00144   {
00145     if (segmentation(i) == 1) //[?]
00146     {
00147       if (reg_index > 0)
00148         regions_[reg_index-1].end = i;
00149       if (reg_index == peakCount -1)
00150         break;
00151       regions_[reg_index].start = i;
00152       regions_[reg_index].classId = 0;
00153       reg_index++;
00154     }
00155   }
00156 }
00157 
00158 mrs_natural
00159 TimeLine::numClasses() const
00160 {
00161   vector<mrs_natural> classes;
00162   bool found = false;
00163 
00164   for(mrs_natural i = 0; i < numRegions_; ++i)
00165   {
00166     found = false;
00167     //check if this region's class Id was already counted
00168     for(mrs_natural c = 0; c < (mrs_natural)classes.size(); ++c)
00169     {
00170       if(classes[c] == regions_[i].classId)
00171       {
00172         found = true;
00173         break;
00174       }
00175     }
00176     //if this is a new classId, count it
00177     if(!found)
00178       classes.push_back(regions_[i].classId);
00179   }
00180 
00181   return (mrs_natural)classes.size();
00182 }
00183 
00184 vector<mrs_string>
00185 TimeLine::getRegionNames() const
00186 {
00187   vector<mrs_string> classNames;
00188   bool found = false;
00189 
00190   for(mrs_natural i = 0; i < numRegions_; ++i)
00191   {
00192     found = false;
00193     //check if this region's class name was already considered
00194     for(mrs_natural c = 0; c < (mrs_natural)classNames.size(); ++c)
00195     {
00196       if(classNames[c] == regions_[i].name)
00197       {
00198         found = true;
00199         break;
00200       }
00201     }
00202     //if this is a new className, store it
00203     if(!found)
00204       classNames.push_back(regions_[i].name);
00205   }
00206 
00207   sort(classNames.begin(), classNames.end());
00208 
00209 
00210   return classNames;
00211 }
00212 
00213 mrs_natural
00214 TimeLine::regionStart(mrs_natural regionNum) const
00215 {
00216   if (regionNum < numRegions_)
00217     return regions_[regionNum].start;
00218   else return -1;
00219 }
00220 
00221 mrs_string
00222 TimeLine::regionName(mrs_natural regionNum) const
00223 {
00224   if (regionNum < numRegions_)
00225     return regions_[regionNum].name;
00226   else return "";
00227 }
00228 
00229 void
00230 TimeLine::setRegionName(mrs_natural regionNum, mrs_string name)
00231 {
00232   if (regionNum < numRegions_)
00233     regions_[regionNum].name = name;
00234 }
00235 
00236 void
00237 TimeLine::setRegionClass(mrs_natural regionNum, mrs_natural classId)
00238 {
00239   if (regionNum < numRegions_)
00240   {
00241     regions_[regionNum].classId = classId;
00242   }
00243 }
00244 
00245 mrs_natural
00246 TimeLine::regionEnd(mrs_natural regionNum) const
00247 {
00248   if (regionNum < numRegions_)
00249     return regions_[regionNum].end;
00250   else return -1;
00251 }
00252 
00253 void
00254 TimeLine::smooth(mrs_natural smoothSize) //[?]
00255 {
00256   TimeRegion region;
00257   TimeRegion pregion;
00258   TimeRegion nregion;
00259 
00260   for (int i=1; i < numRegions_-1; ++i)
00261   {
00262     region = regions_[i];
00263     pregion = regions_[i-1];
00264     nregion = regions_[i+1];
00265 
00266     if ((region.end - region.start < smoothSize) && (region.classId == 1))
00267     {
00268       // if ((pregion.end - pregion.start) > (nregion.end - nregion.start))
00269       // {
00270       removeRegion(i);
00271       i = i-1;
00272       // }
00273       // else
00274       // remove(i+1);
00275     }
00276   }
00277 
00278   for (mrs_natural i=1; i < numRegions_; ++i)
00279   {
00280     region = regions_[i];
00281     pregion = regions_[i-1];
00282 
00283     if (region.classId == pregion.classId)
00284     {
00285       removeRegion(i);
00286       i = i-1;
00287     }
00288   }
00289 }
00290 
00291 void
00292 TimeLine::removeRegion(mrs_natural regionNum)
00293 {
00294   if (regionNum >= 1)
00295   {
00296     regions_[regionNum-1].end = regions_[regionNum].end;
00297     regions_.erase(regions_.begin() + regionNum);
00298     numRegions_--;
00299   }
00300 }
00301 
00302 mrs_real
00303 TimeLine::regionClass(mrs_natural regionNum) const
00304 {
00305 
00306 
00307   if (regionNum < numRegions_)
00308     return regions_[regionNum].classId;
00309   else
00310     return 0;
00311 }
00312 
00313 mrs_natural
00314 TimeLine::sampleClass(mrs_natural index) const
00315 {
00316   TimeRegion region;
00317   for (mrs_natural i=0; i < numRegions_; ++i)
00318   {
00319     region = regions_[i];
00320     if ((region.start <= index) && (index < region.end))
00321     {
00322       return region.classId;
00323     }
00324   }
00325   return 0;
00326 }
00327 
00328 bool
00329 TimeLine::load(mrs_string filename, mrs_string lexicon_labels)
00330 {
00331 
00332   ifstream in;
00333   filename_ = filename;
00334 
00335   if(filename == "")
00336     return false;
00337 
00338   in.open(filename.c_str());
00339   if(!in.is_open())
00340   {
00341     MRSWARN("TimeLine::load() -  Problem opening file " << filename_);
00342     return false;
00343   }
00344 
00345   FileName f(filename);
00346   vector<mrs_string> labels;
00347 
00348 
00349 
00350   // Load lexicon dictionary if available
00351   mrs_string lexicon_label;
00352   mrs_string remainder;
00353   size_t nLabels;
00354 
00355   nLabels = std::count(lexicon_labels.begin(), lexicon_labels.end(), ',');
00356 
00357   if (lexicon_labels != ",")
00358   {
00359     for (size_t i=0; i < nLabels; i++)
00360     {
00361       lexicon_label = lexicon_labels.substr(0, lexicon_labels.find(","));
00362       labels.push_back(lexicon_label);
00363       sort(labels.begin(), labels.end());
00364       remainder = lexicon_labels.substr(lexicon_labels.find(",") + 1, lexicon_labels.length());
00365       lexicon_labels = remainder;
00366     }
00367   }
00368   else
00369     nLabels = 0;
00370 
00371 
00372   if (f.ext() == "txt") // audacity label format
00373   {
00374     numRegions_ = 0;
00375     mrs_real start, end;
00376     mrs_string label;
00377     regions_.clear();
00378     while (!in.eof())
00379     {
00380       in >> start >> end >> label;
00381 
00382 
00383       TimeRegion region;
00384       region.start = (mrs_natural) (start * srate_);
00385       region.end = (mrs_natural) (end * srate_);
00386       region.classId = 1;
00387       region.name = label;
00388       mrs_bool label_found = false;
00389 
00390       for (unsigned int i=0; i < labels.size(); i++)
00391       {
00392         if (label == labels[i])
00393         {
00394           label_found = true;
00395           region.classId = i;
00396         }
00397 
00398       }
00399       if (!label_found)
00400       {
00401 
00402         if (lexicon_labels == ",")
00403         {
00404           labels.push_back(label);
00405           sort(labels.begin(), labels.end());
00406         }
00407       }
00408       regions_.push_back(region);
00409       numRegions_ ++;
00410     }
00411 
00412 
00413 
00414 
00415     // relabel classIds so that they correspond to sorted labels
00416     for (mrs_natural i=0; i < numRegions_; ++i)
00417     {
00418       mrs_string label = regions_[i].name;
00419       vector<mrs_string>::iterator it = find(labels.begin(), labels.end(), label);
00420       if (it == labels.end())
00421         regions_[i].classId = (mrs_natural)-1;
00422       mrs_natural l = distance(labels.begin(), it);
00423       regions_[i].classId = l;
00424     }
00425 
00426 
00427     // last region is a duplicate due to empty last line
00428     // kind of a hack but works
00429     numRegions_ --;
00430     regions_.pop_back();
00431 
00432 
00433     lineSize_ = 1;
00434     size_ = (mrs_natural) (end * srate_);
00435 
00436     in.close();
00437     return true;
00438   }
00439   else     // marsyas .mtl format
00440   {
00441     in >> numRegions_; // read numRegions
00442     MRSDIAG("TimeLine::load() - Number of regions is " << numRegions_);
00443 
00444     in >> lineSize_; //read lineSize
00445     MRSDIAG("TimeLine::load() - lineSize size is " << lineSize_);
00446 
00447     in >> size_; //read size
00448     MRSDIAG("TimeLine::load() - Size is " << size_);
00449 
00450     regions_.clear();
00451     for (mrs_natural i=0; i < numRegions_; ++i)
00452     {
00453       TimeRegion region;
00454       regions_.push_back(region);
00455     }
00456 
00457     for (mrs_natural i=0; i<numRegions_; ++i)
00458     {
00459       mrs_natural token;
00460       mrs_string stoken1, stoken2;
00461       in >> token;
00462       regions_[i].start = token;
00463       in >> token;
00464       regions_[i].classId = token;
00465       in >> token;
00466       regions_[i].end = token;
00467       in >> stoken1;// >> stoken2; //used for .cue files in IEEE TASLP paper...
00468       //regions_[i].name = stoken1 +" "+stoken2; //used for .cue files in IEEE TASLP paper...
00469       regions_[i].name = stoken1;
00470     }
00471 
00472     in.close();
00473 
00474     return true;
00475 
00476   }
00477 
00478 }
00479 
00480 void
00481 TimeLine::info() const
00482 {
00483   mrs_natural i;
00484   MRSMSG("Number of regions = " << numRegions_ << endl);
00485   MRSMSG("Line size  = " << lineSize_ << endl);
00486   MRSMSG("TimeLine size (# line size blocks ) = " << size_ << endl);
00487 
00488   for (i=0; i < numRegions_; ++i)
00489   {
00490     MRSMSG("--------------------------------------------" << endl);
00491     MRSMSG("Region " << i << " start    = " << regions_[i].start << endl);
00492     MRSMSG("Region " << i << " class id = " << regions_[i].classId << endl);
00493     MRSMSG("Region " << i << " name     = " << regions_[i].name << endl);
00494     MRSMSG("Region " << i << " end      = " << regions_[i].end   << endl);
00495   }
00496 }
00497 
00498 void
00499 TimeLine::printnew(FILE *fp)
00500 {
00501   mrs_natural i;
00502   fprintf(fp, "%d\n", (int)numRegions_);
00503   fprintf(fp, "%d\n", (int)lineSize_);
00504   fprintf(fp, "%d\n", (int)size_);
00505 
00506   for (i=0; i<numRegions_; ++i)
00507   {
00508     // convert to milliseconds
00509     float smsec;
00510     float emsec;
00511     smsec = (float) ((regions_[i].start * lineSize_ * 1000) / srate_);
00512     // fprintf(fp, "%d ", regions_[i].start);
00513     fprintf(fp, "%6.0f ", smsec);
00514 
00515     fprintf(fp, "%d ", (int)regions_[i].classId);
00516     emsec = (float) ((regions_[i].end * lineSize_ * 1000) / srate_);
00517     // fprintf(fp, "%d ", regions_[i].end);
00518     fprintf(fp, "%6.0f\n", emsec);
00519 
00520     fprintf(fp, "%s\n", regions_[i].name.c_str());
00521   }
00522 }
00523 
00524 void
00525 TimeLine::write(mrs_string filename)
00526 {
00527   ofstream os(filename.c_str());
00528   os << (*this) << endl;
00529 }
00530 
00531 namespace Marsyas {
00532 ostream&
00533 operator<<(ostream& o, const TimeLine& tline)
00534 {
00535   o << tline.numRegions_ << endl;
00536   o << tline.lineSize_ << endl;
00537   o << tline.size_ << endl;
00538 
00539   for (mrs_natural i=0; i<tline.numRegions_; ++i)
00540   {
00541     o << tline.regions_[i].start ;
00542     o << " " << tline.regions_[i].classId;
00543     o << " " << tline.regions_[i].end << endl;
00544     o << "Region " << i+1 << endl;
00545   }
00546   return o;
00547 }
00548 }
00549 
00550 void
00551 TimeLine::print(FILE *fp)
00552 {
00553   mrs_natural i;
00554   fprintf(fp, "%d\n", (int) numRegions_);
00555   fprintf(fp, "%d\n", (int)lineSize_);
00556   fprintf(fp, "%d\n", (int)size_);
00557 
00558   for (i=0; i<numRegions_; ++i)
00559   {
00560     fprintf(fp, "%d ", (int)regions_[i].start);
00561     fprintf(fp, "%d ", (int)regions_[i].classId);
00562     fprintf(fp, "%d\n", (int)regions_[i].end);
00563     fprintf(fp, "Region %d\n", (int)i+1);
00564   }
00565 }
00566 
00567 /*
00568 void
00569 TimeLine::print_mp3(FILE *fp)
00570 {
00571 verbose("TimeLine::print(FILE *fp)");
00572 int i;
00573 float ratio = 576.0 / 512.0;
00574 
00575 fprintf(fp, "%d\n", num_of_regions_);
00576 fprintf(fp, "%d\n", skip_size_);
00577 fprintf(fp, "%d\n", (int)(size_ * ratio));
00578 
00579 for (i=0; i<num_of_regions_; ++i)
00580 {
00581 fprintf(fp, "%d ", (int)(region_[i].start *ratio));
00582 fprintf(fp, "%d ", region_[i].class_id);
00583 fprintf(fp, "%d\n", (int)(region_[i].end *ratio));
00584 fprintf(fp, "Region %d\n", i+1);
00585 }
00586 
00587 }
00588 */
00589 
00590 /*
00591 void
00592 TimeLine::print_mmf(FILE *fp)
00593 {
00594 int i;
00595 float ratio = 576.0 / 512.0;
00596 
00597 fprintf(fp,"# Feature map information file written by MARSYAS\n");
00598 fprintf(fp,"Segment\n");
00599 fprintf(fp,"#Number of features and number of different classes\n");
00600 fprintf(fp,"%d %d\n", num_of_regions_, 0);
00601 fprintf(fp, "#Names of features\n");
00602 for (i=0; i<num_of_regions_; ++i)
00603 fprintf(fp,"f%d ", i);
00604 fprintf(fp,"\n\n");
00605 fprintf(fp,"#Name of classes\n");
00606 fprintf(fp,"\n\n");
00607 
00608 fprintf(fp,"#Number of feature float_vectors \n");
00609 fprintf(fp,"1\n");
00610 fprintf(fp,"#Feature map data\n");
00611 fprintf(fp,"\n");
00612 
00613 
00614 for (i=0; i<num_of_regions_; ++i)
00615 {
00616 fprintf(fp, "%f ", region_[i].end * ratio - region_[i].start *ratio );
00617 }
00618 fprintf(fp," 0\n\n");
00619 }
00620 */
00621 
00622 void
00623 TimeLine::receive(Communicator* com)
00624 {
00625   static char *buf = new char[256];
00626   mrs_natural i;
00627   mrs_string message;
00628 
00629   com->receive_message(buf);
00630   // message = buf;
00631   numRegions_ = atoi(buf);
00632 
00633   com->receive_message(buf);
00634 
00635   lineSize_ = atoi(buf);
00636 
00637   com->receive_message(buf);
00638   size_ = atoi(buf);
00639 
00640   for (i=0; i < numRegions_; ++i)
00641   {
00642     com->receive_message(buf);
00643   }
00644 }
00645 
00646 void
00647 TimeLine::send(Communicator* com)
00648 {
00649   static char *buf = new char[256];
00650   mrs_natural i;
00651   mrs_string message;
00652 
00653   sprintf(buf, "%d\n", (int)numRegions_);
00654   message = buf;
00655   com->send_message(message);
00656 
00657   sprintf(buf, "%d\n", (int)lineSize_);
00658   message = buf;
00659   com->send_message(message);
00660 
00661   sprintf(buf, "%d\n", (int)size_);
00662   message = buf;
00663   com->send_message(message);
00664 
00665   for (i=0; i<numRegions_; ++i)
00666   {
00667     sprintf(buf, "%d ", (int)regions_[i].start);
00668     message = buf;
00669     com->send_message(message);
00670 
00671     sprintf(buf, "%d ", (int)regions_[i].classId);
00672     message = buf;
00673     com->send_message(message);
00674 
00675     /*sprintf(buf, "%f ", region_[i].color.getR());
00676     message = buf;
00677     com->send_message(message);
00678 
00679     sprintf(buf, "%f ", region_[i].color.getG());
00680     message = buf;
00681     com->send_message(message);
00682 
00683     sprintf(buf, "%f ", region_[i].color.getB());
00684     message = buf;
00685     com->send_message(message);
00686 
00687     */
00688 
00689     sprintf(buf, "%d\n", (int)regions_[i].end);
00690     message = buf;
00691     com->send_message(message);
00692 
00693     sprintf(buf, "Region %d\n", (int)i);
00694     message = buf;
00695     com->send_message(message);
00696   }
00697 }
00698 
00699 /*
00700 void
00701 TimeLine::color(Feature_map &map)
00702 {
00703 int i;
00704 float_vector f1 = map.get_feat(9);
00705 float_vector f2 = map.get_feat(0);
00706 float_vector f3 = map.get_feat(3);
00707 float r;
00708 float g;
00709 float b;
00710 
00711 Gen_Plotter plotter;
00712 //f1.norm(0.5, 0.2);
00713 //f2.norm(0.5, 0.2);
00714 //f3.norm(0.5, 0.2);
00715 
00716 f1.norm(0.00074, 0.0017, 0.5, 0.2);
00717 f2.norm(40.5, 20.5, 0.5, 0.2);
00718 f3.norm(5.63, 2.71, 0.5, 0.2);
00719 
00720 //plotter.plot_wait(f1);
00721 //plotter.plot_wait(f2);
00722 //plotter.plot_wait(f3);
00723 
00724 int start;
00725 int end;
00726 for (i=0; i<num_of_regions_; ++i)
00727 {
00728 start = region_[i].start;
00729 end = region_[i].end;
00730 r = fabs(f1.mean(start,end));
00731 g = fabs(f2.mean(start,end));
00732 b = fabs(f3.mean(start,end));
00733 
00734 //r = 0.5;
00735 //g = 0.5;
00736 //b = 0.5;
00737 
00738 // Clip to colors
00739 if (r > 1.0) r = 1.0;
00740 if (g > 1.0) g = 1.0;
00741 if (b > 1.0) b = 1.0;
00742 if (r < 0.0) r = 0.0;
00743 if (g < 0.0) g = 0.0;
00744 if (b < 0.0) b = 0.0;
00745 
00746 region_[i].color.setRGB(r,g,b);
00747 }
00748 
00749 }
00750 */