Marsyas  0.6.0-alpha
/usr/src/RPM/BUILD/marsyas-0.6.0/src/marsyas/marsystems/ADRessSpectrum.cpp
Go to the documentation of this file.
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 }