00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "AubioYin.h"
00020
00021 using std::ostringstream;
00022 using namespace Marsyas;
00023
00024 AubioYin::AubioYin(mrs_string name):MarSystem("AubioYin", name)
00025 {
00026 addControls();
00027 }
00028
00029 AubioYin::AubioYin(const AubioYin& a) : MarSystem(a)
00030 {
00031 ctrl_tolerance_ = getctrl("mrs_real/tolerance");
00032 }
00033
00034
00035 AubioYin::~AubioYin()
00036 {
00037 }
00038
00039 MarSystem*
00040 AubioYin::clone() const
00041 {
00042 return new AubioYin(*this);
00043 }
00044
00045 void
00046 AubioYin::addControls()
00047 {
00048
00049
00050 addctrl("mrs_real/tolerance", 0.15, ctrl_tolerance_);
00051
00052 }
00053
00054 void
00055 AubioYin::myUpdate(MarControlPtr sender)
00056 {
00057 MRSDIAG("AubioYin.cpp - AubioYin:myUpdate");
00058
00059 MarSystem::myUpdate(sender);
00060
00061 ctrl_onSamples_->setValue(1, NOUPDATE);
00062 ctrl_onObservations_->setValue(ctrl_inObservations_, NOUPDATE);
00063 ctrl_osrate_->setValue(ctrl_israte_, NOUPDATE);
00064 ctrl_onObsNames_->setValue(ctrl_inObsNames_, NOUPDATE);
00065
00066 }
00067
00068 double AubioYin::aubio_quadfrac(double s0, double s1, double s2, double pf) {
00069 double tmp = s0 + (pf/2.) * (pf * ( s0 - 2.*s1 + s2 ) - 3.*s0 + 4.*s1 - s2);
00070 return tmp;
00071 }
00072
00073 double AubioYin::vec_quadint_min(realvec *x,unsigned int pos, unsigned int span) {
00074 double step = 1./200.;
00075
00076 double res, frac, s0, s1, s2, exactpos = (double)pos, resold = 100000.;
00077 if ((pos > span) && (pos < x->getSize()-span)) {
00078 s0 = (*x)(0,pos-span);
00079 s1 = (*x)(0,pos);
00080 s2 = (*x)(0,pos+span);
00081
00082 for (frac = 0.; frac < 2.; frac = frac + step) {
00083 res = AubioYin::aubio_quadfrac(s0, s1, s2, frac);
00084 if (res < resold) {
00085 resold = res;
00086 } else {
00087 exactpos += (frac-step)*span - span/2.;
00088 break;
00089 }
00090 }
00091 }
00092 return exactpos;
00093 }
00094
00095 unsigned int AubioYin::vec_min_elem(realvec *s)
00096 {
00097 int i = 0;
00098 int j = 0;
00099 int pos=0;
00100 double tmp = (*s)(0,0);
00101
00102 for (j=0; j < s->getSize(); j++) {
00103 pos = (tmp < (*s)(i,j))? pos : j;
00104 tmp = (tmp < (*s)(i,j))? tmp : (*s)(i,j);
00105 }
00106
00107 return pos;
00108 }
00109
00110 void
00111 AubioYin::myProcess(realvec& in, realvec& out)
00112 {
00113 mrs_natural c=0;
00114
00115
00116
00117 realvec yin((mrs_natural)(inSamples_/2.0));
00118
00119
00120 mrs_real tol = ctrl_tolerance_->to<mrs_real>();
00121
00122 double pitch = -1.0;
00123
00124
00125
00126
00127
00128 int j,tau = 0;
00129 int period;
00130 double tmp = 0., tmp2 = 0.;
00131 yin(c,0) = 1.;
00132 for (tau=1;tau<yin.getSize();tau++)
00133 {
00134
00135 yin(c,tau) = 0.;
00136 for (j=0;j<yin.getSize();j++)
00137 {
00138 tmp = in(c,j) - in(c,j+tau);
00139 yin(c,tau) += tmp * tmp;
00140 }
00141 tmp2 += yin(c,tau);
00142 yin(c,tau) *= tau/tmp2;
00143 period = tau-3;
00144 if(tau > 4 && (yin(c,period) < tol) &&
00145 (yin(c,period) < yin(c,period+1))) {
00146 pitch = vec_quadint_min(&yin,period,1);
00147 break;
00148 }
00149 }
00150 if (pitch < 0) {
00151 pitch = vec_quadint_min(&yin,vec_min_elem(&yin),1);
00152 }
00153
00154 out(0,0) = ctrl_osrate_/pitch;
00155
00156 }