Marsyas
0.6.0-alpha
|
00001 /* 00002 ** Copyright (C) 2010 Stefaan Lippens 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 "RunningAutocorrelation.h" 00020 #include "../common_source.h" 00021 00022 // For min(). 00023 #include <algorithm> 00024 00025 using namespace std; 00026 using namespace Marsyas; 00027 00028 RunningAutocorrelation::RunningAutocorrelation(mrs_string name) : 00029 MarSystem("RunningAutocorrelation", name) 00030 { 00032 addControls(); 00033 } 00034 00035 RunningAutocorrelation::RunningAutocorrelation(const RunningAutocorrelation& a) : 00036 MarSystem(a) 00037 { 00040 ctrl_maxLag_ = getctrl("mrs_natural/maxLag"); 00041 ctrl_normalize_ = getctrl("mrs_bool/normalize"); 00042 ctrl_doNotNormalizeForLag0_ = getctrl("mrs_bool/doNotNormalizeForLag0"); 00043 ctrl_clear_ = getctrl("mrs_bool/clear"); 00044 ctrl_unfoldToObservations_ = getctrl("mrs_bool/unfoldToObservations"); 00045 } 00046 00047 RunningAutocorrelation::~RunningAutocorrelation() 00048 { 00049 } 00050 00051 MarSystem* 00052 RunningAutocorrelation::clone() const 00053 { 00054 return new RunningAutocorrelation(*this); 00055 } 00056 00057 void RunningAutocorrelation::addControls() 00058 { 00060 addctrl("mrs_natural/maxLag", 15, ctrl_maxLag_); 00061 setctrlState("mrs_natural/maxLag", true); 00062 addctrl("mrs_bool/normalize", false, ctrl_normalize_); 00063 setctrlState("mrs_bool/normalize", true); 00064 addctrl("mrs_bool/doNotNormalizeForLag0", false, 00065 ctrl_doNotNormalizeForLag0_); 00066 setctrlState("mrs_bool/doNotNormalizeForLag0", true); 00067 addctrl("mrs_bool/clear", false, ctrl_clear_); 00068 setctrlState("mrs_bool/clear", true); 00069 addctrl("mrs_bool/unfoldToObservations", false, ctrl_unfoldToObservations_); 00070 setctrlState("mrs_bool/unfoldToObservations", true); 00071 } 00072 00076 mrs_string prefixObservationNamesWithAutocorrelationUnfoldingPrefixes_( 00077 mrs_string inObservationNames, mrs_bool normalize, 00078 mrs_bool doNotNormalizeForLag0, mrs_natural maxLag) 00079 { 00080 vector<mrs_string> inObsNames = obsNamesSplit(inObservationNames); 00081 mrs_string onObsNames(""); 00082 for (vector<mrs_string>::iterator it = inObsNames.begin(); it 00083 != inObsNames.end(); it++) 00084 { 00085 for (int lag = 0; lag <= maxLag; lag++) 00086 { 00087 ostringstream oss; 00088 if (normalize && !(doNotNormalizeForLag0 && lag == 0)) 00089 { 00090 oss << "Normalized"; 00091 } 00092 oss << "Autocorr" << lag << "_" << (*it) << ","; 00093 onObsNames += oss.str(); 00094 } 00095 00096 } 00097 return onObsNames; 00098 00099 } 00100 00101 void RunningAutocorrelation::myUpdate(MarControlPtr sender) 00102 { 00103 (void) sender; //suppress warning of unused parameter(s) 00104 MRSDIAG("RunningAutocorrelation.cpp - RunningAutocorrelation:myUpdate"); 00105 00106 // Update the cache of the control values. 00107 maxLag_ = ctrl_maxLag_->to<mrs_natural> (); 00108 if (maxLag_ < 0) 00109 { 00110 MRSERR("maxLag should be greater than zero."); 00111 // Setting it to zero to be sure. 00112 maxLag_ = 0; 00113 } 00114 normalize_ = ctrl_normalize_->to<mrs_bool> (); 00115 doNotNormalizeForLag0_ = ctrl_doNotNormalizeForLag0_->to<mrs_bool> (); 00116 unfoldToObservations_ = ctrl_unfoldToObservations_->to<mrs_bool> (); 00117 00118 // Configure output flow. 00119 mrs_natural onObservations = unfoldToObservations_ ? inObservations_ 00120 * (maxLag_ + 1) : inObservations_; 00121 mrs_natural onSamples = unfoldToObservations_ ? 1 : maxLag_ + 1; 00122 ctrl_onSamples_->setValue(onSamples, NOUPDATE); 00123 ctrl_onObservations_->setValue(onObservations, NOUPDATE); 00124 ctrl_osrate_->setValue(ctrl_israte_, NOUPDATE); 00125 // Handle the observation names. 00126 mrs_string onObsNames = ctrl_inObsNames_->to<mrs_string> (); 00127 if (unfoldToObservations_) 00128 { 00129 onObsNames 00130 = prefixObservationNamesWithAutocorrelationUnfoldingPrefixes_( 00131 onObsNames, normalize_, doNotNormalizeForLag0_, maxLag_); 00132 } 00133 ctrl_onObsNames_->setValue(onObsNames, NOUPDATE); 00134 00135 // Allocate and initialize the buffers and counters. 00136 this->acBuffer_.stretch(inObservations_, maxLag_ + 1); 00137 this->acBuffer_.setval(0.0); 00138 this->memory_.stretch(inObservations_, maxLag_); 00139 this->memory_.setval(0.0); 00140 00141 // We just cleared the internal buffers, so we should reset the clear control. 00142 ctrl_clear_->setValue(false, NOUPDATE); 00143 } 00144 00145 void RunningAutocorrelation::myProcess(realvec& in, realvec& out) 00146 { 00148 for (mrs_natural i = 0; i < inObservations_; ++i) 00149 { 00150 // Calculate the autocorrelation terms 00151 for (mrs_natural lag = 0; lag <= maxLag_; lag++) 00152 { 00153 // For the first part, we need the memory. 00154 for (mrs_natural n = 0; n < min(lag, inSamples_); n++) 00155 { 00156 acBuffer_(i, lag) += in(i, n) * memory_(i, maxLag_ - lag + n); 00157 } 00158 // For the second part, we have enough with the input slice. 00159 for (mrs_natural n = lag; n < inSamples_; n++) 00160 { 00161 acBuffer_(i, lag) += in(i, n) * in(i, n - lag); 00162 } 00163 } 00164 00165 // Store result in output vector. 00166 mrs_natural u = (mrs_natural) unfoldToObservations_; 00167 mrs_natural o_base = unfoldToObservations_ ? i * (maxLag_ + 1) : i; 00168 for (mrs_natural lag = 0; lag <= maxLag_; lag++) 00169 { 00170 out(o_base + u * lag, (1 - u) * lag) = acBuffer_(i, lag); 00171 00172 } 00173 // Do the (optional) normalization. 00174 if (normalize_ && acBuffer_(i, 0) > 0.0) 00175 { 00176 mrs_natural lag = doNotNormalizeForLag0_ ? 1 : 0; 00177 for (; lag <= maxLag_; lag++) 00178 { 00179 out(o_base + u * lag, (1 - u) * lag) /= acBuffer_(i, 0); 00180 } 00181 } 00182 00183 // Remember the last samples for next time. 00184 // First, shift samples in memory (if needed). 00185 for (mrs_natural m = 0; m < maxLag_ - inSamples_; m++) 00186 { 00187 memory_(i, m) = memory_(i, m + inSamples_); 00188 } 00189 // Second, copy over samples from input. 00190 for (mrs_natural m = 1; m <= min(maxLag_, inSamples_); m++) 00191 { 00192 memory_(i, maxLag_ - m) = in(i, inSamples_ - m); 00193 } 00194 } 00195 }