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 "OnsetTimes.h" 00020 #include "common.h" 00021 #include <algorithm> 00022 00023 using namespace std; 00024 using namespace Marsyas; 00025 00026 OnsetTimes::OnsetTimes(mrs_string name):MarSystem("OnsetTimes", name) 00027 { 00028 addControls(); 00029 timeElapsed_ = 0; 00030 count_ = 0; 00031 lastInductionTime_ = 0; 00032 maxCount_ = 0; 00033 } 00034 00035 OnsetTimes::OnsetTimes(const OnsetTimes& a) : MarSystem(a) 00036 { 00037 // For any MarControlPtr in a MarSystem 00038 // it is necessary to perform this getctrl 00039 // in the copy constructor in order for cloning to work 00040 ctrl_n1stOnsets_ = getctrl("mrs_natural/n1stOnsets"); 00041 ctrl_lookAheadSamples_ = getctrl("mrs_natural/lookAheadSamples"); 00042 ctrl_nPeriods_ = getctrl("mrs_natural/nPeriods"); 00043 ctrl_inductionTime_ = getctrl("mrs_natural/inductionTime"); 00044 ctrl_accSize_ = getctrl("mrs_natural/accSize"); 00045 ctrl_tickCount_ = getctrl("mrs_natural/tickCount"); 00046 ctrl_triggerInduction_ = getctrl("mrs_bool/triggerInduction"); 00047 00048 count_ = a.count_; 00049 lastInductionTime_ = a.lastInductionTime_; 00050 triggerInduction_ = a.triggerInduction_; 00051 size_ = a.size_; 00052 maxCount_ = a.maxCount_; 00053 phasesRaw_ = a.phasesRaw_; 00054 } 00055 00056 OnsetTimes::~OnsetTimes() 00057 { 00058 } 00059 00060 MarSystem* 00061 OnsetTimes::clone() const 00062 { 00063 return new OnsetTimes(*this); 00064 } 00065 00066 void 00067 OnsetTimes::addControls() 00068 { 00069 //Add specific controls needed by this MarSystem. 00070 addctrl("mrs_natural/n1stOnsets", 1, ctrl_n1stOnsets_); 00071 setctrlState("mrs_natural/n1stOnsets", true); 00072 addctrl("mrs_natural/lookAheadSamples", 1, ctrl_lookAheadSamples_); 00073 addctrl("mrs_natural/nPeriods", 1, ctrl_nPeriods_); 00074 setctrlState("mrs_natural/nPeriods", true); 00075 addctrl("mrs_natural/inductionTime", -1, ctrl_inductionTime_); 00076 setctrlState("mrs_natural/inductionTime", true); 00077 addctrl("mrs_natural/accSize", -1, ctrl_accSize_); 00078 setctrlState("mrs_natural/accSize", true); 00079 addctrl("mrs_natural/tickCount", 0, ctrl_tickCount_); 00080 addctrl("mrs_bool/triggerInduction", false, ctrl_triggerInduction_); 00081 setctrlState("mrs_bool/triggerInduction", true); 00082 } 00083 00084 void 00085 OnsetTimes::myUpdate(MarControlPtr sender) 00086 { 00087 MRSDIAG("OnsetTimes.cpp - OnsetTimes:myUpdate"); 00088 n_ = ctrl_n1stOnsets_->to<mrs_natural>(); 00089 nPeriods_ = ctrl_nPeriods_->to<mrs_natural>(); 00090 00091 //if the nr of requested bpm hypotheses is bigger 00092 //than the requested phases we need to fill the rest of the vector with 00093 //0s -> to avoid crash in tempohypotheses Fanout 00094 size_ = 2 * max(n_, nPeriods_); 00095 setctrl("mrs_natural/onSamples", size_); 00096 00097 ctrl_onObservations_->setValue(1, NOUPDATE); 00098 ctrl_osrate_->setValue(ctrl_israte_, NOUPDATE); 00099 00100 inductionSize_ = ctrl_inductionTime_->to<mrs_natural>(); 00101 accSize_ = ctrl_accSize_->to<mrs_natural>(); 00102 triggerInduction_ = ctrl_triggerInduction_->to<mrs_bool>(); 00103 } 00104 00105 void 00106 OnsetTimes::delSurpassedOnsets() 00107 { 00108 //clean surpassed onsets given current induction window 00109 for (int i=0; i < n_; i++) 00110 { 00111 mrs_real onset = phasesRaw_(i); 00112 if(onset > 0) //ignore empty bins 00113 { 00114 //cout << "t: " << timeElapsed_ << "====> i: " << i << "-> " << onset << ";"; 00115 mrs_real onsetAdj = onset + (accSize_ - 1 - timeElapsed_); 00116 //if onset still inside current induction window (to be sure) 00117 if(onsetAdj < (accSize_ -1 - inductionSize_) || onsetAdj > (accSize_ - 1)) 00118 { 00119 //cout << "(" << onsetAdj << ") [" << (accSize_ -1 - inductionSize_) << "; " << (accSize_ - 1) << "]" << endl; 00120 phasesRaw_(i) = 0.0; //if not => delete onset 00121 maxCount_--; //subtract deleted values to realvec 00122 00123 if(count_ > maxCount_) //assure that count never surpasses maximum count (which may happen when one phase deleted) 00124 count_ = maxCount_; 00125 } 00126 //else cout << endl; 00127 } 00128 } 00129 00130 //cout << "UNSORTED RAW-> maxCount: " << maxCount_ << "; Count: " << count_ << endl; 00131 //for (int i=0; i < n_; i++) 00132 //{ 00133 // cout << i << "-> " << phasesRaw_(i) << "; "; 00134 //} 00135 00136 //sort the whole realvec in descending order to take eventual initial zeros 00137 sort(phasesRaw_.getData(), phasesRaw_.getData()+n_, greater<int>()); 00138 //sort back to ascending order 00139 sort(phasesRaw_.getData(), phasesRaw_.getData()+maxCount_); 00140 } 00141 00142 void 00143 OnsetTimes::myProcess(realvec& in, realvec& out) 00144 { 00145 //timeElapsed_ is constantly updated with the referee's next time frame 00146 timeElapsed_ = ctrl_tickCount_->to<mrs_natural>(); 00147 00148 //at every induction step -> update onset positions according to offset 00149 if(triggerInduction_) 00150 { 00151 00152 //cout << "OnTimes-> Induction at: " << timeElapsed_ << "; accSize: " << accSize_ << "; min: " 00153 // << (accSize_ -1 - inductionSize_) << "; max: " << (accSize_ - 1) << "; phS: " << phasesRaw_.getCols() << endl; 00154 00155 //cout << "BEGINING RAW-> maxCount: " << maxCount_ << "; Count: " << count_ << endl; 00156 //for (int i=0; i < n_; i++) 00157 //{ 00158 // cout << i << "-> " << phasesRaw_(i) << "; "; 00159 //} 00160 00161 00162 //delSurpassedOnsets(); 00163 00164 00165 //cout << "SORTED RAW-> maxCount: " << maxCount_ << "; Count: " << count_ << endl; 00166 //for (int i=0; i < n_; i++) 00167 //{ 00168 // cout << i << "-> " << phasesRaw_(i) << "; "; 00169 //} 00170 00171 00172 mrs_realvec phasesAdj(size_); 00173 //Adjust given phases (onsets) to current induction window: 00174 for (int i=0; i < n_; i++) 00175 { 00176 mrs_real onset = phasesRaw_(i); 00177 //cout << "O: " << onset << "; "; 00178 if(onset > 0) //ignore empty bins 00179 { 00180 //cout << "i: " << i << "-> " << onset << " ("; 00181 phasesAdj(0, (2*i)+1) = onset + (accSize_ - 1 - timeElapsed_); 00182 phasesAdj(0, 2*i) = 1.0; 00183 00184 //cout << "(" << phasesAdj(0, (2*i)+1) << "); "; 00185 } 00186 00187 } 00188 //cerr << endl; 00189 00190 //out = phasesAdj; 00191 00192 /* 00193 cout << "END-> maxCount: " << maxCount_ << endl; 00194 for (int i=0; i < n_; i++) 00195 { 00196 cout << i << "-> " << phasesAdj(0, (2*i)+1) << "; "; 00197 } 00198 */ 00199 out = phasesAdj; 00200 } 00201 00202 //cout << "OTime: " << timeElapsed_ << endl; 00203 00204 lookAhead_ = ctrl_lookAheadSamples_->to<mrs_natural>(); 00205 00206 mrs_natural inc = 0; //nr. of first ignored onsets 00207 if((timeElapsed_ - lookAhead_) > 0 && in(0,0) == 1.0) //avoid onset at frame 0 00208 { 00209 if(phasesRaw_.getCols() < n_) 00210 phasesRaw_.stretch(n_); 00211 00212 //cout << "count: " << count_ << "; inc: " << inc << "; n: " << n_ 00213 // << "; t-l: " << (timeElapsed_-lookAhead_) << "; PR: " << (phasesRaw_(0, (count_-inc-1)) + 5) << endl; 00214 //cout << "LOOKAHEAD: " << lookAhead_ << endl; 00215 //cout << "ONSET AT: " << timeElapsed_ << endl; 00216 //if task isn't still done && (first peak || peak distance at least 5 frames from last peak) 00217 //if(count_ == inc || (count_ > inc && count_ < n_ + inc && ((timeElapsed_-lookAhead_)+(accSize_-1 - inductionTime_)) > out(0, 2*(count_-inc)-1) + 5)) 00218 //if(count_ == inc || (count_ > inc && count_ < n_ + inc && ((timeElapsed_-lookAhead_)+(accSize_-1 - inductionSize_)) > out(0, 2*(count_-inc)-1) + 5)) 00219 if(count_ == inc || (count_ > inc && count_ < n_ + inc && ((timeElapsed_-lookAhead_) > phasesRaw_(0, (count_-inc-1)) + 5))) 00220 { 00221 //cout << "Out Last Arg: " << out(0, 2*(count_-inc)+1) << " Current Arg: " << timeElapsed_ - lookAhead_ << endl; 00222 //out(0, 2*(count_-inc)) = in(0,0); 00223 00224 //onsetTime equals to peakerTime within current induction step (curInductionTime_-lookAhead_) 00225 //+ difference between last point in the 00226 //accumulator/ShiftInput (accSize_-1) and the considered inductionTime 00227 //out(0, 2*(count_-inc)+1) = (timeElapsed_-lookAhead_)+(accSize_-1 - inductionSize_); 00228 //out(0, 2*(count_-inc)+1) = ((timeElapsed_-lastInductionTime_) - lookAhead_)+(accSize_-1 - inductionSize_); 00229 //out(0, 2*(count_-inc)+1) = (curInductionTime_-lookAhead_)+(accSize_-1 - inductionTime_); 00230 //out(0, 2*(count_-inc)+1) = ((timeElapsed_-lastInductionTime_) - lookAhead_) + (accSize_-1); 00231 //out(0, 2*(count_-inc)+1) = (timeElapsed_-lookAhead_); 00232 00233 //use phases_ realvec 00234 phasesRaw_(0, (count_-inc)) = (timeElapsed_-lookAhead_); 00235 00236 //cout << "t: " << timeElapsed_ << "|" << (timeElapsed_-lookAhead_) << "- " << ((((timeElapsed_-lookAhead_) * 512.0) - 512.0/2) / 44100.0) << "(" << count_ << ") Onset at: " << (timeElapsed_-lookAhead_)+(862-1 - inductionSize_) 00237 // << "(" << phasesRaw_(0, (count_-inc)) << ")" << endl; 00238 00239 count_++; 00240 if(count_ > maxCount_) //update maxCount for keeping max nr. of phases from all induction windows 00241 maxCount_ = count_; 00242 } 00243 else if(count_ >= n_) //if onsets' realvec is full and new onsets arrive check if the older onsets have already been surpassed 00244 { 00245 delSurpassedOnsets(); 00246 00247 //cout << "SORTED RAW-> maxCount: " << maxCount_ << "; Count: " << count_ << endl; 00248 //for (int i=0; i < n_; i++) 00249 //{ 00250 // cout << i << "-> " << phasesRaw_(i) << "; "; 00251 //} 00252 00253 //add new onset 00254 phasesRaw_(0, (count_-inc)) = (timeElapsed_-lookAhead_); 00255 00256 count_++; 00257 if(count_ > maxCount_) //update maxCount for keeping max nr. of phases from all induction windows 00258 maxCount_ = count_; 00259 } 00260 } 00261 }
1.5.6