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