00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "LyonPassiveEar.h"
00021 #include "Series.h"
00022 #include "Filter.h"
00023 #include "Cascade.h"
00024 #include "HalfWaveRectifier.h"
00025 #include "basis.h"
00026 #include <sstream>
00027
00028 using std::ostringstream;
00029 using std::abs;
00030
00031 using namespace Marsyas;
00032
00033
00034 namespace Marsyas
00035 {
00047 class LyonAgc: public MarSystem
00048 {
00049 private:
00050 static mrs_real lyonEpsilonFromTauFS (mrs_real tau, mrs_real fs)
00051 {
00052 return 1.0 - exp (-1/tau/fs);
00053 }
00054
00055 static void agc (const mrs_realvec input, mrs_realvec &output, mrs_realvec &state, mrs_real epsilon, mrs_real target, mrs_natural n)
00056 {
00057 mrs_natural i;
00058 mrs_real f,
00059 stateLimit = 1. - 1e-1;
00060 mrs_real oneMinusEpsOverThree = (1.0 - epsilon)/3.0;
00061 mrs_real epsOverTarget = epsilon/target;
00062 mrs_real prevState = state(0);
00063
00064 for ( i = 0; i < n-1; ++i)
00065 {
00066 output(i) = fabs (input(i) * (1.0 - state(i)));
00067 f = output(i) * epsOverTarget + oneMinusEpsOverThree * (prevState + state(i) + state(i+1));
00068
00069 if (f > stateLimit)
00070 f = stateLimit;
00071
00072 prevState = state(i);
00073 state(i) = f;
00074 }
00075
00076
00077 output(i) = fabs (input(i) * (1.0 - state(i)));
00078 f = output(i) * epsOverTarget + oneMinusEpsOverThree * (prevState + state(i) + state(i));
00079
00080 if (f > stateLimit)
00081 f = stateLimit;
00082
00083 state(i) = f;
00084 };
00085
00086 void myUpdate(MarControlPtr sender)
00087 {
00089 MarSystem::myUpdate(sender);
00090
00091 const mrs_natural nStates = 4;
00092 mrs_real fs = getctrl ("mrs_real/israte")->to<mrs_real>();
00093 mrs_natural nBands = getctrl ("mrs_natural/numBands")->to<mrs_natural>();
00094
00095
00096 agcParms_.create(2, nStates);
00097 state_.create(nBands, nStates);
00098 tmpOut_.create(nBands, 1);
00099
00100
00101 agcParms_(0,0) = .0032;
00102 agcParms_(0,1) = .0016;
00103 agcParms_(0,2) = .0008;
00104 agcParms_(0,3) = .0004;
00105 agcParms_(1,0) = lyonEpsilonFromTauFS (.64, fs);
00106 agcParms_(1,1) = lyonEpsilonFromTauFS (.16, fs);
00107 agcParms_(1,2) = lyonEpsilonFromTauFS (.04, fs);
00108 agcParms_(1,3) = lyonEpsilonFromTauFS (.01, fs);
00109
00110
00111 state_.setval (0);
00112 };
00113
00114 mrs_realvec agcParms_,
00115 state_,
00116 tmpOut_;
00117
00118 friend class LyonPassiveEar;
00119
00120 public:
00121 LyonAgc(std::string name):MarSystem("LyonAgc", name)
00122 {
00123 addControls ();
00124 };
00125 ~LyonAgc(){};
00126
00127 void addControls()
00128 {
00129 addctrl("mrs_natural/numBands", 1);
00130 setctrlState("mrs_natural/numBands", true);
00131 }
00132
00133 MarSystem* clone() const
00134 {
00135 return new LyonAgc(*this);
00136 };
00137
00138 void myProcess(realvec& in, realvec& out)
00139 {
00140
00141 for (mrs_natural t = 0; t < inSamples_; t++)
00142 {
00143 mrs_natural i,
00144 nStages = agcParms_.getCols (),
00145 nRows = in.getRows ();
00146 mrs_realvec state;
00147 in.getCol (t, tmpOut_);
00148
00149 for (i = 0; i < nStages; ++i)
00150 {
00151 state_.getCol (i, state);
00152 agc (tmpOut_, tmpOut_, state, agcParms_(1,i), agcParms_(0,i), nRows);
00153 state_.setCol (i,state);
00154 }
00155 out.setCol (t, tmpOut_);
00156 }
00157 };
00158 };
00159
00171 class LyonChannelDiff: public MarSystem
00172 {
00173 private:
00174
00175 void myUpdate(MarControlPtr sender)
00176 {
00177
00179 MarSystem::myUpdate(sender);
00180
00181 numBands_ = getctrl ("mrs_natural/numBands")->to<mrs_natural>();
00182
00183
00184 procBuf1_.create(numBands_-1,1);
00185 procBuf2_.create(numBands_-1,1);
00186 };
00187
00188 mrs_realvec procBuf1_,
00189 procBuf2_;
00190 mrs_natural numBands_;
00191 public:
00192 LyonChannelDiff(std::string name):MarSystem("LyonChannelDiff", name)
00193 {
00194 addControls ();
00195 };
00196 ~LyonChannelDiff(){};
00197
00198 void addControls()
00199 {
00200 addctrl("mrs_natural/numBands", 1);
00201 setctrlState("mrs_natural/numBands", true);
00202 }
00203
00204 MarSystem* clone() const
00205 {
00206 return new LyonChannelDiff(*this);
00207 };
00208
00209 void myProcess(realvec& in, realvec& out)
00210 {
00211
00212 mrs_natural t;
00213 for (t = 0; t < inSamples_; t++)
00214 {
00215 in.getSubMatrix (0,t, procBuf1_);
00216 in.getSubMatrix (1,t, procBuf2_);
00217 procBuf1_ -=procBuf2_;
00218 out.setSubMatrix (1,t,procBuf1_);
00219 out(0,t) = in(0,t);
00220 }
00221 };
00222 };
00223
00235 class LyonZeroOutPreEmph: public MarSystem
00236 {
00237 private:
00238
00239 void myUpdate(MarControlPtr sender)
00240 {
00241
00243 MarSystem::myUpdate(sender);
00244 };
00245
00246 public:
00247 LyonZeroOutPreEmph(std::string name):MarSystem("LyonZeroOutPreEmph", name)
00248 {
00249 };
00250 ~LyonZeroOutPreEmph(){};
00251
00252 MarSystem* clone() const
00253 {
00254 return new LyonZeroOutPreEmph(*this);
00255 };
00256
00257 void myProcess(realvec& in, realvec& out)
00258 {
00259 mrs_natural t,o;
00260 for (t = 0; t < inSamples_; t++)
00261 {
00262 out(0,t) = 0;
00263 out(1,t) = 0;
00264 for (o = 2; o < onObservations_; o++)
00265 out(o,t) = in(o,t);
00266 }
00267 };
00268 };
00269 }
00270
00271
00272
00275
00276 LyonPassiveEar::LyonPassiveEar(mrs_string name)
00277 : MarSystem("LyonPassiveEar", name),
00278 fs_ (0),
00279 currDecimState_(0),
00280 numFilterChannels_ (0),
00281 passiveEar_ (0)
00282 {
00283 addControls();
00284 }
00285
00286
00287 LyonPassiveEar::~LyonPassiveEar()
00288 {
00289 if (passiveEar_)
00290 {
00291 delete passiveEar_;
00292 passiveEar_ = 0;
00293 }
00294 }
00295
00296 MarSystem*
00297 LyonPassiveEar::clone() const
00298 {
00299 LyonPassiveEar *newEar = new LyonPassiveEar(*this);
00300 if (passiveEar_)
00301 newEar->passiveEar_ = (Series*)passiveEar_->clone ();
00302
00303 return newEar;
00304 }
00305
00306
00307 void
00308 LyonPassiveEar::addControls()
00309 {
00310 addctrl("mrs_natural/decimFactor", 1);
00311 addctrl("mrs_real/earQ", 8.0F);
00312 addctrl("mrs_real/stepFactor", 0.25F);
00313 addctrl("mrs_bool/channelDiffActive", true);
00314 addctrl("mrs_bool/agcActive", true);
00315 addctrl("mrs_real/decimTauFactor", 3.0F);
00316
00317 addctrl("mrs_realvec/centerFreqs", centerFreqs_);
00318
00319 setctrlState("mrs_natural/decimFactor", true);
00320 setctrlState("mrs_real/earQ", true);
00321 setctrlState("mrs_real/stepFactor", true);
00322 setctrlState("mrs_bool/channelDiffActive", true);
00323 setctrlState("mrs_bool/agcActive", true);
00324 setctrlState("mrs_real/decimTauFactor", true);
00325
00326 setctrlState("mrs_realvec/centerFreqs", false);
00327 }
00328
00329 void
00330 LyonPassiveEar::myUpdate(MarControlPtr sender)
00331 {
00332 (void) sender;
00333
00334 if (!setParametersIntern ())
00335 {
00336 this->updateControlsIntern ();
00337 return;
00338 }
00339
00340 MRSDIAG("LyonPassiveEar.cpp - LyonPassiveEar:myUpdate");
00341
00342
00343
00344 const mrs_real Eb = 1000.0;
00345 const mrs_real EarZeroOffset = 1.5;
00346 const mrs_real EarSharpness = 5.0;
00347 const mrs_real EarPremphCorner = 300.0;
00348 mrs_natural i,numChans;
00349 ostringstream name;
00350 mrs_realvec a(3),
00351 b(3);
00352 mrs_real lowFreq,
00353 topFreq = .5 * getctrl ("mrs_real/israte")->to<mrs_real>();
00354 Cascade *filterBank = 0;
00355
00356
00357
00358
00359
00360 topFreq = topFreq -
00361 (sqrt (sqr(topFreq) + sqr(Eb)) / earQ_ * stepFactor_ * EarZeroOffset) +
00362 sqrt (sqr(topFreq) + sqr(Eb)) / earQ_ * stepFactor_;
00363
00364
00365
00366
00367
00368 lowFreq = Eb / sqrt (4 * sqr(earQ_) - 1);
00369 numChans = (mrs_natural)(floor ((earQ_ * (-log (lowFreq + sqrt (sqr(lowFreq) + sqr(Eb))) +
00370 log (topFreq + sqrt (sqr(Eb) + sqr(topFreq)))))/stepFactor_) + .1);
00371
00372
00373
00374
00375
00376
00377
00378
00379 centerFreqs_.create (numChans);
00380 for (i = 0; i < numChans; ++i)
00381 centerFreqs_(i) = (-((exp(((i+1)*stepFactor_)/earQ_) * sqr(Eb))/
00382 (topFreq + sqrt(sqr(Eb) + sqr(topFreq)))) + (topFreq + sqrt(sqr(Eb) + sqr(topFreq)))/ exp(((i+1)*stepFactor_)/earQ_))*.5;
00383
00384
00385 if (passiveEar_)
00386 {
00387 delete passiveEar_;
00388 passiveEar_ = 0;
00389 }
00390
00391 passiveEar_ = new Series ("LyonPassiveEar");
00392 passiveEar_->addMarSystem (filterBank = new Cascade("LyonFilterBank"));
00393 passiveEar_->addMarSystem (new HalfWaveRectifier("hwr1"));
00394 passiveEar_->addMarSystem (new LyonZeroOutPreEmph("ZeroOut"));
00395 if (agcActive_)
00396 passiveEar_->addMarSystem (new LyonAgc("agc"));
00397 if (channelDiffActive_)
00398 {
00399 passiveEar_->addMarSystem (new LyonChannelDiff("differ"));
00400 passiveEar_->addMarSystem (new HalfWaveRectifier("hwr2"));
00401 }
00402
00403 if (decimFactor_ > 1)
00404 {
00405 b(0) = b(1) = 0;
00406 b(2) = a(0) = 1;
00407 a(1) = -2.0*(1-LyonAgc::lyonEpsilonFromTauFS (decimFactor_/fs_*decimTauFactor_, fs_));
00408 a(2) = sqr(a(1)/(-2.0));
00409 b *= lyonSetGain (b, a, 1.0, 0, fs_);
00410 }
00411 else
00412 {
00413
00414 b(0) = a(0) = 1;
00415 b(1) = b(2) = a(1) = a(2) = 0;
00416 }
00417
00418 passiveEar_->addMarSystem (lyonCreateFilter (b,a,"decim"));
00419
00420
00421
00422
00423
00424 b(0) = a(1) = a(2) = 0;
00425 b(1) = a(0) = 1;
00426 b(2) = -exp(-TWOPI*EarPremphCorner/fs_);
00427 b *= lyonSetGain (b, a, 1.0, fs_*.25, fs_);
00428
00429 name.str("");
00430 name << "front_" << 0;
00431 filterBank->addMarSystem(lyonCreateFilter (b, a, name.str()));
00432
00433 b(0) = 1;
00434 b(1) = 0;
00435 b(2) = -1;
00436 a = lyonSecondOrderFilter (topFreq, centerFreqs_(0)/(sqrt(sqr(centerFreqs_(0)) + sqr(Eb))/earQ_), fs_);
00437 b *= lyonSetGain (b, a, 1.0F, fs_*.25F, fs_);
00438
00439 name.str("");
00440 name << "front_" << 1;
00441 filterBank->addMarSystem(lyonCreateFilter (b, a, name.str()));
00442
00443 for (i = 0; i < numChans; ++i)
00444 {
00445 mrs_real EarBandwidth, CascadeZeroCF, CascadeZeroQ, CascadePoleCF, CascadePoleQ;
00446
00447
00448
00449
00450
00451
00452
00453 EarBandwidth = sqrt(sqr(centerFreqs_(i)) + sqr(Eb))/earQ_;
00454 CascadeZeroCF = centerFreqs_(i) + EarBandwidth * stepFactor_ * EarZeroOffset;
00455 CascadeZeroQ = EarSharpness * CascadeZeroCF / EarBandwidth;
00456 CascadePoleCF = centerFreqs_(i);
00457 CascadePoleQ = centerFreqs_(i)/EarBandwidth;
00458
00459
00460 b = lyonSecondOrderFilter (CascadeZeroCF, CascadeZeroQ, fs_);
00461 a = lyonSecondOrderFilter (CascadePoleCF, CascadePoleQ, fs_);
00462
00463
00464
00465
00466
00467
00468
00469
00470 b *= (i == 0) ? lyonSetGain (b, a, centerFreqs_(i)/centerFreqs_(i+1), 0, fs_) :
00471 lyonSetGain (b, a, centerFreqs_(i-1)/centerFreqs_(i), 0, fs_);
00472
00473
00474 name.str("");
00475 name << "filter_" << i;
00476 filterBank->addMarSystem(lyonCreateFilter (b, a, name.str()));
00477 }
00478
00479 numFilterChannels_ = numChans + 2;
00480
00481 this->updateControlsIntern ();
00482
00483
00484 tmpOut_.create (numFilterChannels_, inSamples_);
00485 decimOut_.create (numFilterChannels_-2, inSamples_/decimFactor_);
00486 }
00487
00488 void
00489 LyonPassiveEar::myProcess(realvec& in, realvec& out)
00490 {
00491 if(getctrl("mrs_bool/mute")->to<mrs_bool>()) return;
00492
00493
00494 mrs_natural i,
00495 currCount = -currDecimState_-1,
00496 numOutSamples = (inSamples_+currDecimState_)/decimFactor_;
00497
00498 MRSASSERT(currDecimState_ <= decimFactor_);
00499
00500
00501 if (onSamples_ != numOutSamples)
00502 updControl ("mrs_natural/onSamples", numOutSamples);
00503
00504 decimOut_.stretch (numFilterChannels_-2, numOutSamples);
00505
00506
00507 passiveEar_->process(in, tmpOut_);
00508
00509
00510 for (i = 0; i < numOutSamples; ++i)
00511 {
00512 mrs_realvec decimTmp(numFilterChannels_-2,1);
00513 currCount = currCount + decimFactor_;
00514 MRSASSERT(currCount <= inSamples_);
00515 tmpOut_.getSubMatrix (2, currCount, decimTmp);
00516 decimOut_.setSubMatrix (0, i, decimTmp);
00517 }
00518 currDecimState_ = inSamples_ - currCount-1;
00519 out = decimOut_;
00520 }
00521
00522
00524 mrs_bool LyonPassiveEar::setParametersIntern ()
00525 {
00526 mrs_bool updateMe = false;
00527
00528 updateMe |= (passiveEar_ == 0);
00529
00530
00531 if (decimFactor_ != getctrl ("mrs_natural/decimFactor")->to<mrs_natural>())
00532 {
00533 updateMe = true;
00534 decimFactor_ = getctrl ("mrs_natural/decimFactor")->to<mrs_natural>();
00535 }
00536 if (earQ_ != getctrl ("mrs_real/earQ")->to<mrs_real>())
00537 {
00538 updateMe = true;
00539 earQ_ = getctrl ("mrs_real/earQ")->to<mrs_real>();
00540 }
00541 if (stepFactor_ != getctrl ("mrs_real/stepFactor")->to<mrs_real>())
00542 {
00543 updateMe = true;
00544 stepFactor_ = getctrl ("mrs_real/stepFactor")->to<mrs_real>();
00545 }
00546 if (channelDiffActive_ != getctrl ("mrs_bool/channelDiffActive")->to<mrs_bool>())
00547 {
00548 updateMe = true;
00549 channelDiffActive_ = getctrl ("mrs_bool/channelDiffActive")->to<mrs_bool>();
00550 }
00551 if (agcActive_ != getctrl ("mrs_bool/agcActive")->to<mrs_bool>())
00552 {
00553 updateMe = true;
00554 agcActive_ = getctrl ("mrs_bool/agcActive")->to<mrs_bool>();
00555 }
00556 if (decimTauFactor_ != getctrl ("mrs_real/decimTauFactor")->to<mrs_real>())
00557 {
00558 updateMe = true;
00559 decimTauFactor_ = getctrl ("mrs_real/decimTauFactor")->to<mrs_real>();
00560 }
00561 if (fs_ != getctrl ("mrs_real/israte")->to<mrs_real>())
00562 {
00563 updateMe = true;
00564 fs_ = getctrl ("mrs_real/israte")->to<mrs_real>();
00565 }
00566
00567 return updateMe;
00568 }
00569
00570 void LyonPassiveEar::updateControlsIntern ()
00571 {
00572 passiveEar_->updControl("mrs_natural/inObservations", getctrl("mrs_natural/inObservations")->to<mrs_natural>());
00573 passiveEar_->updControl("mrs_natural/inSamples", getctrl("mrs_natural/inSamples")->to<mrs_natural>());
00574 passiveEar_->updControl("mrs_real/israte", getctrl("mrs_real/israte")->to<mrs_real>());
00575
00576 ctrl_onSamples_->setValue(inSamples_/decimFactor_);
00577 ctrl_osrate_->setValue(israte_*1.0/decimFactor_);
00578
00579 if (numFilterChannels_)
00580 {
00581 updControl ("mrs_realvec/centerFreqs", centerFreqs_);
00582 ctrl_onObservations_->setValue((numFilterChannels_-2)*getctrl("mrs_natural/inObservations")->to<mrs_natural>());
00583
00584 passiveEar_->setctrl("mrs_natural/onObservations", getctrl("mrs_natural/onObservations")->to<mrs_natural>());
00585 if (agcActive_)
00586 passiveEar_->updControl("LyonAgc/agc/mrs_natural/numBands", numFilterChannels_);
00587 if (channelDiffActive_)
00588 passiveEar_->updControl("LyonChannelDiff/differ/mrs_natural/numBands", numFilterChannels_);
00589 }
00590 }
00591
00593 mrs_realvec LyonPassiveEar::lyonSecondOrderFilter (mrs_real midFreq, mrs_real q, mrs_real sRate)
00594 {
00595
00596
00597
00598
00599
00600 mrs_realvec result (3);
00601 mrs_real cft = midFreq / sRate,
00602 rho = exp (-PI * cft / q);
00603
00604 result(0) = 1;
00605 result(1) = -2 * rho * cos (TWOPI * cft * sqrt (1 - 1.0/(4*sqr(q))));
00606 result(2) = sqr(rho);
00607 return result;
00608 }
00609
00611 mrs_real LyonPassiveEar::lyonFreqResp (mrs_realvec firCoeffs, mrs_realvec iirCoeffs, mrs_real freq, mrs_real sRate, mrs_bool inDb)
00612 {
00613
00614
00615
00616
00617
00618 mrs_complex cf = mrs_complex (cos (TWOPI * freq / sRate), sin (TWOPI * freq / sRate));
00619 mrs_complex mag = (firCoeffs(2) + firCoeffs(1) * cf + firCoeffs(0) * (cf*cf)) / (iirCoeffs(2) + iirCoeffs(1) * cf + (cf*cf));
00620 mrs_real res = sqrt (sqr(mag.real ()) + sqr (mag.imag ()));
00621
00622 return inDb? 20.0/log(10.0) * log (res) : res;
00623 }
00624
00626 mrs_real LyonPassiveEar::lyonSetGain (mrs_realvec firCoeffs, mrs_realvec iirCoeffs, mrs_real newGain, mrs_real freq, mrs_real sRate)
00627 {
00628
00629
00630
00631
00632 return newGain / lyonFreqResp (firCoeffs, iirCoeffs, freq, sRate, false);
00633 }
00634
00636 Filter* LyonPassiveEar::lyonCreateFilter (mrs_realvec b, mrs_realvec a, mrs_string name)
00637 {
00638 Filter *filter = new Filter(name);
00639 filter->setctrl("mrs_realvec/ncoeffs", b);
00640 filter->setctrl("mrs_realvec/dcoeffs", a);
00641
00642 return filter;
00643 }