Marsyas
0.6.0-alpha
|
00001 /* 00002 ** Copyright (C) 1998-2006 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 "SCF.h" 00020 #include "../common_source.h" 00021 00022 using namespace std; 00023 using namespace Marsyas; 00024 00025 SCF::SCF(mrs_string name):MarSystem("SCF",name) 00026 { 00027 } 00028 00029 SCF::~SCF() 00030 { 00031 } 00032 00033 MarSystem* 00034 SCF::clone() const 00035 { 00036 return new SCF(*this); 00037 } 00038 00039 void 00040 SCF::myUpdate(MarControlPtr sender) 00041 { 00042 (void) sender; //suppress warning of unused parameter(s) 00043 MRSDIAG("SCF.cpp - SCF:myUpdate"); 00044 00045 //MPEG-7 audio standard: 00046 //assumes an 1/4 octave frequency resolution, 00047 //resulting in 24 frequency bands between 250Hz and 16kHz. 00048 //If the signal under analysis does not contain frequencies 00049 //above a determined value (e.g. due to signal sampling rate or 00050 //bandwidth limitations), the nr of bands should be reduced. 00051 00052 mrs_natural i; 00053 00054 //nrBands_ = getctrl("mrs_natural/nrbands");// can this be received as a control value? 00055 nrBands_ = 24; 00056 //can this parameter be dynamically modified, depending on the 00057 //sampling frequency?!? 00058 nrValidBands_ = nrBands_; 00059 00060 setctrl(ctrl_onSamples_, 1); 00061 setctrl(ctrl_onObservations_, nrBands_); 00062 setctrl(ctrl_osrate_, ctrl_israte_); 00063 00064 //features names 00065 mrs_string orig = ctrl_inObsNames_->to<mrs_string>(); 00066 // remove final comma in name 00067 orig = orig.substr(0, orig.size()-1); 00068 ostringstream oss; 00069 for (i = 0; i < nrBands_; ++i) 00070 oss << "SCF_" + orig << i+1 << ","; 00071 setctrl(ctrl_onObsNames_, oss.str()); 00072 00073 edge_.create(nrBands_ + 1); 00074 bandLoEdge_.create(nrBands_); 00075 bandHiEdge_.create(nrBands_); 00076 00077 //nominal band edges (Hz) -> reference = 1kHz (MPEG7) 00078 for(i = 0 ; i < nrBands_ + 1 ; ++i) 00079 { 00080 // 1/4 octave resolution (MPEG7) 00081 edge_(i) = 1000.0 * std::pow(2.0, (0.25 * (i - 8))); 00082 } 00083 // overlapped low and high band edges (Hz) 00084 for (i = 0; i < nrBands_; ++i) 00085 { 00086 bandLoEdge_(i) = edge_(i) * 0.95f; //band overlapping (MPEG7) 00087 bandHiEdge_(i) = edge_(i+1) * 1.05f; //band overlapping (MPEG7) 00088 } 00089 00090 spectrumSize_ = ctrl_inObservations_->to<mrs_natural>();//PowerSpectrum returns N/2+1 spectral points 00091 //spectrumBinFreqs_.create(spectrumSize_); 00092 00093 // spectrum sampling rate - not audio 00094 df_ = ctrl_israte_->to<mrs_real>(); 00095 00096 //calculate the frequency (Hz) of each FFT bin 00097 //for (mrs_natural k=0; k < spectrumSize_ ; k++) 00098 // spectrumBinFreqs_(k) = (float) k * df_; 00099 00100 //calculate FFT bin indexes for each band's edges 00101 il_.resize(nrBands_); 00102 ih_.resize(nrBands_); 00103 for(i = 0; i < nrBands_; ++i) 00104 { 00105 //round to nearest int (MPEG7) 00106 il_[i] = (mrs_natural)(bandLoEdge_(i)/df_ + 0.5f); 00107 ih_[i] = (mrs_natural)(bandHiEdge_(i)/df_ + 0.5f); 00108 00109 //must verify if sampling rate is enough 00110 //for the specified nr of bands. If not, 00111 //reduce nr of valid freq. bands 00112 if(ih_[i] >= spectrumSize_) //if ih_[i] >= N/2+1 = spectrumSize_ = inObservations ... 00113 { 00114 nrValidBands_ = i; 00115 il_.resize(nrValidBands_); 00116 ih_.resize(nrValidBands_); 00117 break; 00118 } 00119 } 00120 } 00121 00122 void 00123 SCF::myProcess(realvec& in, realvec& out) 00124 { 00125 mrs_natural i, k, bandwidth; 00126 double c, maxc; 00127 double aritMean ; 00128 00129 //default SCF value = 1.0; (defines SCF=1.0 for silence) 00130 out.setval(1.0); 00131 00132 //MPEG7 defines a grouping mechanism for the frequency bands above 1KHz 00133 //in order to reduce computational effort of the following calculation. 00134 //For now such grouping mechanism is not implemented... 00135 for(i = 0; i < nrValidBands_; ++i) 00136 { 00137 aritMean = 0.0; 00138 maxc = 0.0; 00139 bandwidth = ih_[i] - il_[i] + 1; 00140 for(k = il_[i]; k <= ih_[i]; k++) 00141 { 00142 c = in(k); //power spectrum coeff 00143 aritMean += c / bandwidth; 00144 if(c > maxc) 00145 maxc = c; 00146 } 00147 if (aritMean != 0.0) 00148 { 00149 out(i) = (float)(maxc/aritMean); 00150 } 00151 //else //mean power = 0 => silence... 00152 // out(i) = 1.0; //as used for the SFM (MPEG-7)... 00153 } 00154 00155 //for freq bands above the nyquist freq 00156 //return SFM value defined in MPEG7 for silence 00157 //for(i = nrValidBands_; i < nrBands_; ++i) 00158 // out(i) = 1.0; 00159 }