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 "PeakSynthOscBank.h" 00020 #include <marsyas/peakView.h> 00021 00022 00023 using std::ostringstream; 00024 using std::cout; 00025 using std::endl; 00026 00027 using namespace Marsyas; 00028 00029 PeakSynthOscBank::PeakSynthOscBank(mrs_string name):MarSystem("PeakSynthOscBank",name) 00030 { 00031 psize_ = 0; 00032 size_ = 0; 00033 00034 addControls(); 00035 } 00036 00037 PeakSynthOscBank::PeakSynthOscBank(const PeakSynthOscBank& a):MarSystem(a) 00038 { 00039 ctrl_harmonize_ = getctrl("mrs_realvec/harmonize"); 00040 } 00041 00042 PeakSynthOscBank::~PeakSynthOscBank() 00043 { 00044 } 00045 00046 MarSystem* 00047 PeakSynthOscBank::clone() const 00048 { 00049 return new PeakSynthOscBank(*this); 00050 } 00051 00052 void 00053 PeakSynthOscBank::addControls() 00054 { 00055 addctrl("mrs_natural/Interpolation", MRS_DEFAULT_SLICE_NSAMPLES/4); 00056 setctrlState("mrs_natural/Interpolation", true); 00057 addctrl("mrs_real/PitchShift", 1.0); 00058 setctrlState("mrs_real/PitchShift", true); 00059 addctrl("mrs_real/SynthesisThreshold", 0.0); 00060 setctrlState("mrs_real/SynthesisThreshold", true); 00061 addctrl("mrs_realvec/harmonize", realvec(), ctrl_harmonize_); 00062 setctrlState("mrs_realvec/harmonize", true); 00063 } 00064 00065 void 00066 PeakSynthOscBank::myUpdate(MarControlPtr sender) 00067 { 00068 (void) sender; //suppress warning of unused parameter(s) 00069 setctrl("mrs_natural/onSamples", getctrl("mrs_natural/Interpolation")); 00070 setctrl("mrs_natural/onObservations", (mrs_natural)1); 00071 setctrl("mrs_real/osrate", getctrl("mrs_real/israte")); 00072 00073 inObservations_ = getctrl("mrs_natural/inObservations")->to<mrs_natural>(); 00074 00075 nbH_ = (ctrl_harmonize_->to<mrs_realvec>().getSize()-1)/2; 00076 // replace this !! 00077 if (!nbH_) 00078 { 00079 MarControlAccessor acc(ctrl_harmonize_, NOUPDATE); 00080 realvec& harmonize = acc.to<mrs_realvec>(); 00081 harmonize.stretch(3); 00082 harmonize(1) = 1.0; 00083 harmonize(2) = 1.0; 00084 } 00085 00086 size_ = 2048*nbH_; 00087 00088 //if (size_ != psize_) 00089 { 00090 lastamp_.stretch(size_); 00091 nextamp_.stretch(size_); 00092 lastfreq_.stretch(size_); 00093 nextfreq_.stretch(size_); 00094 index_.stretch(size_); 00095 nextindex_.stretch(size_); 00096 N_ = inObservations_/peakView::nbPkParameters; 00097 00098 L_ = 8192; 00099 table_.stretch(L_); 00100 00101 for (mrs_natural t=0; t < L_; t++) 00102 { 00103 table_(t) = cos(TWOPI * t/L_); 00104 } 00105 psize_ = size_; 00106 } 00107 // N_ = inObservations_/nbPkParameters; 00108 P_ = getctrl("mrs_real/PitchShift")->to<mrs_real>(); 00109 I_ = getctrl("mrs_natural/Interpolation")->to<mrs_natural>(); 00110 S_ = getctrl("mrs_real/SynthesisThreshold")->to<mrs_real>(); 00111 R_ = getctrl("mrs_real/osrate")->to<mrs_real>(); 00112 } 00113 00114 void 00115 PeakSynthOscBank::myProcess(realvec& in, realvec& out) 00116 { 00117 mrs_natural t,c; 00118 out.setval(0.0); 00119 00120 if (P_ > 1.0) 00121 NP_ = (mrs_natural)(N_/P_); 00122 else 00123 NP_ = N_; 00124 00125 Iinv_ = (mrs_real)(1.0 / I_); 00126 Pinc_ = P_ * L_ / R_; 00127 00128 nextamp_.setval(0); 00129 nextfreq_.setval(0); 00130 nextindex_.setval(0); 00131 00132 // FIXME This line defines a (possibly) unused variable 00133 // bool flag = false; 00134 00135 if(nbH_) 00136 { 00137 for(mrs_natural j=0 ; j<nbH_ ; j++) 00138 { 00139 mrs_real mulF = ctrl_harmonize_->to<mrs_realvec>()(1+j*2); 00140 mrs_real mulA = ctrl_harmonize_->to<mrs_realvec>()(2+j*2); 00141 00142 for (t=0; t < NP_; t++) 00143 { 00144 mrs_natural index = (mrs_natural) ceil(in(t)/R_*2048*2+0.5); 00145 if (in(t) == 0.0 || index >= 2048) 00146 break; 00147 index+=j*2048; 00148 00149 /* save current values for next iteration */ 00150 00151 if(nextfreq_(index)) 00152 { 00153 cout << "PROBLEM"<<endl; 00154 } 00155 nextamp_(index) = in(t+NP_)*mulA; 00156 nextfreq_(index) = in(t)*Pinc_*mulF; 00157 } 00158 } 00159 } 00160 00161 for (mrs_natural t=0; t < nextamp_.getSize(); t++) 00162 { 00163 // cout << endl << index << endl; 00164 if(lastfreq_(t) && nextfreq_(t)) 00165 { 00166 f_ = lastfreq_(t); 00167 finc_ = (nextfreq_(t) - f_)*Iinv_; 00168 } 00169 else if(nextfreq_(t)) 00170 { 00171 f_ = nextfreq_(t); 00172 finc_=0; 00173 } 00174 else 00175 { 00176 f_ = lastfreq_(t); 00177 finc_=0; 00178 } 00179 00180 a_ = lastamp_(t); 00181 ainc_ = (nextamp_(t) - a_)*Iinv_; 00182 00183 address_ = index_(t); 00184 00185 /* avoid extra computing */ 00186 if ((a_ != 0.0 || ainc_!=0.0)) 00187 { 00188 // accumulate I samples from each oscillator 00189 // into output slice 00190 for (c=0; c < I_; ++c) 00191 { 00192 naddress_ = (mrs_natural)address_ % L_; 00193 out(0, c) += a_ * table_(naddress_); 00194 address_ += f_; 00195 00196 while (address_ >= L_) 00197 address_ -= L_; 00198 while (address_ < 0) 00199 address_ += L_; 00200 00201 a_ += ainc_; 00202 f_ += finc_; 00203 } 00204 // move down one parenthesis 00205 } 00206 nextindex_(t) = address_; 00207 } 00208 00209 lastamp_ = nextamp_; 00210 lastfreq_ = nextfreq_; 00211 index_ = nextindex_; 00212 }