00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "common.h"
00020 #include "AutoCorrelation.h"
00021 #include "Windowing.h"
00022
00023 using std::cout;
00024 using std::endl;
00025
00026 using std::ostringstream;
00027 using namespace Marsyas;
00028
00029 AutoCorrelation::AutoCorrelation(mrs_string name):MarSystem("AutoCorrelation",name)
00030 {
00031 myfft_ = NULL;
00032 addControls();
00033 }
00034
00035 AutoCorrelation::~AutoCorrelation()
00036 {
00037 delete myfft_;
00038 }
00039
00040
00041 AutoCorrelation::AutoCorrelation(const AutoCorrelation& a):MarSystem(a)
00042 {
00043 myfft_ = NULL;
00044
00045 ctrl_magcompress_ = getctrl("mrs_real/magcompress");
00046 ctrl_normalize_ = getctrl("mrs_natural/normalize");
00047 ctrl_octaveCost_ = getctrl("mrs_real/octaveCost");
00048 ctrl_voicingThreshold_ = getctrl("mrs_real/voicingThreshold");
00049 ctrl_aliasedOutput_ = getctrl("mrs_bool/aliasedOutput");
00050 ctrl_makePositive_ = getctrl("mrs_bool/makePositive");
00051 ctrl_setr0to1_ = getctrl("mrs_bool/setr0to1");
00052 ctrl_setr0to0_ = getctrl("mrs_bool/setr0to0");
00053 ctrl_lowCutoff_ = getctrl("mrs_real/lowCutoff");
00054 ctrl_highCutoff_ = getctrl("mrs_real/highCutoff");
00055 }
00056
00057 void
00058 AutoCorrelation::addControls()
00059 {
00060 addctrl("mrs_real/magcompress", 2.0, ctrl_magcompress_);
00061 addctrl("mrs_natural/normalize", 0, ctrl_normalize_);
00062 addctrl("mrs_real/octaveCost", 0.0, ctrl_octaveCost_);
00063 addctrl("mrs_real/voicingThreshold", 0.1, ctrl_voicingThreshold_);
00064 addctrl("mrs_bool/aliasedOutput", false, ctrl_aliasedOutput_);
00065 addctrl("mrs_bool/makePositive", false, ctrl_makePositive_);
00066 addctrl("mrs_bool/setr0to1", false, ctrl_setr0to1_);
00067 addctrl("mrs_bool/setr0to0", true, ctrl_setr0to0_);
00068 addctrl("mrs_real/lowCutoff", 0.0, ctrl_lowCutoff_);
00069 addctrl("mrs_real/highCutoff", 1.0, ctrl_highCutoff_);
00070
00071
00072 ctrl_normalize_->setState(true);
00073 ctrl_octaveCost_->setState(true);
00074 ctrl_voicingThreshold_->setState(true);
00075 ctrl_aliasedOutput_->setState(true);
00076 ctrl_lowCutoff_->setState(true);
00077 ctrl_highCutoff_->setState(true);
00078 }
00079
00080 MarSystem*
00081 AutoCorrelation::clone() const
00082 {
00083 return new AutoCorrelation(*this);
00084 }
00085
00086 void
00087 AutoCorrelation::myUpdate(MarControlPtr sender)
00088 {
00089 (void) sender;
00090
00091 if(!myfft_)
00092 myfft_ = new fft();
00093
00094
00095 setctrl("mrs_natural/onSamples", getctrl("mrs_natural/inSamples"));
00096 setctrl("mrs_natural/onObservations", getctrl("mrs_natural/inObservations"));
00097 setctrl("mrs_real/osrate", getctrl("mrs_real/israte"));
00098
00099
00100 lowSamples_ = (mrs_natural) ceil(inSamples_
00101 * getctrl("mrs_real/lowCutoff")->to<mrs_real>());
00102 numSamples_ = (mrs_natural) ceil( inSamples_
00103 * getctrl("mrs_real/highCutoff")->to<mrs_real>()
00104 ) - lowSamples_;
00105
00106 if(ctrl_aliasedOutput_->to<mrs_bool>())
00107 fftSize_ = inSamples_;
00108 else
00109 {
00110
00111 fftSize_ = (mrs_natural)pow(2.0, ceil(log(2.0*numSamples_-1.0)/log(2.0)));
00112 }
00113
00114 scratch_.create(fftSize_);
00115
00116
00117
00118 normalize_ = 0;
00119 if(getctrl("mrs_natural/normalize")->to<mrs_natural>())
00120 {
00121 realvec tmp(getctrl("mrs_natural/onSamples")->to<mrs_natural>());
00122 normalize_ = 1;
00123 norm_.create(getctrl("mrs_natural/onSamples")->to<mrs_natural>());
00124 norm_.setval(1);
00125 Windowing win("Windowing");
00126 win.updControl("mrs_string/type", "Hanning");
00127 win.updControl("mrs_natural/inSamples", norm_.getCols());
00128 win.updControl("mrs_natural/inObservations", norm_.getRows());
00129 win.process(norm_, tmp);
00130
00131 AutoCorrelation autocorr("Autocorrelation");
00132 autocorr.updControl("mrs_natural/inSamples", norm_.getCols());
00133 autocorr.updControl("mrs_natural/inObservations", norm_.getRows());
00134 autocorr.update();
00135 autocorr.process(tmp, norm_);
00136
00137 for (mrs_natural i = 0 ; i < norm_.getSize() ; ++i)
00138 norm_(i) = 1/norm_(i);
00139 }
00140
00141 octaveCost_ = getctrl("mrs_real/octaveCost")->to<mrs_real>();
00142 voicing_ = getctrl("mrs_real/voicingThreshold")->to<mrs_real>();
00143 if(octaveCost_)
00144 {
00145 octaveCost_ *= octaveCost_;
00146 octaveMax_ = octaveCost_*log(36.0*inSamples_);
00147 }
00148 }
00149
00150 void
00151 AutoCorrelation::myProcess(realvec& in, realvec& out)
00152 {
00153
00154
00155
00156
00157
00158 mrs_natural t,o;
00159 k_ = ctrl_magcompress_->to<mrs_real>();
00160
00161
00162
00163 scratch_.create(fftSize_);
00164 for (o=0; o < inObservations_; o++)
00165 {
00166 for (t=lowSamples_; t < (lowSamples_+numSamples_); t++)
00167 {
00168 scratch_(t-(lowSamples_)) = in(o,t);
00169 }
00170
00171
00172
00173
00174
00175
00176 for(t=(lowSamples_+numSamples_); t < fftSize_; t++)
00177 scratch_(t) = 0.0;
00178
00179
00180
00181 mrs_real *tmp = scratch_.getData();
00182
00183
00184 myfft_->rfft(tmp, fftSize_/2, FFT_FORWARD);
00185
00186
00187
00188 if (k_ == 2.0)
00189 {
00190 re_ = tmp[0];
00191 tmp[0] = re_ * re_;
00192 re_ = tmp[1];
00193 tmp[1] = re_ * re_;
00194 }
00195 else
00196 {
00197 re_ = tmp[0];
00198 re_ = sqrt(re_ * re_);
00199 tmp[0] = pow(re_, k_);
00200 re_ = tmp[1];
00201 re_ = sqrt(re_ * re_);
00202 tmp[1] = pow(re_, k_);
00203 }
00204
00205
00206
00207 for (t=1; t < fftSize_/2; t++)
00208 {
00209 re_ = tmp[2*t];
00210 im_ = tmp[2*t+1];
00211 if (k_ == 2.0)
00212 am_ = re_ * re_ + im_ * im_;
00213 else
00214 {
00215 am_ = sqrt(re_ * re_ + im_ * im_);
00216 am_ = pow(am_, k_);
00217 }
00218 tmp[2*t] = am_;
00219 tmp[2*t+1] = 0;
00220 }
00221
00222
00223 myfft_->rfft(tmp, fftSize_/2, FFT_INVERSE);
00224
00225
00226 if(normalize_)
00227 {
00228 for (t=0; t < onSamples_; t++)
00229 {
00230 out(o,t) = scratch_(t)*norm_(t);
00231 }
00232 }
00233 else
00234 for (t=0; t < onSamples_; t++)
00235 {
00236
00237 out(o,t) = 1.0 * scratch_(t) + 0.0 * out(o,t);
00238
00239
00240
00241 }
00242
00243 }
00244
00245
00246 if (ctrl_makePositive_->to<mrs_bool>())
00247 {
00248 out -= out.minval();
00249 }
00250
00251 if(octaveCost_)
00252 {
00253 for (o=0; o < inObservations_; o++)
00254 {
00255 mrs_real maxOut = 0;
00256 for (t=1 ; t<onSamples_/2 ; t++)
00257 if (out(o, t)> out(o, t+1) && out(o, t) > out(o, t-1) && out(o, t)>maxOut)
00258 maxOut = out(o, t) ;
00259
00260
00261 if(maxOut && maxOut/out(o, 0) > 1-voicing_)
00262 for (t=1; t < onSamples_; t++)
00263 out(o, t) += octaveMax_-octaveCost_*log(36.0*t);
00264 else
00265 out.setval(0);
00266 }
00267 }
00268
00269 if (ctrl_setr0to1_->to<mrs_bool>())
00270 {
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287 }
00288
00289
00290
00291
00292
00293 if (ctrl_setr0to0_->to<mrs_bool>())
00294 {
00295
00296
00297
00298
00299
00300
00301 for (o=0; o < onObservations_; o++)
00302 for (t=0; t < onSamples_; t++)
00303 {
00304 out(o,t) = out(o,t);
00305 }
00306 }
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317 }