00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "Windowing.h"
00020 #include <stdexcept>
00021
00022 using namespace std;
00023 using namespace Marsyas;
00024
00025 Windowing::Windowing(mrs_string name):MarSystem("Windowing",name)
00026 {
00027 zeroPadding_ = 0;
00028 size_ = 0;
00029 addcontrols();
00030 }
00031
00032 Windowing::Windowing(const Windowing& a):MarSystem(a)
00033 {
00034 ctrl_type_ = getctrl("mrs_string/type");
00035 ctrl_zeroPhasing_ = getctrl("mrs_bool/zeroPhasing");
00036 ctrl_zeroPadding_ = getctrl("mrs_natural/zeroPadding");
00037 ctrl_size_ = getctrl("mrs_natural/size");
00038 ctrl_variance_ = getctrl("mrs_real/variance");
00039 ctrl_normalize_ = getctrl("mrs_bool/normalize");
00040 zeroPadding_ = 0;
00041 size_ = 0;
00042 }
00043
00044 Windowing::~Windowing()
00045 {
00046 }
00047
00048 MarSystem*
00049 Windowing::clone() const
00050 {
00051 return new Windowing(*this);
00052 }
00053
00054 void
00055 Windowing::addcontrols()
00056 {
00057 addctrl("mrs_string/type", "Hamming", ctrl_type_);
00058 addctrl("mrs_bool/zeroPhasing", false, ctrl_zeroPhasing_);
00059 addctrl("mrs_natural/zeroPadding", 0, ctrl_zeroPadding_);
00060 addctrl("mrs_natural/size", 0, ctrl_size_);
00061 addctrl("mrs_real/variance", 0.4, ctrl_variance_);
00062 addctrl("mrs_bool/normalize", false, ctrl_normalize_);
00063
00064 setctrlState("mrs_string/type", true);
00065 setctrlState("mrs_bool/zeroPhasing", true);
00066 setctrlState("mrs_natural/zeroPadding", true);
00067 setctrlState("mrs_natural/size", true);
00068 setctrlState("mrs_real/variance", true);
00069 setctrlState("mrs_bool/normalize", true);
00070 }
00071
00072
00073
00074 void
00075 Windowing::myUpdate(MarControlPtr sender)
00076 {
00077 mrs_natural t;
00078 (void) sender;
00079 mrs_string type = ctrl_type_->to<mrs_string>();
00080
00081 ctrl_onObservations_->setValue(ctrl_inObservations_, NOUPDATE);
00082 ctrl_osrate_->setValue(ctrl_israte_, NOUPDATE);
00083
00084
00085 mrs_string inObsNames = ctrl_inObsNames_->to<mrs_string>();
00086 mrs_string prefix = mrs_string("Win") + type + mrs_string("_");
00087 ctrl_onObsNames_->setValue(obsNamesAddPrefix(inObsNames, prefix), NOUPDATE);
00088
00089
00090 if (ctrl_zeroPadding_->to<mrs_natural>() != onSamples_- inSamples_)
00091 {
00092
00093 if (ctrl_zeroPadding_->to<mrs_natural>() < 0)
00094 {
00095 ctrl_zeroPadding_->setValue(0, NOUPDATE);
00096 }
00097 ctrl_size_->setValue(ctrl_inSamples_->to<mrs_natural>() +
00098 ctrl_zeroPadding_->to<mrs_natural>(), NOUPDATE);
00099 onSamples_ = ctrl_size_->to<mrs_natural>();
00100 }
00101
00102 if (ctrl_size_->to<mrs_natural>() != onSamples_)
00103 {
00104
00105 if (ctrl_size_->to<mrs_natural>() < inSamples_)
00106 {
00107 ctrl_size_->setValue(inSamples_, NOUPDATE);
00108 }
00109 ctrl_zeroPadding_->setValue(ctrl_size_->to<mrs_natural>() -
00110 ctrl_inSamples_->to<mrs_natural>(), NOUPDATE);
00111 }
00112
00113 ctrl_onSamples_->setValue(ctrl_size_, NOUPDATE);
00114
00115
00116 if (ctrl_zeroPhasing_->isTrue())
00117 {
00118 delta_ = inSamples_/2+1;
00119 }
00120 else
00121 {
00122 delta_=0;
00123 }
00124
00125
00126 tmp_.create(inSamples_);
00127
00128
00129
00130 envelope_.create(inSamples_);
00131
00132 if (type == "Hamming")
00133 {
00134 windowingFillHamming(envelope_);
00135 }
00136 else if (type == "Hanning" || type == "Hann")
00137 {
00138 windowingFillHanning(envelope_);
00139 }
00140 else if (type == "Triangle")
00141 {
00142 windowingFillTriangle(envelope_);
00143 }
00144 else if (type == "Bartlett")
00145 {
00146 windowingFillBartlett(envelope_);
00147 }
00148 else if (type == "Gaussian")
00149 {
00150 windowingFillGaussian(envelope_, ctrl_variance_->to<mrs_real>());
00151 }
00152 else if (type == "Blackman")
00153 {
00154 windowingFillBlackman(envelope_, 0.16);
00155 }
00156 else if (type == "Blackman-Harris")
00157 {
00158 windowingFillBlackmanHarris(envelope_);
00159 }
00160 else if (type == "Cosine" || type == "Sine")
00161 {
00162 windowingFillCosine(envelope_);
00163 }
00164 else
00165 {
00166 ostringstream oss;
00167 oss << "Invalid windowing type \"" << type << "\"";
00168 throw invalid_argument(oss.str());
00169 }
00170
00171
00172
00173 if (ctrl_normalize_->to<mrs_bool>() == true)
00174 {
00175 mrs_real sum = 0.0;
00176
00177 for (t =0; t < inSamples_; t++)
00178 {
00179 sum += envelope_(t);
00180 }
00181 mrs_real afac = (mrs_real)(2.0 /sum);
00182 envelope_ *= afac;
00183 ctrl_normalize_->setValue(false, NOUPDATE);
00184 }
00185
00186
00187 }
00188
00189 void
00190 Windowing::myProcess(realvec& in, realvec& out)
00191 {
00192 out.setval(0.0);
00193 mrs_natural o,t;
00194
00195 for (o=0; o < inObservations_; o++)
00196 {
00197
00198 if (ctrl_zeroPhasing_->isTrue())
00199 {
00200
00201 for (t = 0; t < inSamples_; t++)
00202 {
00203 tmp_(t) = in(o,t)*envelope_(t);
00204 }
00205 for (t = 0; t < inSamples_/2; t++)
00206 {
00207 out(o,t)=tmp_((t+delta_)%inSamples_);
00208 }
00209 for (t = inSamples_/2; t < inSamples_; t++)
00210 {
00211 out(o,t+(onSamples_-inSamples_))=tmp_((t+delta_)%inSamples_);
00212 }
00213 }
00214 else
00215 {
00216 for (t=0; t< inSamples_; ++t)
00217 {
00218 out(o,t) = in(o,t) * envelope_(t);
00219 }
00220 }
00221 }
00222 }
00223
00224
00225
00242 void
00243 Marsyas::windowingFillRaisedCosine(realvec& envelope, mrs_real alpha, mrs_real beta)
00244 {
00245 mrs_natural N = envelope.getSize();
00246 for (mrs_natural t = 0; t < N; t++)
00247 {
00248 envelope(t) = alpha - beta * cos(2.0 * PI * t / (N - 1.0));
00249 }
00250 }
00251
00252
00253
00254
00255
00263 void
00264 Marsyas::windowingFillTriangle(realvec& envelope)
00265 {
00266 mrs_natural N = envelope.getSize();
00267 for (mrs_natural t = 0; t < N; t++)
00268 {
00269 envelope(t) = 2.0/N * (N/2.0 - abs(t - (N - 1.0)/2.0));
00270 }
00271 }
00272
00280 void
00281 Marsyas::windowingFillBartlett(realvec& envelope)
00282 {
00283 mrs_natural N = envelope.getSize();
00284 for (mrs_natural t = 0; t < N; t++)
00285 {
00286 envelope(t) = 2.0/(N-1.0) * ((N-1.0)/2.0 - abs(t - (N - 1.0)/2.0));
00287 }
00288 }
00289
00297 void Marsyas::windowingFillGaussian(realvec& envelope, mrs_real sigma)
00298 {
00299 mrs_natural N = envelope.getSize();
00300 mrs_real tmp;
00301 for (mrs_natural t = 0; t < N; t++)
00302 {
00303 tmp = (t - (N - 1.0) / 2.0) / (sigma * (N - 1.0) / 2.0);
00304 envelope(t) = exp(-0.5*tmp*tmp);
00305 }
00306 }
00307
00315 void Marsyas::windowingFillBlackman(realvec& envelope, mrs_real alpha)
00316 {
00317 mrs_natural N = envelope.getSize();
00318 mrs_real a0 = (1.0 - alpha) / 2.0;
00319 mrs_real a2 = alpha / 2.0;
00320 for (mrs_natural t = 0; t < N; t++)
00321 {
00322 envelope(t) = a0 - 0.5 * cos(2.0 * PI * t / (N - 1.0))
00323 + a2 * cos(4.0 * PI * t / (N - 1.0));
00324 }
00325 }
00326
00335 void Marsyas::windowingFillBlackmanHarris(realvec& envelope)
00336 {
00337 mrs_natural N = envelope.getSize();
00338 mrs_real a0 = 0.35875, a1 = 0.48829, a2 = 0.14128, a3 = 0.01168;
00339 for (mrs_natural t = 0; t < N; t++)
00340 {
00341 envelope(t) = a0 - a1 * cos(2.0 * PI * t / (N - 1.0))
00342 + a2 * cos(4.0 * PI * t / (N - 1.0))
00343 - a3 * cos(6.0 * PI * t / (N - 1.0));
00344 }
00345 }
00346
00354 void Marsyas::windowingFillCosine(realvec& envelope)
00355 {
00356 mrs_natural N = envelope.getSize();
00357 for (mrs_natural t = 0; t < N; t++)
00358 {
00359 envelope(t) = sin(PI * t / (N - 1.0));
00360 }
00361 }