Marsyas  0.6.0-alpha
/usr/src/RPM/BUILD/marsyas-0.6.0/src/marsyas/marsystems/AimHCL.cpp
Go to the documentation of this file.
00001 /*
00002 ** Copyright (C) 1998-2006 George Tzanetakis <gtzan@cs.uvic.ca>
00003 **
00004 ** This program is free software; you can redistribute it and/or modify
00005 ** it under the terms of the GNU General Public License as published by
00006 ** the Free Software Foundation; either version 2 of the License, or
00007 ** (at your option) any later version.
00008 **
00009 ** This program is distributed in the hope that it will be useful,
00010 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 ** GNU General Public License for more details.
00013 **
00014 ** You should have received a copy of the GNU General Public License
00015 ** along with this program; if not, write to the Free Software
00016 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00017 */
00018 
00019 #include "AimHCL.h"
00020 #include "../common_source.h"
00021 
00022 
00023 using std::ostringstream;
00024 using namespace Marsyas;
00025 
00026 AimHCL::AimHCL(mrs_string name):MarSystem("AimHCL",name)
00027 {
00028   is_initialized = false;
00029   initialized_lowpass_cutoff = 0;
00030 
00031   is_reset = false;
00032   reseted_inobservations = 0;
00033   reseted_lowpass_order = 0;
00034 
00035   addControls();
00036 }
00037 
00038 
00039 AimHCL::~AimHCL()
00040 {
00041 }
00042 
00043 
00044 MarSystem*
00045 AimHCL::clone() const
00046 {
00047   return new AimHCL(*this);
00048 }
00049 
00050 void
00051 AimHCL::addControls()
00052 {
00053   addControl("mrs_bool/do_lowpass", true , ctrl_do_lowpass_);
00054   addControl("mrs_bool/do_log", false , ctrl_do_log_);
00055   addControl("mrs_real/lowpass_cutoff", 1200.0 , ctrl_lowpass_cutoff_);
00056   addControl("mrs_natural/lowpass_order", 2 , ctrl_lowpass_order_);
00057 }
00058 
00059 void
00060 AimHCL::myUpdate(MarControlPtr sender)
00061 {
00062   (void) sender;  //suppress warning of unused parameter(s)
00063   MRSDIAG("AimHCL.cpp - AimHCL:myUpdate");
00064   ctrl_onObservations_->setValue(ctrl_inObservations_->to<mrs_natural>(), NOUPDATE);
00065   ctrl_onSamples_->setValue(ctrl_inSamples_->to<mrs_natural>(), NOUPDATE);
00066   ctrl_osrate_->setValue(ctrl_israte_->to<mrs_real>());
00067   ctrl_onObsNames_->setValue("AimHCL_" + ctrl_inObsNames_->to<mrs_string>() , NOUPDATE);
00068 
00069   //
00070   // Does the MarSystem need initialization?
00071   //
00072   if (initialized_lowpass_cutoff != ctrl_lowpass_cutoff_->to<mrs_real>()) {
00073     is_initialized = false;
00074   }
00075 
00076   if (!is_initialized) {
00077     InitializeInternal();
00078     is_initialized = true;
00079     initialized_lowpass_cutoff = ctrl_lowpass_cutoff_->to<mrs_real>();
00080   }
00081 
00082   //
00083   // Does the MarSystem need a reset?
00084   //
00085   if (reseted_inobservations != ctrl_inObservations_->to<mrs_natural>() ||
00086       reseted_lowpass_order != ctrl_lowpass_order_->to<mrs_natural>()) {
00087     is_reset = false;
00088   }
00089 
00090   if (!is_reset) {
00091     ResetInternal();
00092     is_reset = true;
00093     reseted_inobservations = ctrl_inObservations_->to<mrs_natural>();
00094     reseted_lowpass_order = ctrl_lowpass_order_->to<mrs_natural>();
00095   }
00096 
00097 }
00098 
00099 
00100 bool
00101 AimHCL::InitializeInternal() {
00102   time_constant_ = 1.0 / (2.0 * PI * ctrl_lowpass_cutoff_->to<mrs_real>());
00103   return true;
00104 }
00105 
00106 void
00107 AimHCL::ResetInternal() {
00108   xn_ = 0.0;
00109   yn_ = 0.0;
00110   yns_.clear();
00111   yns_.resize(ctrl_inObservations_->to<mrs_natural>());
00112   mrs_natural _lowpass_order = ctrl_lowpass_order_->to<mrs_natural>();
00113   for (int c = 0; c < ctrl_inObservations_->to<mrs_natural>(); ++c) {
00114     yns_[c].resize(_lowpass_order, 0.0);
00115   }
00116 }
00117 
00118 //
00119 // With do_log, the signal is first scaled up so that values <1.0 become
00120 // negligible. This just rescales the sample values to fill the range of a
00121 // 16-bit signed integer, then we lose the bottom bit of resolution. If the
00122 // signal was sampled at 16-bit resolution, there shouldn't be anything to
00123 // speak of there anyway. If it was sampled using a higher resolution, then
00124 // some data will be discarded.
00125 //
00126 void
00127 AimHCL::myProcess(realvec& in, realvec& out)
00128 {
00129   mrs_natural o,t;
00130   mrs_real _israte = ctrl_israte_->to<mrs_real>();
00131   mrs_natural _inObservations = ctrl_inObservations_->to<mrs_natural>();
00132   mrs_natural _inSamples = ctrl_inSamples_->to<mrs_natural>();
00133   mrs_natural _onSamples = ctrl_onSamples_->to<mrs_natural>();
00134   mrs_natural _lowpass_order = ctrl_lowpass_order_->to<mrs_natural>();
00135   mrs_bool _do_lowpass = ctrl_do_lowpass_->to<mrs_bool>();
00136   mrs_bool _do_log = ctrl_do_log_->to<mrs_bool>();
00137 
00138   mrs_natural _num_channels = _inObservations / 2;
00139   double b = exp(-1.0 / (_israte * time_constant_));
00140   double gain = 1.0 / (1.0 - b);
00141 
00142   for (o = 0; o < _num_channels; ++o) {
00143     for (t = 0; t < _inSamples; ++t) {
00144       // cout << "in(o,t)=" << in(o,t) << endl;
00145       if (in(o,t) < 0.0) {
00146         // cout << "s=zero" << endl;
00147         out(o, t) = 0.0;
00148       } else {
00149         double s = in(o,t);
00150         if (_do_log) {
00151           s *= pow(2.0, 15);
00152           if (s < 1.0) s = 1.0;
00153           s = 20.0 * log10(s);
00154         }
00155         // cout << "s=" << s << endl;
00156         out(o, t) = s;
00157       }
00158     }
00159     if (_do_lowpass) {
00160 
00161       for (int j = 0; j < _lowpass_order; j++) {
00162         for (int k = 0; k < _onSamples; ++k) {
00163           xn_ = out(o,k);
00164           yn_ = xn_ + b * yns_[o][j];
00165           yns_[o][j] = yn_;
00166           // cout << "gain=" << gain << endl;
00167           // cout << "yn_=" << yn_ << endl;
00168           out(o, k) = yn_ / gain;
00169         }
00170       }
00171     }
00172   }
00173 
00174   // Copy over the centre frequencies
00175   for (o = _num_channels; o < _num_channels * 2; ++o) {
00176     for (t = 0; t < _inSamples; ++t) {
00177       out(o, t) = in(o, t);
00178     }
00179   }
00180 
00181 }