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 "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 }