00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "BeatPhase.h"
00020
00021 using std::ostringstream;
00022 using std::cout;
00023 using std::endl;
00024
00025 using namespace Marsyas;
00026
00027 BeatPhase::BeatPhase(mrs_string name):MarSystem("BeatPhase", name)
00028 {
00029 addControls();
00030 sampleCount_ = 0;
00031 current_beat_location_ = 0.0;
00032 pinSamples_ = 0;
00033
00034
00035 }
00036
00037 BeatPhase::BeatPhase(const BeatPhase& a) : MarSystem(a)
00038 {
00039 ctrl_tempo_candidates_ = getctrl("mrs_realvec/tempo_candidates");
00040
00041 ctrl_tempos_ = getctrl("mrs_realvec/tempos");
00042 ctrl_temposcores_ = getctrl("mrs_realvec/tempo_scores");
00043 ctrl_phase_tempo_ = getctrl("mrs_real/phase_tempo");
00044 ctrl_ground_truth_tempo_ = getctrl("mrs_real/ground_truth_tempo");
00045 ctrl_beats_ = getctrl("mrs_realvec/beats");
00046 ctrl_bhopSize_ = getctrl("mrs_natural/bhopSize");
00047 ctrl_bwinSize_ = getctrl("mrs_natural/bwinSize");
00048 ctrl_timeDomain_ = getctrl("mrs_realvec/timeDomain");
00049 ctrl_nCandidates_ = getctrl("mrs_natural/nCandidates");
00050 ctrl_beatOutput_ = getctrl("mrs_realvec/beatOutput");
00051
00052 sampleCount_ = 0;
00053 current_beat_location_ = 0.0;
00054 pinSamples_ = 0;
00055
00056 }
00057
00058 BeatPhase::~BeatPhase()
00059 {
00060 }
00061
00062 MarSystem*
00063 BeatPhase::clone() const
00064 {
00065 return new BeatPhase(*this);
00066 }
00067
00068 void
00069 BeatPhase::addControls()
00070 {
00071 mrs_natural nCandidates = 8;
00072
00073
00074 addctrl("mrs_realvec/tempo_candidates", realvec(nCandidates), ctrl_tempo_candidates_);
00075 addctrl("mrs_realvec/tempos", realvec(nCandidates), ctrl_tempos_);
00076 addctrl("mrs_realvec/tempo_scores", realvec(nCandidates), ctrl_temposcores_);
00077
00078 addctrl("mrs_real/phase_tempo", 100.0, ctrl_phase_tempo_);
00079 addctrl("mrs_real/ground_truth_tempo", 100.0, ctrl_ground_truth_tempo_);
00080 addctrl("mrs_realvec/beats", realvec(), ctrl_beats_);
00081 addctrl("mrs_natural/bhopSize", 64, ctrl_bhopSize_);
00082 addctrl("mrs_natural/bwinSize", 1024, ctrl_bwinSize_);
00083 addctrl("mrs_realvec/timeDomain", realvec(), ctrl_timeDomain_);
00084 addctrl("mrs_natural/nCandidates", nCandidates, ctrl_nCandidates_);
00085 setctrlState("mrs_natural/nCandidates", true);
00086 addctrl("mrs_realvec/beatOutput", realvec(), ctrl_beatOutput_);
00087 }
00088
00089 void
00090 BeatPhase::myUpdate(MarControlPtr sender)
00091 {
00092
00093 MarSystem::myUpdate(sender);
00094
00095
00096 inSamples_ = getctrl("mrs_natural/inSamples")->to<mrs_natural>();
00097 mrs_natural nCandidates = getctrl("mrs_natural/nCandidates")->to<mrs_natural>();
00098
00099 MarControlAccessor acc_t(ctrl_tempos_);
00100 mrs_realvec& tempos = acc_t.to<mrs_realvec>();
00101 tempos.stretch(nCandidates);
00102
00103 MarControlAccessor acc_ts(ctrl_temposcores_);
00104 mrs_realvec& temposcores = acc_ts.to<mrs_realvec>();
00105 temposcores.stretch(nCandidates);
00106
00107 MarControlAccessor acc_tc(ctrl_tempo_candidates_);
00108 mrs_realvec& tempocandidates = acc_tc.to<mrs_realvec>();
00109 tempocandidates.stretch(nCandidates * 2);
00110
00111
00112
00113 if (pinSamples_ != inSamples_)
00114 {
00115 {
00116 MarControlAccessor acc(ctrl_beats_);
00117 mrs_realvec& beats = acc.to<mrs_realvec>();
00118 beats.create(inSamples_);
00119
00120
00121 MarControlAccessor beatOutputAcc(ctrl_beatOutput_);
00122 mrs_realvec& beatOutput = beatOutputAcc.to<mrs_realvec>();
00123 beatOutput.create(inSamples_);
00124 }
00125 }
00126
00127 pinSamples_ = inSamples_;
00128
00129
00130
00131 }
00132
00133
00134 void
00135 BeatPhase::myProcess(realvec& in, realvec& out)
00136 {
00137 mrs_natural o,t;
00138
00139
00140
00141
00142
00143
00144
00145
00146 MarControlAccessor acctc(ctrl_tempo_candidates_);
00147 mrs_realvec& tempo_candidates = acctc.to<mrs_realvec>();
00148
00149
00150 MarControlAccessor acct(ctrl_tempos_);
00151 mrs_realvec& tempos = acct.to<mrs_realvec>();
00152 MarControlAccessor accts(ctrl_temposcores_);
00153 mrs_realvec& tempo_scores = accts.to<mrs_realvec>();
00154
00155
00156
00157 for (int i=0; i < tempo_candidates.getSize()/2; i++)
00158 {
00159 tempos(i) = 0.25 * tempo_candidates(2*i+1);
00160 tempo_scores(i) = tempo_candidates(2*i);
00161 }
00162
00163
00164 tempo_scores /= tempo_scores.sum();
00165
00166
00167 mrs_realvec onset_scores;
00168 onset_scores.create(tempo_scores.getSize());
00169
00170 mrs_realvec tempo_phases;
00171 tempo_phases.create(tempo_scores.getSize());
00172
00173
00174 for (int k=0; k < tempos.getSize(); k++)
00175 {
00176 if (tempos(k) < 50.0)
00177 tempos(k) = 0;
00178 if (tempos(k) > 200)
00179 tempos(k) = 0;
00180
00181 }
00182
00183
00184
00185
00186 mrs_natural bhopSize = ctrl_bhopSize_->to<mrs_natural>();
00187
00188 MarControlAccessor acc(ctrl_beats_);
00189 mrs_realvec& beats = acc.to<mrs_realvec>();
00190
00191
00192 for (o=0; o < inObservations_; o++)
00193 {
00194 for (t = 0; t < inSamples_; t++)
00195 {
00196 out (o,t) = in(o,t);
00197 beats (o,t) = 0.0;
00198 }
00199 }
00200
00201 mrs_real tempo;
00202 mrs_real period;
00203 mrs_natural phase;
00204 mrs_real cross_correlation = 0.0;
00205 mrs_real max_crco=0.0;
00206 mrs_natural max_phase = 0.0;
00207 mrs_realvec phase_correlations;
00208
00209
00210
00211
00212
00213
00214
00215
00216 for (o=0; o < inObservations_; o++)
00217 {
00218 for (int k=0; k < tempos.getSize(); k++)
00219 {
00220 max_crco = 0.0;
00221
00222 tempo = tempos(k);
00223 if (tempo >= 50)
00224 period = 2.0 * osrate_ * 60.0 / tempo;
00225 else
00226 period = 0;
00227 period = (mrs_natural)(period+0.5);
00228
00229
00230
00231 if (period > 1.0)
00232 {
00233 phase_correlations.create(period);
00234
00235 for (phase=inSamples_-1; phase > inSamples_-1-period; phase--)
00236 {
00237 cross_correlation = 0.0;
00238
00239 for (int b=0; b < 4; b++)
00240 {
00241 cross_correlation += in(o,phase - b * period);
00242 cross_correlation += 0.65 * in(o,phase - b * 1.5 * period);
00243 if ((b == 0) || (b == 2))
00244 cross_correlation += 0.5 * in(o,phase - b * period);
00245 }
00246 phase_correlations(inSamples_-1-phase) = cross_correlation;
00247 if (cross_correlation > max_crco)
00248 {
00249 max_crco = cross_correlation;
00250 max_phase = phase;
00251 }
00252
00253 }
00254 onset_scores(k) = phase_correlations.var();
00255 tempo_scores(k) = max_crco;
00256 tempo_phases(k) = max_phase;
00257 beats.setval(0.0);
00258 }
00259 }
00260 }
00261
00262
00263
00264 onset_scores /= onset_scores.sum();
00265 tempo_scores /= tempo_scores.sum();
00266
00267
00268 for (int i=0; i < tempo_scores.getSize(); i++)
00269 tempo_scores(i) = onset_scores(i) + tempo_scores(i);
00270
00271
00272 tempo_scores /= tempo_scores.sum();
00273
00274
00275
00276 mrs_real max_score = 0.0;
00277 int max_i=0;
00278 for (int i= 0; i < tempos.getSize(); i++)
00279 {
00280 if (tempo_scores(i) > max_score)
00281 {
00282 max_score = tempo_scores(i);
00283 max_i = i;
00284 }
00285 }
00286
00287
00288
00289
00290 tempos(0) = tempos(max_i);
00291 tempo_scores(0) = tempo_scores(max_i);
00292 ctrl_phase_tempo_->setValue(tempos(max_i));
00293
00294
00295
00296 tempo = tempos(max_i);
00297 if (tempo < 75.0)
00298 tempo = tempo * 2;
00299 mrs_real beat_length = 60.0 / tempo;
00300
00301 if (tempo >= 50)
00302 period = 2.0 * osrate_ * 60.0 / tempo;
00303 else
00304 period = 0;
00305
00306 period = (mrs_natural)(period+0.5);
00307
00308 for (int b=0; b < 4; b++)
00309 beats(0,tempo_phases(max_i) - b * period) = -0.5;
00310
00311
00312 mrs_natural prev_sample_count;
00313 prev_sample_count = sampleCount_;
00314
00315
00316 int total_beats = 0;
00317 MarControlAccessor beatOutputAcc(ctrl_beatOutput_);
00318 mrs_realvec& beatOutput = beatOutputAcc.to<mrs_realvec>();
00319 for (t = 0; t < inSamples_; t++)
00320 {
00321 beatOutput(t) = 0.0;
00322 }
00323
00324
00325 mrs_real beat_location;
00326 for (int t = inSamples_-1-2*bhopSize; t < inSamples_; t++)
00327 {
00328 if (beats(0,t) == -0.5)
00329 {
00330 beat_location = (sampleCount_ + t -(inSamples_-1 -bhopSize)) / (2.0 * osrate_);
00331 if ((beat_location > current_beat_location_)&&((beat_location - current_beat_location_) > beat_length * 0.75))
00332 {
00333 if (ctrl_verbose_->isTrue())
00334 MRSMSG(beat_location << "\t"
00335 << beat_location + 0.02 << " b");
00336 beatOutput(total_beats) = beat_location;
00337 current_beat_location_ = beat_location;
00338 total_beats++;
00339 }
00340 }
00341 }
00342 sampleCount_ += bhopSize;
00343 }