Marsyas
0.6.0-alpha
|
00001 /* 00002 ** Copyright (C) 1998-2010 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 "AimHCL2.h" 00020 #include "../common_source.h" 00021 00022 using std::ostringstream; 00023 using namespace Marsyas; 00024 00025 AimHCL2::AimHCL2(mrs_string name):MarSystem("AimHCL2",name) 00026 { 00027 is_initialized = false; 00028 initialized_lowpass_cutoff = 0; 00029 00030 is_reset = false; 00031 reseted_inobservations = 0; 00032 reseted_lowpass_order = 0; 00033 00034 addControls(); 00035 } 00036 00037 00038 AimHCL2::~AimHCL2() 00039 { 00040 } 00041 00042 00043 MarSystem* 00044 AimHCL2::clone() const 00045 { 00046 return new AimHCL2(*this); 00047 } 00048 00049 void 00050 AimHCL2::addControls() 00051 { 00052 addControl("mrs_bool/do_lowpass", true , ctrl_do_lowpass_); 00053 addControl("mrs_bool/do_log", false , ctrl_do_log_); 00054 addControl("mrs_real/lowpass_cutoff", 1200.0 , ctrl_lowpass_cutoff_); 00055 addControl("mrs_natural/lowpass_order", 2 , ctrl_lowpass_order_); 00056 } 00057 00058 void 00059 AimHCL2::myUpdate(MarControlPtr sender) 00060 { 00061 (void) sender; //suppress warning of unused parameter(s) 00062 MRSDIAG("AimHCL2.cpp - AimHCL2:myUpdate"); 00063 ctrl_onObservations_->setValue(ctrl_inObservations_->to<mrs_natural>(), NOUPDATE); 00064 ctrl_onSamples_->setValue(ctrl_inSamples_->to<mrs_natural>(), NOUPDATE); 00065 ctrl_osrate_->setValue(ctrl_israte_->to<mrs_real>()); 00066 ctrl_onObsNames_->setValue("AimHCL2_" + ctrl_inObsNames_->to<mrs_string>() , NOUPDATE); 00067 00068 // 00069 // Does the MarSystem need initialization? 00070 // 00071 if (initialized_lowpass_cutoff != ctrl_lowpass_cutoff_->to<mrs_real>()) { 00072 is_initialized = false; 00073 } 00074 00075 if (!is_initialized) { 00076 InitializeInternal(); 00077 is_initialized = true; 00078 initialized_lowpass_cutoff = ctrl_lowpass_cutoff_->to<mrs_real>(); 00079 } 00080 00081 // 00082 // Does the MarSystem need a reset? 00083 // 00084 if (reseted_inobservations != ctrl_inObservations_->to<mrs_natural>() || 00085 reseted_lowpass_order != ctrl_lowpass_order_->to<mrs_natural>()) { 00086 is_reset = false; 00087 } 00088 00089 if (!is_reset) { 00090 ResetInternal(); 00091 is_reset = true; 00092 reseted_inobservations = ctrl_inObservations_->to<mrs_natural>(); 00093 reseted_lowpass_order = ctrl_lowpass_order_->to<mrs_natural>(); 00094 } 00095 00096 } 00097 00098 00099 bool 00100 AimHCL2::InitializeInternal() { 00101 time_constant_ = 1.0 / (2.0 * PI * ctrl_lowpass_cutoff_->to<mrs_real>()); 00102 return true; 00103 } 00104 00105 void 00106 AimHCL2::ResetInternal() { 00107 xn_ = 0.0; 00108 yn_ = 0.0; 00109 yns_.clear(); 00110 yns_.resize(ctrl_inObservations_->to<mrs_natural>()); 00111 mrs_natural _lowpass_order = ctrl_lowpass_order_->to<mrs_natural>(); 00112 for (int c = 0; c < ctrl_inObservations_->to<mrs_natural>(); ++c) { 00113 yns_[c].resize(_lowpass_order, 0.0); 00114 } 00115 } 00116 00117 // 00118 // With do_log, the signal is first scaled up so that values <1.0 become 00119 // negligible. This just rescales the sample values to fill the range of a 00120 // 16-bit signed integer, then we lose the bottom bit of resolution. If the 00121 // signal was sampled at 16-bit resolution, there shouldn't be anything to 00122 // speak of there anyway. If it was sampled using a higher resolution, then 00123 // some data will be discarded. 00124 // 00125 void 00126 AimHCL2::myProcess(realvec& in, realvec& out) 00127 { 00128 mrs_natural o,t; 00129 mrs_real _israte = ctrl_israte_->to<mrs_real>(); 00130 mrs_natural _inObservations = ctrl_inObservations_->to<mrs_natural>(); 00131 mrs_natural _inSamples = ctrl_inSamples_->to<mrs_natural>(); 00132 mrs_natural _onSamples = ctrl_onSamples_->to<mrs_natural>(); 00133 mrs_natural _lowpass_order = ctrl_lowpass_order_->to<mrs_natural>(); 00134 mrs_bool _do_lowpass = ctrl_do_lowpass_->to<mrs_bool>(); 00135 mrs_bool _do_log = ctrl_do_log_->to<mrs_bool>(); 00136 00137 mrs_natural _num_channels = _inObservations; 00138 double b = exp(-1.0 / (_israte * time_constant_)); 00139 double gain = 1.0 / (1.0 - b); 00140 00141 for (o = 0; o < _num_channels; ++o) { 00142 for (t = 0; t < _inSamples; ++t) { 00143 // cout << "in(o,t)=" << in(o,t) << endl; 00144 if (in(o,t) < 0.0) { 00145 // cout << "s=zero" << endl; 00146 out(o, t) = 0.0; 00147 } else { 00148 double s = in(o,t); 00149 if (_do_log) { 00150 s *= pow(2.0, 15); 00151 if (s < 1.0) s = 1.0; 00152 s = 20.0 * log10(s); 00153 } 00154 // cout << "s=" << s << endl; 00155 out(o, t) = s; 00156 } 00157 } 00158 if (_do_lowpass) { 00159 00160 for (int j = 0; j < _lowpass_order; j++) { 00161 for (int k = 0; k < _onSamples; ++k) { 00162 xn_ = out(o,k); 00163 yn_ = xn_ + b * yns_[o][j]; 00164 yns_[o][j] = yn_; 00165 // cout << "gain=" << gain << endl; 00166 // cout << "yn_=" << yn_ << endl; 00167 out(o, k) = yn_ / gain; 00168 } 00169 } 00170 } 00171 } 00172 00173 00174 00175 }