Marsyas
0.6.0-alpha
|
00001 /* 00002 ** Copyright (C) 1998-2011 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 "ADRessSpectrum.h" 00020 00021 00022 using std::ostringstream; 00023 using std::abs; 00024 00025 using namespace Marsyas; 00026 00027 ADRessSpectrum::ADRessSpectrum(mrs_string name):MarSystem("ADRessSpectrum", name) 00028 { 00029 addControls(); 00030 N2_ = 0; 00031 } 00032 00033 ADRessSpectrum::ADRessSpectrum(const ADRessSpectrum& a) : MarSystem(a) 00034 { 00035 N2_ = a.N2_; 00036 ctrl_d_ = getctrl("mrs_real/d"); 00037 ctrl_H_ = getctrl("mrs_real/H"); 00038 } 00039 00040 ADRessSpectrum::~ADRessSpectrum() 00041 { 00042 } 00043 00044 MarSystem* 00045 ADRessSpectrum::clone() const 00046 { 00047 return new ADRessSpectrum(*this); 00048 } 00049 00050 void 00051 ADRessSpectrum::addControls() 00052 { 00053 addctrl("mrs_real/d", 0.5, ctrl_d_); 00054 addctrl("mrs_real/H", 0.5, ctrl_H_); 00055 } 00056 00057 void 00058 ADRessSpectrum::myUpdate(MarControlPtr sender) 00059 { 00060 (void) sender; //suppress warning of unused parameter(s) 00061 00062 mrs_real pN2 = N2_; 00063 00064 //left and right channels ADRess info is stacked vertically in the input 00065 N2_ = ctrl_inObservations_->to<mrs_natural>() / 2; // = N/2+1 spectrum points for each channel 00066 00067 ctrl_onSamples_->setValue(1, NOUPDATE); 00068 //output a complex spectrum for a single channel 00069 ctrl_onObservations_->setValue(((N2_-1)*2)); //N 00070 00071 if(pN2 != N2_) 00072 { 00073 ostringstream oss; 00074 //Left channel 00075 oss << "ADRessSpectrum_rbin_0" << ","; //DC bin (only has real part) 00076 oss << "ADRessSpectrum_rbin_" << N2_-1 << ","; // = N/2, i.e. Nyquist bin (only has real part) 00077 for (mrs_natural n=2; n < N2_; n++) 00078 { 00079 oss << "ADRessSpectrum_rbin_" << n-1 << ","; 00080 oss << "ADRessSpectrum_ibin_" << n-1 << ","; 00081 } 00082 ctrl_onObsNames_->setValue(oss.str(), NOUPDATE); 00083 } 00084 00085 beta_ = ctrl_onSamples_->to<mrs_natural>()-2; 00086 } 00087 00088 void 00089 ADRessSpectrum::myProcess(realvec& in, realvec& out) 00090 { 00091 mrs_natural t; 00092 out.setval(0.0); 00093 00094 //output spectrum of the "selected" source, given d and H 00095 mrs_natural H = (mrs_natural)(beta_* ctrl_H_->to<mrs_natural>()); 00096 if(H < 0) 00097 { 00098 H = 0; 00099 ctrl_H_->setValue(0.0); 00100 } 00101 if(H > beta_) 00102 { 00103 H = beta_; 00104 ctrl_H_->setValue(1.0); 00105 } 00106 00107 mrs_natural H2 = H/2; 00108 00109 mrs_natural d = (mrs_natural)(beta_*ctrl_d_->to<mrs_real>()); 00110 if(d < 0) 00111 { 00112 d = 0; 00113 ctrl_d_->setValue(0.0); 00114 } 00115 if(d > beta_) 00116 { 00117 d = beta_; 00118 ctrl_d_->setValue(1.0); 00119 } 00120 00121 mrs_real mag = 0; 00122 mrs_real phase = 0; 00123 mrs_real azim = 0; 00124 00125 00126 for(mrs_natural k=0; k < N2_; ++k) 00127 { 00128 //get magnitude, phase and azimuth of bin k from input 00129 mag = 0.0; 00130 for(t=0; t <= beta_; ++t) 00131 { 00132 //search for non-zero values in azimuth plane 00133 azim = -1; 00134 if(in(k,t+1) > 0.0) 00135 { 00136 azim = t; 00137 mag = in(k,t+1); 00138 phase = in(k, 0); 00139 break; 00140 } 00141 if(in(k+N2_,t+1) > 0.0) 00142 { 00143 azim = beta_*2-t; 00144 mag = in(k+N2_,t+1); 00145 phase = in(k+N2_, 0); 00146 break; 00147 } 00148 } 00149 00150 if(azim < 0) 00151 { 00152 //no sound at this bin, 00153 //so do not send anything to output 00154 continue; 00155 } 00156 00157 //check if bin is inside specified range, 00158 //otherwise, send nothing to output 00159 if(abs(d-azim) <= H2) 00160 { 00161 //convert back to rectangular form 00162 re_ = mag*cos(phase); 00163 im_ = mag*sin(phase); 00164 00165 //write bin to output 00166 if (k==0) 00167 { 00168 out(0,0) = re_; //DC 00169 } 00170 else if (k == N2_-1) 00171 { 00172 out(1, 0) = re_; //Nyquist 00173 } 00174 else 00175 { 00176 out(2*k, 0) = re_; //all other bins 00177 out(2*k+1, 0) = im_; 00178 } 00179 } 00180 } 00181 }