SynthSineSpectrum.cxx

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2004 MUSIC TECHNOLOGY GROUP (MTG)
00003  *                         UNIVERSITAT POMPEU FABRA
00004  *
00005  *
00006  * This program is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019  *
00020  */
00021 
00022 #include "SpectrumConfig.hxx"
00023 #include "SpecTypeFlags.hxx"
00024 #include "SynthSineSpectrum.hxx"
00025 #include "BlackHarrisLobe.hxx"
00026 
00027 using namespace CLAM;
00028 
00029 
00030 /******************************************************************/
00031 /************************ SynthSineSpectrum ***********************/
00032 
00033 
00034 
00035 SynthSineSpectrum::SynthSineSpectrum()
00036         : mInput( "Input", this ),
00037           mOutput("Output", this )
00038 {
00039         Configure(SynthSineSpectrumConfig());
00040 }
00041 
00042 SynthSineSpectrum::SynthSineSpectrum(SynthSineSpectrumConfig& cfg)
00043         : mInput( "Input", this ),
00044           mOutput("Output", this )
00045 {
00046         Configure(cfg);
00047 }
00048 
00049 
00050 bool SynthSineSpectrum::ConcreteConfigure(const ProcessingConfig& c)
00051 {
00052         CopyAsConcreteConfig(mConfig, c);
00053         WindowGeneratorConfig wcfg;
00054         wcfg.SetNormalize(EWindowNormalize::eNone);
00055         wcfg.SetSize(MAINLOBE_TABLE_SIZE);
00056         wcfg.SetType(EWindowType::eBlackmanHarris92);
00057         mWndGen.Configure(wcfg);
00058         //@TODO: there is some kind of bug in the window generator: when generating the 
00059         //BlackmannHarris transform it does not yield the same results as the above table!
00060         //mBlackHarris92TransMainLobe.SetSize(MAINLOBE_TABLE_SIZE);
00061         //mWndGen.Do(mBlackHarris92TransMainLobe);
00062         return true;
00063 }
00064 
00065 
00066 SynthSineSpectrum::~SynthSineSpectrum()
00067 {
00068 }
00069 
00070 bool SynthSineSpectrum::Do()
00071 {
00072         bool result = Do( mInput.GetData(), mOutput.GetData());
00073         mInput.Consume();
00074         mOutput.Produce();
00075         return result;
00076 }
00077 
00078 
00079 //-------------------------------------------------------------------//
00080 // note : for now we first fill the mSynthsineSpectrum. Then we convert this 
00081 // to a  Spectrum. Its more cpu expensive, but as we dont know which processes
00082 // has to be applied the mSynthSineSpectrum, we use it like this
00083 // COULD BE OPTIMIZED LATER !!!! JO 
00084 bool SynthSineSpectrum::Do(const SpectralPeakArray& peakArray,Spectrum& residualSpectrumOut, double gain)
00085 {
00086         CLAM_DEBUG_ASSERT( AbleToExecute(), "SynthSineSpectrum::Do - processing is not running" );
00087 
00088         InitSynthSpec(mConfig.GetSpectrumSize());               // could be optimised with memset
00089         FillSynthSineSpectrum(peakArray,gain);
00090 
00091         SpectrumConfig Scfg; 
00092         Scfg.SetScale(EScale::eLinear);
00093         SpecTypeFlags sflags;
00094         sflags.bComplex = 1;
00095         sflags.bPolar = 0;
00096         sflags.bMagPhase = 0;
00097         sflags.bMagPhaseBPF = 0;
00098         int spectralSize;
00099         spectralSize = mSynthSineSpectrum.Size();
00100         Scfg.SetType(sflags);
00101         Scfg.SetSize(spectralSize);
00102         Scfg.SetSpectralRange(residualSpectrumOut.GetSpectralRange());
00103         residualSpectrumOut.Configure(Scfg);    
00104         residualSpectrumOut.SetComplexArray(mSynthSineSpectrum); 
00105         return true;
00106 }
00107 
00108 void SynthSineSpectrum::FillSynthSineSpectrum   (       const SpectralPeakArray& peakArray, double gain)
00109 {
00110         TSize           mainLobeBins = TSize ( TData(8)*CLAM_pow(2.0,(double)mConfig.GetZeroPadding()) ) ; // Number of bins in the mainlope of a transformed BHarris92 window 
00111                            
00112         TIndex          b,i,k,l,Index,numPeaks = peakArray.GetnPeaks();
00113                                         
00114         SpectralPeak currPeak;
00115         double currMag,currBinPos,Sin,Cos,approxMag,fIndex,currFreq,phase;
00116         Array< Complex >  SpecPeakEnvelope(mainLobeBins);
00117         SpecPeakEnvelope.SetSize(mainLobeBins);
00118         DataArray& peakFreqBuffer=peakArray.GetFreqBuffer();
00119         DataArray& peakMagBuffer=peakArray.GetMagBuffer();
00120         DataArray& peakPhaseBuffer=peakArray.GetPhaseBuffer();
00121 
00122         TData samplingRate=mConfig.GetSamplingRate();
00123         TSize spectrumSize=mConfig.GetSpectrumSize();
00124         TSize zeroPadding=TSize( TData(mConfig.GetZeroPadding()) );
00125 
00126         TData binPosFactor=2*(spectrumSize-1)/samplingRate;
00127         TData firstBinFactor= 3* CLAM_pow((TData)2,(TData)zeroPadding);
00128 
00129         int incr=int(CLAM_pow(2.0,9.0-mConfig.GetZeroPadding()));
00130         int lastBin=4096-incr;
00131         /* loop thru all the peaks ...*/
00132         for(i=0;i<numPeaks;i++)
00133         {
00134                 if(peakArray.GetScale()==EScale::eLog)//if it is in dB
00135                 {
00136                         currMag = CLAM_pow(10.0,(peakMagBuffer[i]/20.0));
00137                 }
00138                 else    currMag = peakMagBuffer[i];
00139                 currFreq = peakFreqBuffer[i];
00140                 phase = peakPhaseBuffer[i];
00141                 Cos = CLAM_cos(phase);          // we assume the phase is constant throughout the frame
00142                 Sin = CLAM_sin(phase);
00143                 // we use the frequency specify position of the peak, not the binpos !
00144                 currBinPos = currFreq*binPosFactor;
00145     
00146                 double Loc = currBinPos;
00147                 TIndex firstBin = TIndex( int( Loc ) - firstBinFactor );
00148                 double BinRemainder = Loc - floor (Loc);
00149                 fIndex = (1.0 - BinRemainder);
00150                 Index=(int)(0.5 + fIndex*MAINLOBE_TABLE_SIZE/(mainLobeBins));
00151                 
00152                 /* SpecPeakEnvelope holds the 7*(2^ZeroPadding) Bin approximation of a Peak which is            */
00153                 /* convoluted with the transform of a BlackmanHarris 92 window Main Lobe  */
00154                 int n;
00155                 int currBin=Index;
00156                 double mainLobe = sBlackHarris92TransMainLobe[currBin];
00157                 for (n=0; currBin<=lastBin;n++)
00158                 {
00159                         approxMag = currMag * mainLobe;
00160 
00161                         SpecPeakEnvelope[n].SetReal(TData(approxMag*Cos));
00162                         SpecPeakEnvelope[n].SetImag(TData(approxMag*Sin));
00163                         currBin+=incr;
00164                         mainLobe = sBlackHarris92TransMainLobe[currBin];
00165                 }
00166 
00167                 if( (Index+4096-incr) >= MAINLOBE_TABLE_SIZE)
00168                 {
00169                         SpecPeakEnvelope[mainLobeBins-1].SetReal(0);
00170                         SpecPeakEnvelope[mainLobeBins-1].SetImag(0);
00171                 }
00172                 else
00173                 {
00174                         approxMag = currMag * sBlackHarris92TransMainLobe[Index+4096-incr]; 
00175                         SpecPeakEnvelope[mainLobeBins-1].SetReal(TData(approxMag*Cos));
00176                         SpecPeakEnvelope[mainLobeBins-1].SetImag(TData(approxMag*Sin));
00177                 }
00178     
00179                 /* Add the current Peak to the spektrum and check for aliasing at the limits */
00180                 for (k = 0, l = firstBin; k < mainLobeBins ; k++,l++)
00181                 {
00182                         if (l > 0 && l < mConfig.GetSpectrumSize()-1) // we are inside the spectrum limits
00183                         {
00184                                 mSynthSineSpectrum[l] += SpecPeakEnvelope[k]; 
00185                         }    
00186         
00187                         else if (l < 0) // part of peaklobe is below zero frequency, mirror it back 
00188                         {
00189                                 b = -l;
00190                                 mSynthSineSpectrum[b].SetReal(mSynthSineSpectrum[b].Real()+SpecPeakEnvelope[k].Real());
00191                                 mSynthSineSpectrum[b].SetImag(mSynthSineSpectrum[b].Imag()-SpecPeakEnvelope[k].Imag());
00192                         }
00193         
00194                         else if (l == 0) //  only real part, no phase
00195                         {
00196                                 mSynthSineSpectrum[0].SetReal(mSynthSineSpectrum[0].Real()+2*(SpecPeakEnvelope[k].Real()));
00197                         }
00198         
00199                         else if (l > mConfig.GetSpectrumSize()-1&&(l<mConfig.GetSpectrumSize()*2-1)) //   part of peaklobe is over nyquist frequency, mirror it back 
00200                         {
00201                                 b = 2 * (spectrumSize-1) - l;
00202                                 mSynthSineSpectrum[b].SetReal(mSynthSineSpectrum[b].Real()+SpecPeakEnvelope[k].Real());
00203                                 mSynthSineSpectrum[b].SetImag(mSynthSineSpectrum[b].Imag()-SpecPeakEnvelope[k].Imag());
00204                         }
00205         
00206                         else if (l == spectrumSize-1) //  only real part, no phase
00207                         {       
00208                                 mSynthSineSpectrum[l].SetReal(mSynthSineSpectrum[l].Real()+2*(SpecPeakEnvelope[k].Real()));
00209                         }
00210                 }    
00211         }
00212 }
00213 //-------------------------------------------------------------------//
00214 void SynthSineSpectrum::InitSynthSpec(TSize size)
00215 {
00216         TSize i;
00217         mSynthSineSpectrum.Resize(size);        
00218         mSynthSineSpectrum.SetSize(size); 
00219         for(i=0;i<size;i++)
00220         {
00221                 mSynthSineSpectrum[i] =  Complex(0,0);
00222         }
00223 }
00224 
Generated by  doxygen 1.6.3