00001 /* 00002 * Copyright (c) 2001-2006 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 "Complex.hxx" 00023 #include "SpectralEnvelopeExtract.hxx" 00024 #include "Spectrum.hxx" 00025 #include "SpecTypeFlags.hxx" 00026 #include "SpectralPeakArray.hxx" 00027 00028 #define CLASS "SpectralEnvelopeExtract" 00029 00030 namespace CLAM { 00031 00032 /* The Configuration object has at least to have a name */ 00033 00034 void SpectralEnvelopeExtractConfig::DefaultInit() 00035 { 00036 AddAll(); 00037 UpdateData(); 00038 DefaultValues(); 00039 } 00040 00041 00042 void SpectralEnvelopeExtractConfig::DefaultValues() 00043 { 00044 SetInterpolationType(EInterpolation::eSpline); 00045 SetMaxPeaks(200); 00046 } 00047 00048 00049 /* Processing object Method implementations */ 00050 00051 SpectralEnvelopeExtract::SpectralEnvelopeExtract() 00052 { 00053 Configure(SpectralEnvelopeExtractConfig()); 00054 } 00055 00056 SpectralEnvelopeExtract::SpectralEnvelopeExtract(const SpectralEnvelopeExtractConfig &c = SpectralEnvelopeExtractConfig()) 00057 { 00058 Configure(c); 00059 } 00060 00061 SpectralEnvelopeExtract::~SpectralEnvelopeExtract() 00062 {} 00063 00064 00065 /* Configure the Processing Object according to the Config object */ 00066 00067 bool SpectralEnvelopeExtract::ConcreteConfigure(const ProcessingConfig& c) 00068 { 00069 00070 CopyAsConcreteConfig(mConfig, c); 00071 mMagBPF.SetIntpType(mConfig.GetInterpolationType()); 00072 mPhaseBPF.SetIntpType(EInterpolation::eLinear); 00073 return true; 00074 } 00075 00076 /* Setting Prototypes for faster processing */ 00077 00078 bool SpectralEnvelopeExtract::SetPrototypes(const SpectralPeakArray& input,Spectrum& output) 00079 { 00080 return true; 00081 } 00082 00083 bool SpectralEnvelopeExtract::SetPrototypes() 00084 { 00085 return true; 00086 } 00087 00088 bool SpectralEnvelopeExtract::UnsetPrototypes() 00089 { 00090 return true; 00091 } 00092 00093 /* The supervised Do() function */ 00094 00095 bool SpectralEnvelopeExtract::Do(void) 00096 { 00097 CLAM_ASSERT(false,CLASS"::Do(): Supervised mode not implemented"); 00098 return false; 00099 } 00100 00101 /* The unsupervised Do() function */ 00102 00103 bool SpectralEnvelopeExtract::Do(const SpectralPeakArray& input, Spectrum& output) 00104 { 00105 output.SetScale(input.GetScale()); 00106 00107 TSize nPeaks=input.GetnPeaks(); 00108 00109 if (nPeaks<4) return false; //cannot extract an envelope out of only 3 peaks! 00110 00111 CheckOutputType(output); 00112 00113 DataArray& magBuffer=input.GetMagBuffer(); 00114 DataArray& phaseBuffer=input.GetPhaseBuffer(); 00115 DataArray& freqBuffer=input.GetFreqBuffer(); 00116 00117 Array<Point>& magPointArray=output.GetMagBPF().GetPointArray(); 00118 Array<Point>& phasePointArray=output.GetPhaseBPF().GetPointArray(); 00119 00120 //Max number of points allowed: should be a config param 00121 magPointArray.Resize(mConfig.GetMaxPeaks()); 00122 magPointArray.SetSize(mConfig.GetMaxPeaks()); 00123 phasePointArray.Resize(mConfig.GetMaxPeaks()); 00124 phasePointArray.SetSize(mConfig.GetMaxPeaks()); 00125 00126 00127 for(int i=0;i<nPeaks;i++) 00128 { 00129 magPointArray[i+1].SetX(freqBuffer[i]); 00130 magPointArray[i+1].SetY(magBuffer[i]); 00131 00132 phasePointArray[i+1].SetX(freqBuffer[i]); 00133 phasePointArray[i+1].SetY(phaseBuffer[i]); 00134 00135 } 00136 00137 //todo: a lot of duplicated code, should extract in different functions 00138 if(input.GetScale()==EScale::eLog) 00139 { 00140 00141 //we now set first point (maybe we should do the same as with last point?) 00142 magPointArray[0].SetX(0); 00143 magPointArray[0].SetY(magBuffer[0]-3); 00144 phasePointArray[0].SetX(0); 00145 phasePointArray[0].SetY(0); 00146 nPeaks++; 00147 00148 /* we keep adding points to bpf until magnitude is insignificant 00149 (note that we add points outside the spectral range) */ 00150 TData lastFreq=freqBuffer[nPeaks-2]; 00151 TData freqGap=lastFreq-freqBuffer[nPeaks-3]; 00152 TData currentFreq=lastFreq+freqGap; 00153 TData currentMag=magBuffer[nPeaks-2]; 00154 00155 while(currentMag>-200) 00156 { 00157 currentMag-=(currentFreq/lastFreq-1)*12; 00158 00159 magPointArray[nPeaks].SetY(currentMag); 00160 magPointArray[nPeaks].SetX(currentFreq); 00161 phasePointArray[nPeaks].SetY(0); 00162 phasePointArray[nPeaks].SetX(currentFreq); 00163 00164 currentFreq+=freqGap; 00165 nPeaks++; 00166 if(nPeaks==mConfig.GetMaxPeaks()) break; 00167 00168 } 00169 //we resize arrays to final size 00170 magPointArray.Resize(nPeaks); 00171 magPointArray.SetSize(nPeaks); 00172 phasePointArray.Resize(nPeaks); 00173 phasePointArray.SetSize(nPeaks); 00174 00175 00176 } 00177 else 00178 { 00179 //we now set first point (maybe we should do the same as with last point?) 00180 magPointArray[0].SetX(0); 00181 magPointArray[0].SetY(magBuffer[0]*0.5); 00182 phasePointArray[0].SetX(0); 00183 phasePointArray[0].SetY(0); 00184 nPeaks++; 00185 00186 /* we keep adding points to bpf until magnitude is insignificant 00187 (note that we add points outside the spectral range) */ 00188 TData lastFreq=freqBuffer[nPeaks-2]; 00189 TData freqGap=lastFreq-freqBuffer[nPeaks-3]; 00190 TData currentFreq=lastFreq+freqGap; 00191 TData currentMag=magBuffer[nPeaks-2]; 00192 00193 00194 while(currentMag<0.0000000001) 00195 { 00196 currentMag*=CLAM_pow(0.06,(double)(currentFreq/lastFreq-1.0)); 00197 00198 magPointArray[nPeaks].SetY(currentMag); 00199 magPointArray[nPeaks].SetX(currentFreq); 00200 phasePointArray[nPeaks].SetY(0); 00201 phasePointArray[nPeaks].SetX(currentFreq); 00202 00203 currentFreq+=freqGap; 00204 nPeaks++; 00205 if(nPeaks==mConfig.GetMaxPeaks()) break; 00206 } 00207 00208 //we resize arrays to final size 00209 magPointArray.Resize(nPeaks); 00210 magPointArray.SetSize(nPeaks); 00211 phasePointArray.Resize(nPeaks); 00212 phasePointArray.SetSize(nPeaks); 00213 00214 } 00215 00216 output.SetSize(nPeaks); 00217 output.GetMagBPF().UpdateSplineTable(); 00218 00219 return true; 00220 } 00221 00222 bool SpectralEnvelopeExtract::CheckOutputType(Spectrum& out) 00223 { 00224 SpecTypeFlags tmpFlags; 00225 00226 tmpFlags.bMagPhaseBPF=1; 00227 tmpFlags.bMagPhase=0; 00228 out.SetType(tmpFlags); 00229 00230 00231 out.SetMagBPF(mMagBPF); 00232 out.SetPhaseBPF(mPhaseBPF); 00233 00234 00235 return true; 00236 } 00237 };//namespace CLAM 00238