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 "PhaseManagement.hxx" 00023 #include "Err.hxx" 00024 #include "SpectralPeakArray.hxx" 00025 00026 namespace CLAM 00027 { 00028 00029 00030 00031 PhaseManagement::PhaseManagement(): 00032 mCurrentTime("CurrentTime",this),mCurrentPitch("CurrentPitch",this) 00033 { 00034 Configure(PhaseManagementConfig()); 00035 Init(); 00036 } 00037 00038 PhaseManagement::PhaseManagement(PhaseManagementConfig& c): 00039 mCurrentTime("CurrentTime",this),mCurrentPitch("CurrentPitch",this) 00040 { 00041 Configure(c); 00042 Init(); 00043 } 00044 00045 bool PhaseManagement::ConcreteConfigure(const ProcessingConfig& c) 00046 { 00047 CopyAsConcreteConfig(mConfig, c); 00048 return true; 00049 } 00050 00051 void PhaseManagement::Init() 00052 { 00053 mRandomPhase.Resize(mConfig.GetMaxSines()); 00054 mRandomPhase.SetSize(mConfig.GetMaxSines()); 00055 00056 mFrameTime=0; 00057 mLastPeriodTime=0.0; 00058 mNextPeriodTime=0.0; 00059 mLastFundFreq=0.0; 00060 00061 mLastPeakArray.AddPhaseBuffer(); 00062 mLastPeakArray.AddBinWidthBuffer(); 00063 mLastPeakArray.AddBinPosBuffer(); 00064 mLastPeakArray.AddIndexArray(); 00065 00066 mLastPeakArray.UpdateData(); 00067 mLastPeakArray.SetScale(EScale::eLog); 00068 // init 00069 GenerateRandomPhases(mRandomPhase); 00070 GenerateRandomPhases(mLastPeakArray.GetPhaseBuffer()); 00071 00072 mLastPeakArray.SetIsIndexUpToDate(true); 00073 00074 } 00075 00076 00077 PhaseManagement::~PhaseManagement() 00078 { 00079 00080 } 00081 00082 bool PhaseManagement::Do(SpectralPeakArray& in) 00083 { 00084 switch(mConfig.GetType()) 00085 { 00086 case (EPhaseGeneration::eAlign): 00087 { 00088 DoPhaseAlignment(in); 00089 break; 00090 } 00091 case (EPhaseGeneration::eContinuation): 00092 { 00093 DoPhaseContinuation(in); 00094 break; 00095 } 00096 case (EPhaseGeneration::eRandom): 00097 { 00098 DoRandomPhases(in); 00099 break; 00100 } 00101 case (EPhaseGeneration::eNone): 00102 { 00103 break; 00104 } 00105 } 00106 return true; 00107 } 00108 00109 bool PhaseManagement::Do(Frame& currentFrame) 00110 { 00111 mCurrentTime.DoControl(currentFrame.GetCenterTime()); 00112 mCurrentPitch.DoControl(currentFrame.GetFundamental().GetFreq(0)); 00113 00114 return Do(currentFrame.GetSpectralPeakArray()); 00115 } 00116 00117 //----------------------------------------------------------------------------// 00118 void 00119 PhaseManagement::ResetPhaseAlignment() 00120 { 00121 // reset values before starting new thesis thread 00122 mLastPeriodTime = 0.0; 00123 mNextPeriodTime = 0.0; 00124 mLastFundFreq = 0.0; 00125 } 00126 //----------------------------------------------------------------------------// 00127 00128 void 00129 PhaseManagement::DoPhaseAlignment(SpectralPeakArray& peakArray) 00130 { 00131 00132 TIndex numPeaks = peakArray.GetnPeaks(); 00133 double phase,freq; 00134 00135 TData t=mCurrentTime.GetLastValue(); 00136 //phaseAlignment 00137 if (mCurrentPitch.GetLastValue()>0) // use phase align only when mCurrentPitch.GetLastValue() is existing 00138 { 00139 double newPeriodDuration = 1/mCurrentPitch.GetLastValue(); 00140 00141 if ((mLastPeriodTime!=0.0) && (mLastPeriodTime<mCurrentTime.GetLastValue())) 00142 { 00143 double lastPeriodDuration = mNextPeriodTime - mLastPeriodTime; 00144 mNextPeriodTime = mLastPeriodTime + newPeriodDuration; 00145 double averagePeriodDuration = 0.5*lastPeriodDuration + 0.5*newPeriodDuration; 00146 00147 double timeDiff = t-mLastPeriodTime; 00148 00149 TIndex nPeriodsElapsed = (TIndex)floor(timeDiff/averagePeriodDuration); 00150 00151 if (timeDiff-nPeriodsElapsed*averagePeriodDuration > newPeriodDuration-mFrameTime*0.5) 00152 nPeriodsElapsed++; 00153 00154 double timePeriodDiff = timeDiff - nPeriodsElapsed*averagePeriodDuration; 00155 00156 double thPeriodPosition = (timeDiff-nPeriodsElapsed*averagePeriodDuration)/newPeriodDuration; 00157 00158 timePeriodDiff = thPeriodPosition*newPeriodDuration; 00159 00160 for (int i = 0;i<numPeaks;i++) 00161 { 00162 double phase1 = peakArray.GetPhase(i); 00163 freq = peakArray.GetFreq(i); 00164 phase = phase1+TWO_PI*freq*timePeriodDiff; 00165 // in orig. sms we distinguish here perfect harmonic/not perfect harmonic 00166 phase = phase - floor(phase/TWO_PI)*TWO_PI; // phase wrapping 00167 peakArray.SetPhase(i,TData(phase)); 00168 } 00169 if (nPeriodsElapsed > 0) 00170 { 00171 mLastPeriodTime += nPeriodsElapsed*averagePeriodDuration; 00172 mNextPeriodTime = mLastPeriodTime + newPeriodDuration; 00173 } 00174 } 00175 else 00176 { 00177 mLastPeriodTime = t; 00178 mNextPeriodTime = t + newPeriodDuration; 00179 } 00180 } 00181 else 00182 { 00183 mLastPeriodTime = 0.0; 00184 mNextPeriodTime = 0.0; 00185 } 00186 mLastPeakArray.SetIsIndexUpToDate(true); 00187 00188 } 00189 00190 //----------------------------------------------------------------------------// 00191 00192 void PhaseManagement::DoRandomPhases(SpectralPeakArray& peakArray) 00193 { 00194 //MTG::SpectralPeakArray* peakArray = thFrame.GetPeakArrayPtr(); 00195 TIndex numPeaks = peakArray.GetnPeaks(); 00196 00197 int i; 00198 double phase,freq; 00199 00200 DataArray& lastPhase=mLastPeakArray.GetPhaseBuffer(); 00201 DataArray& lastFreq=mLastPeakArray.GetFreqBuffer(); 00202 int nPeaks=peakArray.GetnPeaks(); 00203 00204 lastPhase.Resize(nPeaks); 00205 lastPhase.SetSize(nPeaks); 00206 lastFreq.Resize(nPeaks); 00207 lastFreq.SetSize(nPeaks); 00208 00209 for (i=0;i<numPeaks;i++) 00210 { 00211 //phase = peakArray.GetPhase(i); 00212 freq = peakArray.GetFreq(i); 00213 00214 //find peak corresponding to current track 00215 TIndex prevPos =peakArray.GetIndex(i); 00216 00217 // use a set of random phases and calculate each time the correct phase.. 00218 if (prevPos == -1||prevPos>mLastPeakArray.GetnPeaks()) // new track... 00219 { 00220 phase = mRandomPhase[i]; 00221 peakArray.SetPhase(i,TData(phase)); 00222 00223 lastPhase[i]=phase; 00224 lastFreq[i]=freq; 00225 /*SpectralPeak tmpPeak; 00226 mLastPeakArray.InitPeak(tmpPeak); 00227 tmpPeak.SetPhase(TData(phase)); 00228 tmpPeak.SetFreq(TData(phase)); 00229 mLastPeakArray.AddSpectralPeak(tmpPeak);*/ 00230 } 00231 else // track is existing, calculate according phase.. 00232 { 00233 SpectralPeak lastPeak=mLastPeakArray.GetSpectralPeak(prevPos); 00234 phase = lastPeak.GetPhase() + TWO_PI*((lastPeak.GetFreq()+freq)*0.5*mFrameTime); 00235 00236 //phase = phase - floor(phase/TWO_PI)*TWO_PI; 00237 while (phase >= TWO_PI) phase = phase -TWO_PI; // other way.. 00238 peakArray.SetPhase(i,TData(phase)); 00239 lastPhase[prevPos]=TData(phase); 00240 lastFreq[prevPos]=TData(phase); 00241 } 00242 } 00243 mLastPeakArray.SetIsIndexUpToDate(true); 00244 00245 00246 } 00247 00248 00249 void PhaseManagement::DoPhaseContinuation(SpectralPeakArray& p) 00250 { 00251 int i; 00252 TData t=mCurrentTime.GetLastValue(); 00253 int nPeaks = p.GetnPeaks(); 00254 DataArray& lastPhaseBuffer = mLastPeakArray.GetPhaseBuffer(); 00255 DataArray& lastFreqBuffer = mLastPeakArray.GetFreqBuffer(); 00256 DataArray& currentPhaseBuffer = p.GetPhaseBuffer(); 00257 DataArray& currentFreqBuffer = p.GetFreqBuffer(); 00258 00259 TData timeDifference = t-mFrameTime; 00260 TData halfPI= TData(TWO_PI)*TData(0.5); 00261 00262 TData halfPITimeDifference = timeDifference*halfPI; 00263 TData twoPITimeDifference = TData(TWO_PI)*timeDifference; 00264 00265 for(i=0;i<nPeaks;i++) 00266 { 00267 TIndex currentIndex=p.GetIndex(i); 00268 TIndex lastPos=mLastPeakArray.GetPositionFromIndex(currentIndex); 00269 if(lastPos!=-1) 00270 { 00271 //SpectralPeak tmpPeak=mLastPeakArray.GetSpectralPeak(lastPos); 00272 //p.SetPhase(i,tmpPeak.GetPhase()+TData(TWO_PI)*TData(0.5)*(tmpPeak.GetFreq()+p.GetFreq(i))*(t-mFrameTime)); 00273 currentPhaseBuffer[i] = lastPhaseBuffer[lastPos]+ 00274 halfPITimeDifference*(lastFreqBuffer[lastPos]+currentFreqBuffer[i]); 00275 00276 } 00277 else 00278 { 00279 //p.SetPhase(i,TData(TWO_PI)*p.GetFreq(i)*(t-mFrameTime)); 00280 currentPhaseBuffer[i] = currentFreqBuffer[i]*twoPITimeDifference; 00281 } 00282 //p.SetPhase(i,p.GetPhase(i)-floor((TData)(p.GetPhase(i)/TData(TWO_PI)))*TData(TWO_PI)); 00283 currentPhaseBuffer[i] = currentPhaseBuffer[i]-floor((TData)(currentPhaseBuffer[i]/TData(TWO_PI)))*TData(TWO_PI); 00284 } 00285 mFrameTime=t; 00286 mLastPeakArray=p; 00287 mLastPeakArray.SetIsIndexUpToDate(true); 00288 } 00289 00290 //----------------------------------------------------------------------------// 00291 void 00292 PhaseManagement::GenerateRandomPhases(DataArray& a) 00293 { 00294 for (int i = 0; i<a.Size();i++) 00295 { 00296 a[i] = rand()/TData(RAND_MAX*TWO_PI); 00297 } 00298 } 00299 //----------------------------------------------------------------------------// 00300 void 00301 PhaseManagement::SetLastPhasesAndFreqs(SpectralPeakArray& peakArray) 00302 { 00303 DataArray& lastPhase=mLastPeakArray.GetPhaseBuffer(); 00304 DataArray& lastFreq=mLastPeakArray.GetFreqBuffer(); 00305 DataArray& currentPhase= peakArray.GetPhaseBuffer(); 00306 DataArray& currentFreq= peakArray.GetFreqBuffer(); 00307 int nPeaks=peakArray.GetnPeaks(); 00308 00309 lastPhase.Resize(nPeaks); 00310 lastPhase.SetSize(nPeaks); 00311 lastFreq.Resize(nPeaks); 00312 lastFreq.SetSize(nPeaks); 00313 00314 for (int i=0;i<nPeaks;i++) 00315 { 00316 lastPhase[i] = currentPhase[i]; 00317 lastFreq[i] = currentFreq[i]; 00318 } 00319 mLastPeakArray.SetIsIndexUpToDate(true); 00320 00321 } 00322 00323 } // namespace CLAM 00324