Marsyas
0.6.0-alpha
|
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 }