CLAM-Development
1.1
|
00001 /* 00002 * Copyright (c) 2001-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 "Segment.hxx" 00023 #include "Frame.hxx" 00024 #include "SpectrumConfig.hxx" 00025 #include "SpectralAnalysis.hxx" 00026 #include "ProcessingFactory.hxx" 00027 00028 namespace CLAM 00029 { 00030 00031 namespace Hidden 00032 { 00033 static const char * metadata[] = { 00034 "key", "SpectralAnalysis", 00035 "category", "Analysis", 00036 "description", "SpectralAnalysis", 00037 0 00038 }; 00039 static FactoryRegistrator<ProcessingFactory, SpectralAnalysis> reg = metadata; 00040 } 00041 00042 SpectralAnalysis::SpectralAnalysis() 00043 : mInput("Input",this ), 00044 mOutput("Output",this ) 00045 { 00046 AttachChildren(); 00047 Configure(SpectralAnalysisConfig()); 00048 } 00049 00050 SpectralAnalysis::SpectralAnalysis(SpectralAnalysisConfig& cfg) 00051 : mInput("Input",this), 00052 mOutput("Output",this) 00053 { 00054 AttachChildren(); 00055 Configure(cfg); 00056 } 00057 00058 SpectralAnalysis::~SpectralAnalysis() 00059 { 00060 } 00061 00062 bool SpectralAnalysis::ConcreteConfigure(const ProcessingConfig& cfg) 00063 { 00064 CopyAsConcreteConfig(mConfig,cfg); 00065 00066 mConfig.Sync(); 00067 ConfigureChildren(); 00068 ConfigureData(); 00069 return true; 00070 } 00071 00072 00073 bool SpectralAnalysis::ConfigureChildren() 00074 { 00075 mPO_WinGen.Configure(mConfig.GetWindowGenerator()); 00076 mPO_CShift.Configure(mConfig.GetCircularShift()); 00077 mPO_FFT.Configure(mConfig.GetFFT()); 00078 return true; 00079 00080 } 00081 00082 void SpectralAnalysis::ConfigureData() 00083 { 00084 TData samplingRate=mConfig.GetSamplingRate(); 00085 00086 mInput.SetSize(mConfig.GetWindowSize()); 00087 mInput.SetHop(mConfig.GetHopSize()); 00088 00089 mAudioFrame.SetSize(mConfig.GetprFFTSize()); 00090 mAudioFrame.SetSampleRate(mConfig.GetSamplingRate()); 00091 mWindow.SetSize(mConfig.GetWindowSize()); 00092 00093 /*Window is generated and data is kept in internal member mWindow*/ 00094 mPO_WinGen.Do(mWindow); 00095 00096 /*Leaving out last sample of odd-sized window*/ 00097 mWindow.SetSize(mWindow.GetSize()-1); 00098 00099 /* Adding zero padding to windowing function */ 00100 mWindow.SetSize(mConfig.GetprFFTSize()); 00101 00102 /* Spectrum used only for initializing a frame */ 00103 SpectrumConfig scfg; 00104 scfg.SetSize(mConfig.GetprFFTSize()/2+1); 00105 mSpec.Configure(scfg); 00106 00107 00108 /*Setting prototypes in the FFT*/ 00109 mPO_FFT.SetPrototypes (mWindow, mSpec); 00110 mInput.SetSampleRate( samplingRate ); 00111 } 00112 00113 void SpectralAnalysis::AttachChildren() 00114 { 00115 mPO_WinGen.SetParent(this); 00116 mPO_AProduct.SetParent(this); 00117 mPO_CShift.SetParent(this); 00118 mPO_FFT.SetParent(this); 00119 } 00120 00121 bool SpectralAnalysis::Do(void) 00122 { 00123 mOutput.GetData().SetSize( mConfig.GetFFT().GetAudioSize()/2+1); 00124 mOutput.GetData().SetSpectralRange( mInput.GetAudio().GetSampleRate()/2); 00125 00126 bool result = Do(mInput.GetAudio(),mOutput.GetData()); 00127 00128 mInput.Consume(); 00129 mOutput.Produce(); 00130 00131 return result; 00132 } 00133 00134 bool SpectralAnalysis::Do(const Audio& in,Spectrum& outSp) 00135 { 00136 00137 /* mAudioFrame is used as a helper audio copy where all windowing is done */ 00138 in.GetAudioChunk(0,in.GetSize()-1 ,mAudioFrame,true ); 00139 00140 // TODO: it is wrong 00141 mAudioFrame.SetSize(mConfig.GetWindowSize()-1); 00142 00143 00144 /* Zero padding is added to audioframe */ 00145 mAudioFrame.SetSize(mConfig.GetprFFTSize()); 00146 00147 /* Windowing function is now applied */ 00148 mPO_AProduct.Do(mAudioFrame, mWindow, mAudioFrame); 00149 00150 /* Finally, we do the circular shift */ 00151 mPO_CShift.Do(mAudioFrame,mAudioFrame); 00152 00153 /* and now the FFT can be performed */ 00154 mPO_FFT.Do(mAudioFrame, outSp); 00155 00156 return true; 00157 } 00158 00159 00160 bool SpectralAnalysis::Do(Frame& in) 00161 { 00162 return Do(in.GetAudioFrame(),in.GetSpectrum()); 00163 } 00164 00165 bool SpectralAnalysis::Do(Segment& in) 00166 { 00167 return Do(in.GetFrame(in.mCurrentFrameIndex++)); 00168 } 00169 00170 00171 } // namespace CLAM 00172