00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "LPC.h"
00020
00021
00022
00023 using std::ostringstream;
00024 using namespace Marsyas;
00025
00026 LPC::LPC(mrs_string name):MarSystem("LPC",name)
00027 {
00028 addControls();
00029 }
00030
00031 LPC::LPC(const LPC& a):MarSystem(a)
00032 {
00033 ctrl_coeffs_ = getctrl("mrs_realvec/coeffs");
00034 ctrl_pitch_ = getctrl("mrs_real/pitch");
00035 ctrl_power_ = getctrl("mrs_real/power");
00036 }
00037
00038 LPC::~LPC()
00039 {
00040 }
00041
00042 MarSystem*
00043 LPC::clone() const
00044 {
00045 return new LPC(*this);
00046 }
00047
00048 void
00049 LPC::addControls()
00050 {
00051 addctrl("mrs_natural/order", (mrs_natural)10);
00052 addctrl("mrs_realvec/coeffs", realvec(), ctrl_coeffs_);
00053 addctrl("mrs_real/pitch", 0.0, ctrl_pitch_);
00054 addctrl("mrs_real/power", 0.0, ctrl_power_);
00055 setctrlState("mrs_natural/order", true);
00056 addctrl("mrs_real/lambda", (mrs_real)0.0);
00057 addctrl("mrs_real/gamma", (mrs_real)1.0);
00058 }
00059
00060 void
00061 LPC::myUpdate(MarControlPtr sender)
00062 {
00063 (void) sender;
00064 MRSDIAG("LPC.cpp - LPC:myUpdate");
00065
00066 order_ = getctrl("mrs_natural/order")->to<mrs_natural>();
00067
00068 setctrl("mrs_natural/onObservations", (mrs_natural)(order_+2));
00069 setctrl("mrs_natural/onSamples", (mrs_natural)1);
00070 setctrl("mrs_real/osrate", getctrl("mrs_real/israte"));
00071
00072
00073 ostringstream oss;
00074 for (mrs_natural i = 0; i < order_; ++i)
00075 oss << "LPC_" << i+1 << ",";
00076 oss << "LPC_Pitch," << "LPC_Gain,";
00077 setctrl("mrs_string/onObsNames", oss.str());
00078
00079 temp_.create(order_ ,order_);
00080 Zs_.create(order_);
00081
00082 {
00083 MarControlAccessor acc(ctrl_coeffs_, NOUPDATE);
00084 realvec& coeffs = acc.to<mrs_realvec>();
00085 coeffs.stretch(order_+1);
00086 }
00087
00088
00089 #ifdef _MATLAB_LPC_
00090 MATLAB_EVAL("LPC_pitch = [];");
00091 #endif
00092
00093 }
00094
00095
00096 void
00097 LPC::autocorrelationWarped(const realvec& in, realvec& r, mrs_real& pitch, mrs_real lambda)
00098 {
00099
00100
00101
00102
00103
00104 mrs_real* x = in.getData();
00105 mrs_natural L = in.getSize();
00106 mrs_real* R = r.getData();
00107 mrs_natural P = in.getSize()/2;
00108
00109 mrs_real* dl = new mrs_real[L];
00110 mrs_real* Rt = new mrs_real[L];
00111 mrs_real r1,r2,r1t;
00112 R[0]=0;
00113 Rt[0]=0;
00114 r1=0;
00115 r2=0;
00116 r1t=0;
00117 for(mrs_natural k=0; k<L;k++)
00118 {
00119 Rt[0]+=x[k]*x[k];
00120
00121 dl[k]=r1-lambda*(x[k]-r2);
00122 r1 = x[k];
00123 r2 = dl[k];
00124 }
00125 for(mrs_natural i=1; i<=P; ++i)
00126 {
00127 Rt[i]=0;
00128 r1=0;
00129 r2=0;
00130 for(mrs_natural k=0; k<L;k++)
00131 {
00132 Rt[i]+=dl[k]*x[k];
00133
00134 r1t = dl[k];
00135 dl[k]=r1-lambda*(r1t-r2);
00136 r1 = r1t;
00137 r2 = dl[k];
00138 }
00139 }
00140
00141 for(long i=0; i<=P; ++i)
00142 R[i]=Rt[i]/in.getSize();
00143
00144 delete[] dl;
00145 delete[] Rt;
00146
00147
00148
00149
00150 mrs_real temp = r(0);
00151
00152 mrs_real j = (mrs_real)in.getSize() * 0.02;
00153
00154 while (r((mrs_natural)j) < temp && j < in.getSize()/2)
00155 {
00156 temp = r((mrs_natural)j);
00157 j++;
00158 }
00159
00160 temp = 0.0;
00161 for (mrs_natural i=(mrs_natural)j; i < in.getSize() * 0.5; ++i)
00162 {
00163 if (r(i) > temp)
00164 {
00165 j = i;
00166 temp = r(i);
00167 }
00168 }
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181 if ((r((mrs_natural)j) / r(0)) < 0.4) j=0;
00182
00183 if (j > in.getSize()/4) j = 0;
00184
00185
00186
00187
00188
00189 pitch = (mrs_real)j;
00190
00191
00192 #ifdef _MATLAB_LPC_
00193 MATLAB_PUT(pitch, "pitch");
00194 MATLAB_EVAL("LPC_pitch = [LPC_pitch pitch];");
00195 #endif
00196 }
00197
00198
00199 void
00200 LPC::LevinsonDurbin(const realvec& r, realvec& a, realvec& kVec, mrs_real& e)
00201 {
00202
00203
00204 mrs_natural P = order_;
00205 mrs_real* R = r.getData();
00206 mrs_real* A = a.getData();
00207 mrs_real* K = kVec.getData();
00208 e = 0.0;
00209
00210 mrs_real Am1[62];
00211
00212 if(R[0]==0.0)
00213 {
00214 for(mrs_natural i=1; i<=P; ++i)
00215 {
00216 K[i]=0.0;
00217 A[i]=0.0;
00218 }
00219 }
00220 else
00221 {
00222 mrs_real km,Em1,Em;
00223 mrs_natural k,s,m;
00224
00225 for (k=0;k<=P;k++){
00226 A[k]=0;
00227 Am1[k]=0; }
00228
00229 A[0]=1;
00230 Am1[0]=1;
00231 km=0;
00232 Em1=R[0];
00233
00234 for (m=1;m<=P;m++)
00235 {
00236 mrs_real err=0.0f;
00237
00238 for (k=1;k<=m-1;k++)
00239 err += Am1[k]*R[m-k];
00240
00241 km = (R[m]-err)/Em1;
00242 K[m-1] = -km;
00243 A[m]=km;
00244
00245 for (k=1;k<=m-1;k++)
00246 A[k]=Am1[k]-km*Am1[m-k];
00247
00248 Em=(1-km*km)*Em1;
00249
00250 for(s=0;s<=P;s++)
00251 Am1[s] = A[s];
00252
00253 Em1 = Em;
00254
00255 e = Em1*Em1;
00256 }
00257 e = sqrt(e/(mrs_real)P);
00258 }
00259 }
00260
00261 mrs_real
00262 LPC::predictionError(const realvec& data, const realvec& coeffs)
00263 {
00264 mrs_natural i, j;
00265 mrs_real power = 0.0;
00266 mrs_real error, tmp;
00267
00268
00269 for (i=0; i< order_; ++i)
00270 {
00271 Zs_(i) = data(order_-i-1);
00272 }
00273
00274 mrs_natural count = 0;
00275 for (i=order_; i<(mrs_natural)data.getSize() ; ++i)
00276 {
00277 tmp = 0.0;
00278 for (j=0; j< order_; j++)
00279 tmp += Zs_(j) * coeffs(j);
00280 for (j=order_-1; j>0; j--)
00281 Zs_(j) = Zs_(j-1);
00282
00283 Zs_(0) = data(i);
00284 error = data(i) - tmp;
00285 power += error * error;
00286 count ++;
00287 }
00288 return sqrt(power/(mrs_real)count);
00289 }
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302 mrs_real
00303 LPC::VRfDotProd (mrs_real * x1, mrs_real * x2, mrs_natural N)
00304 {
00305 mrs_natural i;
00306 mrs_real sum;
00307
00308 sum = 0.0;
00309 for (i = 0; i < N; ++i)
00310 sum += x1[i] * x2[i];
00311
00312 return sum;
00313 }
00314
00315 void
00316 LPC::SPautoc (mrs_real * x, mrs_natural Nx, mrs_real * cor, mrs_natural Nt)
00317 {
00318 mrs_natural i;
00319 mrs_natural N;
00320
00321 N = Nt;
00322 if (Nt > Nx)
00323 N = Nx;
00324
00325 for (i = 0; i < N; ++i)
00326 cor[i] = VRfDotProd (x, &x[i], Nx - i);
00327
00328 for (i = N; i < Nt; ++i)
00329 cor[i] = 0.0;
00330
00331 return;
00332 }
00333
00334
00335 mrs_real
00336 LPC::SPcorXpc (mrs_real * rxx, mrs_real * pc, mrs_natural Np)
00337 {
00338 mrs_natural i, j, k;
00339 mrs_real rc, tp;
00340 mrs_real perr, t, sum;
00341
00342 perr = rxx[0];
00343
00344
00345 for (k = 0; k < Np; ++k) {
00346
00347
00348 sum = rxx[k+1];
00349 for (i = 0; i < k; ++i)
00350 sum = sum - rxx[k-i] * pc[i];
00351
00352
00353 if (perr == 0.0 && sum == 0.0)
00354 rc = 0.0;
00355 else
00356 rc = (-sum / perr);
00357
00358
00359
00360
00361
00362
00363 t = perr + rc * sum;
00364
00365 perr = t;
00366
00367
00368 pc[k] = -rc;
00369 for (i = 0, j = k - 1; i < j; ++i, --j) {
00370 tp = pc[i] + rc * pc[j];
00371 pc[j] = pc[j] + rc * pc[i];
00372 pc[i] = tp;
00373 }
00374 if (i == j)
00375 pc[i] = pc[i] + rc * pc[i];
00376 }
00377
00378 return perr;
00379 }
00380
00381
00382
00383 void
00384 LPC::myProcess(realvec& in, realvec& out)
00385 {
00386 mrs_natural i;
00387 mrs_real LevinsonError = 0.0;
00388
00389
00390 mrs_real pitch = 0.0, lag = 0.0;
00391
00392
00393 #ifdef _MATLAB_LPC_
00394 MATLAB_PUT(featureMode_, "featureMode");
00395 MATLAB_PUT(in, "LPC_in");
00396 MATLAB_PUT(order_, "LPC_order");
00397 MATLAB_PUT(getctrl("mrs_real/gamma")->to<mrs_real>(), "LPC_gamma");
00398 #endif
00399
00400
00401
00402
00403
00404 realvec r(in.getSize());
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414 realvec a(order_+1);
00415 realvec k(order_+1);
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426 autocorrelationWarped(in, r, lag, getctrl("mrs_real/lambda")->to<mrs_real>());
00427 LevinsonError = SPcorXpc (r.getData(), a.getData(), a.getSize()-1);
00428
00429
00430 LevinsonError = sqrt(LevinsonError);
00431
00432 pitch = getctrl("mrs_real/israte")->to<mrs_real>()/lag ;
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443 for(i=0; i < order_; ++i)
00444
00445 out(i) = -a(i);
00446
00447
00448
00449
00450 out(order_) = pitch;
00451 out(order_+1) = LevinsonError;
00452
00453
00454
00455
00456
00457 mrs_real gamma = getctrl("mrs_real/gamma")->to<mrs_real>();
00458 if(gamma != 1.0)
00459 {
00460 for(mrs_natural j = 0; j < order_; j++)
00461 {
00462 out(j) = (out(j) * pow((mrs_real)gamma, (mrs_real)j+1));
00463 }
00464 }
00465
00466 {
00467 MarControlAccessor acc(ctrl_coeffs_);
00468 realvec& coeffs = acc.to<mrs_realvec>();
00469 coeffs(0) = 1.0;
00470 for(i=1; i < order_+1; ++i)
00471 {
00472
00473 coeffs(i) = out(i-1);
00474 ctrl_pitch_->setValue(pitch);
00475 ctrl_power_->setValue(LevinsonError);
00476 }
00477 }
00478
00479
00480 #ifdef _MATLAB_LPC_
00481 MATLAB_PUT(out, "LPC_out");
00482 MATLAB_PUT(getctrl("mrs_real/pitch")->to<mrs_real>(), "pitch_MARS");
00483 MATLAB_PUT(getctrl("mrs_real/power")->to<mrs_real>(), "g_MARS");
00484 MATLAB_PUT(ctrl_coeffs_->to<mrs_realvec>(), "a_MARS");
00485 MATLAB_EVAL("LPC_test");
00486 mrs_real matlabGain;
00487 MATLAB_GET("LPCgain", matlabGain);
00488 #endif
00489
00490 }