CLAM-Development
1.1
|
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