Marsyas
0.6.0-alpha
|
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 */