Marsyas  0.6.0-alpha
/usr/src/RPM/BUILD/marsyas-0.6.0/src/marsyas/marsystems/ResampleSinc.cpp
Go to the documentation of this file.
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 "ResampleSinc.h"
00020 #include "../common_source.h"
00021 
00022 using namespace std;
00023 using namespace Marsyas;
00024 
00034 ResampleSinc::ResampleSinc(mrs_string name):MarSystem("ResampleSinc", name)
00035 {
00036   //Add any specific controls needed by ResampleSinc
00037   //(default controls all MarSystems should have
00038   //were already added by MarSystem::addControl(),
00039   //called by :MarSystem(name) constructor).
00040   //If no specific controls are needed by a MarSystem
00041   //there is no need to implement and call this addControl()
00042   //method (see for e.g. Rms.cpp)
00043   addControls();
00044 }
00045 
00046 ResampleSinc::ResampleSinc(const ResampleSinc& a) : MarSystem(a)
00047 {
00048   // For any MarControlPtr in a MarSystem
00049   // it is necessary to perform this getctrl
00050   // in the copy constructor in order for cloning to work
00051 
00052 
00053 //Controls:
00054   //mrs_bool ctrl_windowedMode  -   false:  apply sinc interpolation directly
00055   //                                true:   (default) use values of Kaiser Window and interpolate linearly between them if necessary
00056   //mrs_bool ctrl_samplingRateAdjustmentMode - adjust new resulting SamplingRate for following Marsystems
00057   //mrs_real stretch - desired stretch ratio (number of output samples = input number of samples*stretch)
00058   //mrs_real offStart - (default:0) offset from the start (towards the end) of the Samples (if only a part of the samples should be used to interpolate)
00059   //mrs_real offEnd - (default:0) offset from the end (towards the start) of the Samples (if only a part of the samples should be used to interpolate)
00060 
00061 
00062   ctrl_offStart_ = getctrl("mrs_real/offStart");
00063   ctrl_offEnd_ = getctrl("mrs_real/offEnd");
00064   ctrl_windowedMode_ = getctrl("mrs_bool/windowedMode");
00065   ctrl_samplingRateAdjustmentMode_ = getctrl("mrs_bool/samplingRateAdjustmentMode");
00066   ctrl_stretch_ = getctrl("mrs_real/stretch");
00067 
00068 }
00069 
00070 ResampleSinc::~ResampleSinc()
00071 {
00072 
00073 }
00074 
00075 MarSystem*
00076 ResampleSinc::clone() const
00077 {
00078   return new ResampleSinc(*this);
00079 }
00080 
00081 void
00082 ResampleSinc::addControls()
00083 {
00084   //Add specific controls needed by this MarSystem.
00085   addctrl("mrs_real/offStart", 0.0, ctrl_offStart_);
00086   addctrl("mrs_real/offEnd", 0.0, ctrl_offEnd_);
00087   addctrl("mrs_bool/samplingRateAdjustmentMode", (mrs_bool)true , ctrl_samplingRateAdjustmentMode_);
00088   addctrl("mrs_bool/windowedMode", (mrs_bool)false , ctrl_windowedMode_);
00089   addctrl("mrs_real/stretch", 1.0 , ctrl_stretch_);
00090   setctrlState("mrs_real/stretch", true);
00091   setctrlState("mrs_bool/samplingRateAdjustmentMode",(mrs_bool)true);
00092 
00093 }
00094 
00095 void
00096 ResampleSinc::myUpdate(MarControlPtr sender)
00097 {
00098   MarSystem::myUpdate(sender);
00099 
00100 
00101   mrs_real alpha = ctrl_stretch_->to<mrs_real>();
00102 
00103   mrs_natural onSamples = (mrs_natural) (alpha * ctrl_inSamples_->to<mrs_natural>());
00104 
00105   ctrl_onSamples_->setValue(onSamples, NOUPDATE);
00106 
00107   arrx_.allocate(onSamples);
00108 
00109   //cout << "updating: " << ctrl_inSamples_->to<mrs_natural>() << endl;
00110   ctrl_onObservations_->setValue(ctrl_inObservations_->to<mrs_natural>());
00111   if (!(ctrl_samplingRateAdjustmentMode_->to<mrs_bool>()))
00112   {
00113     alpha=1.0;
00114   }
00115 
00116   ctrl_osrate_->setValue(ctrl_israte_->to<mrs_real>()*alpha);
00117   mrs_string inObsNames = ctrl_inObsNames_->to<mrs_string>();
00118   // Add prefix to the observation names.
00119   ctrl_onObsNames_->setValue(obsNamesAddPrefix(inObsNames, "ResampleSinc_"), NOUPDATE);
00120 
00121 }
00122 
00123 mrs_real
00124 ResampleSinc::sinc(mrs_real t)
00125 {
00126   mrs_real ret=0.0;
00127   if (t==0)
00128     ret=1.0;
00129   else
00130     ret=sin(t*PI)/(t*PI);
00131   return ret;
00132 }
00133 
00134 mrs_real
00135 ResampleSinc::window(mrs_real position)
00136 {
00137   mrs_realvec y;
00138   y.create(11);
00139 
00140 //    Kaiser Window beta=2, length 11
00141   y(0)=1;
00142   y(1)=1.393725584134;
00143   y(2)=1.749980639738;
00144   y(3)=2.033757714070;
00145   y(4)=2.21650903826;
00146   y(5)=2.279585302336;
00147 
00148 //    Kaiser Window beta=1, length 13
00149 //    y(0)=1;
00150 //    y(1)=1.077860145694;
00151 //    y(2)=1.143786491151;
00152 //    y(3)=1.196474329913;
00153 //    y(4)=1.234877004454;
00154 //    y(5)=1.258229528804;
00155 //    y(6)=1.266065877752;
00156 
00157 //    Kaiser Window beta=2, length 13
00158 //    y(0)=1.0;
00159 //    y(1)=1.3297043679778717;
00160 //    y(2)=1.6376481570588971;
00161 //    y(3)=1.9029098945382872;
00162 //    y(4)=2.1070523256224973;
00163 //    y(5)=2.2356659845728475;
00164 //    y(6)=2.2795853023360673;
00165 
00166 
00167   mrs_real divisor=2.279585302336;
00168 
00169   for (mrs_natural i=0; i<y.getSize(); ++i)
00170 
00171     if (i<=y.getSize()/2)
00172       y(i)=y(i)/divisor;
00173     else
00174       y(i)=y(y.getSize()-i-1);
00175 
00176   if ((position <-5) | (position > 5))
00177     return 0;
00178 
00179   mrs_natural index=0;
00180   while (index+1<5+position)
00181   {
00182     index=index+1;
00183   }
00184   mrs_real difference=5+position-index;
00185   return (1-difference)*y(index)+difference*y(index+1);
00186 }
00187 
00188 
00189 void
00190 ResampleSinc::myProcess(realvec& in, realvec& out)
00191 {
00192   mrs_bool windowedMode = ctrl_windowedMode_->to<mrs_bool>();
00193   mrs_real offStart=ctrl_offStart_->to<mrs_real>();
00194   mrs_real offEnd=ctrl_offEnd_->to<mrs_real>();
00195   mrs_real ratio=(inSamples_-1-offStart-offEnd)/(mrs_real)(onSamples_-1);
00196 
00197   for(mrs_natural i=0; i<onSamples_; ++i)
00198     arrx_(i)=offStart+i*ratio;
00199 
00200   mrs_natural winlength = 5; //maximum windowlength is also enforced by the window function
00201 
00202   for (mrs_natural o=0; o<inObservations_; o++)
00203   {
00204     for (int i=0; i<onSamples_; ++i)
00205     {
00206       mrs_real sample = 0;
00207       for (mrs_natural ansinks=0; ansinks<inSamples_; ansinks++)
00208       {
00209         mrs_real sincIndex = arrx_(i)-ansinks;
00210         if (abs(sincIndex)<winlength)
00211         {
00212           if (windowedMode)
00213           {
00214             sample += in(o,ansinks)*sinc(sincIndex)*window(sincIndex);
00215           }
00216           else
00217           {
00218             sample += in(o,ansinks)*sinc(sincIndex);
00219           }
00220         }
00221       }
00222       out(o,i) = sample;
00223     }
00224   }
00225 }