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 "Audio.hxx" 00023 #include "Frame.hxx" 00024 #include "Segment.hxx" 00025 #include "Fundamental.hxx" 00026 #include "SpectrumConfig.hxx" 00027 #include "SMSAnalysis.hxx" 00028 00029 namespace CLAM 00030 { 00031 00032 SMSAnalysis::SMSAnalysis() 00033 : mAudioProvider( "Audio provider", 0 ) 00034 { 00035 mAudioProvider.ConnectToIn( mCore.GetInPort( "Input Audio" )); 00036 AttachChildren(); 00037 Configure(SMSAnalysisConfig()); 00038 } 00039 00040 SMSAnalysis::SMSAnalysis(SMSAnalysisConfig& cfg) 00041 : mAudioProvider( "Audio provider", 0 ) 00042 { 00043 AttachChildren(); 00044 Configure(cfg); 00045 } 00046 00047 SMSAnalysis::~SMSAnalysis() 00048 { 00049 } 00050 00051 bool SMSAnalysis::ConcreteConfigure(const ProcessingConfig& cfg) 00052 { 00053 CopyAsConcreteConfig(mConfig,cfg); 00054 ConfigureChildren(); 00055 ConfigureData(); 00056 return true; 00057 } 00058 00059 00060 bool SMSAnalysis::ConfigureChildren() 00061 { 00062 mCore.Configure( mConfig ); 00063 return true; 00064 00065 } 00066 00067 void SMSAnalysis::ConfigureData() 00068 { 00069 mAudioFrameIndex=0; 00070 00071 mAudioProvider.SetSize( mConfig.GetHopSize() ); 00072 mAudioProvider.SetHop( mConfig.GetHopSize() ); 00073 } 00074 00075 void SMSAnalysis::AttachChildren() 00076 { 00077 mCore.SetParent( this ); 00078 } 00079 00080 bool SMSAnalysis::ConcreteStart() 00081 { 00082 //we have to initialize internal counter 00083 mAudioFrameIndex=0; 00084 return ProcessingComposite::ConcreteStart(); 00085 } 00086 00087 bool SMSAnalysis::Do() 00088 { 00089 return mCore.Do(); 00090 } 00091 00092 bool SMSAnalysis::Do(Frame& in) 00093 { 00094 InitFrame(in); 00095 00096 //we set spectrum size and fundamental number of candidates 00097 in.GetSpectrum().SetSize(mConfig.GetSinSpectralAnalysis().GetFFT().GetAudioSize()/2+1); 00098 in.GetFundamental().SetnMaxCandidates(1); 00099 00100 bool result=false; 00101 00102 if(mAudioProvider.CanProduce()) 00103 { 00104 00105 mAudioProvider.SetSampleRate( in.GetAudioFrame().GetSampleRate() ); 00106 mAudioProvider.GetAudio().GetBuffer() = in.GetAudioFrame().GetBuffer(); 00107 mAudioProvider.Produce(); 00108 } 00109 00110 if(mCore.CanConsumeAndProduce()) 00111 result = mCore.Do(); 00112 else 00113 return false; 00114 00115 OutPortBase & outSinSpectrum = mCore.GetOutPort("Sinusoidal Branch Spectrum"); 00116 in.GetSinusoidalAnalSpectrum() = OutPortPublisher<Spectrum>::GetLastWrittenData( outSinSpectrum ); 00117 00118 OutPortBase & outResSpectrum = mCore.GetOutPort("Residual Spectrum"); 00119 in.GetResidualSpec() = OutPortPublisher<Spectrum>::GetLastWrittenData( outResSpectrum ); 00120 00121 OutPortBase & outSpectrum = mCore.GetOutPort("Residual Branch Spectrum"); 00122 in.GetSpectrum() = OutPortPublisher<Spectrum>::GetLastWrittenData( outSpectrum ); 00123 00124 OutPortBase & fundamental = mCore.GetOutPort("Fundamental"); 00125 in.GetFundamental() = OutPortPublisher<Fundamental>::GetLastWrittenData( fundamental ); 00126 00127 OutPortBase & peaks = mCore.GetOutPort("Sinusoidal Peaks"); 00128 in.GetSpectralPeakArray() = OutPortPublisher<SpectralPeakArray>::GetLastWrittenData( peaks ); 00129 00130 // MRJ: Let's check the poscondition... 00131 CLAM_DEBUG_ASSERT( in.GetResidualSpec().GetSpectralRange() > 0, 00132 "Residual spectrum is not being properly configured" ); 00133 00134 if (result) // TODO: refactor 00135 //if we have been able to analyze something we set whether frame is voiced or not 00136 in.SetIsHarmonic(in.GetFundamental().GetFreq(0)>0); 00137 return result; 00138 } 00139 00140 bool SMSAnalysis::Do(Segment& in) 00141 { 00142 //first we compute necessary sizes, indices and parameters 00143 TIndex frameIndex=in.mCurrentFrameIndex; 00144 int step=mConfig.GetHopSize(); 00145 TData samplingRate=mConfig.GetSamplingRate(); 00146 TTime frameCenterTime=frameIndex*step/samplingRate; 00147 //Audio center time is different from frame center time. This index corresponds to 00148 //the audio that is being written into member stream buffer 00149 TIndex audioCenterSample=(mAudioFrameIndex)*step; 00150 //Unused variable: TTime audioCenterTime=audioCenterSample/samplingRate; 00151 00153 //If we have reached end of input audio we return false 00154 if(frameCenterTime>in.GetAudio().GetDuration()*0.001) 00155 return false; 00156 00157 tmpFrame.SetDuration(step/samplingRate); 00158 tmpFrame.SetCenterTime(TData(frameCenterTime)); 00159 tmpFrame.AddAudioFrame(); 00160 tmpFrame.UpdateData(); 00161 tmpFrame.GetAudioFrame().SetBeginTime(((float)frameIndex - 0.5f)*step/samplingRate); 00162 tmpFrame.GetAudioFrame().SetSampleRate(in.GetAudio().GetSampleRate()); 00163 00164 /* Note: Here we are just taking the "new" audio belonging to each frame. That is, the 00165 HopSize samples centered around CenterTime */ 00166 in.GetAudio().GetAudioChunk(audioCenterSample-step/2,audioCenterSample+step/2, 00167 tmpFrame.GetAudioFrame(),true); 00168 00169 //we have taken a new audio chunk and must increment internal counter 00170 mAudioFrameIndex++; 00171 00172 //tmpFrame.SetAudioFrame(tmpAudio); 00173 bool hasProcessed=Do(tmpFrame); 00174 00175 if(hasProcessed) 00176 {//we have been able to do an analysis and write the result into tmpFrame's attributes 00177 in.mCurrentFrameIndex++; 00178 in.AddFrame(tmpFrame); 00179 } 00180 00181 return true; 00182 } 00183 00184 void SMSAnalysis::InitFrame(Frame& in) 00185 { 00186 //We add necessary attributes to input frame 00187 if ( !in.HasSpectrum() ) 00188 in.AddSpectrum(); 00189 if ( !in.HasSpectralPeakArray() ) 00190 in.AddSpectralPeakArray(); 00191 if ( !in.HasFundamental() ) 00192 in.AddFundamental(); 00193 if ( !in.HasResidualSpec() ) 00194 in.AddResidualSpec(); 00195 if ( !in.HasIsHarmonic() ) 00196 in.AddIsHarmonic(); 00197 if ( !in.HasSinusoidalAnalSpectrum() ) 00198 in.AddSinusoidalAnalSpectrum(); 00199 00200 in.UpdateData(); 00201 } 00202 00203 } // namespace CLAM 00204