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 "SMSPitchShift.hxx" 00023 #include "ProcessingFactory.hxx" 00024 00025 00026 namespace CLAM 00027 { 00028 00029 namespace Hidden 00030 { 00031 static const char * metadata[] = { 00032 "key", "SMSPitchShift", 00033 "category", "SMS Transformations", 00034 "description", "SMSPitchShift", 00035 0 00036 }; 00037 static FactoryRegistrator<ProcessingFactory, SMSPitchShift> reg = metadata; 00038 } 00039 00040 bool SMSPitchShift::Do(const SpectralPeakArray& inPeaks, 00041 const Fundamental& inFund, 00042 const Spectrum& inRes, 00043 SpectralPeakArray& outPeaks, 00044 Fundamental& outFund, 00045 Spectrum& outRes) 00046 { 00047 bool ignoreResidual = mIgnoreResidual.GetLastValue()>0.; 00048 if (!mConfig.GetPreserveOuts()) //TODO big cludge for streaming 00049 { 00050 outPeaks = inPeaks; 00051 outFund = inFund; 00052 if (!ignoreResidual) 00053 outRes = inRes; 00054 } 00055 00056 TData amount = mPitchSteps.GetLastValue(); 00057 if(amount==1)//no pitch shift 00058 return true; 00059 00060 TData spectralRange = inRes.GetSpectralRange(); 00061 TData fundamental = inFund.GetFreq(0); 00062 bool isHarmonic = fundamental > .5; 00063 mIsHarmonic.DoControl( isHarmonic ); 00064 00065 for (int i=0;i<inFund.GetnCandidates();i++) 00066 outFund.SetFreq(i,inFund.GetFreq(i)*amount); 00067 00068 mSpectralEnvelope.SetSpectralRange(spectralRange); 00069 00070 bool haveEnvelope=false; 00071 00072 //First extract spectral envelope 00073 if(isHarmonic) 00074 haveEnvelope = mSpectralEnvelopeExtract.Do(inPeaks,mSpectralEnvelope); 00075 00076 if(&outPeaks!=&inPeaks)//TODO: this is already solved inPeaks new DT 00077 outPeaks=inPeaks; 00078 DataArray& iFreqArray=inPeaks.GetFreqBuffer(); 00079 DataArray& oFreqArray=outPeaks.GetFreqBuffer(); 00080 DataArray& iBinPosArray=inPeaks.GetBinPosBuffer(); 00081 DataArray& oBinPosArray=outPeaks.GetBinPosBuffer(); 00082 TSize nPeaks=inPeaks.GetnPeaks(); 00083 00084 //Shift all peaks 00085 for(int i=0;i<nPeaks;i++) 00086 { 00087 TData newFreq=iFreqArray[i]*amount; 00088 if (newFreq>=spectralRange) 00089 { 00090 outPeaks.SetnPeaks(i); 00091 break; 00092 } 00093 oFreqArray[i]=newFreq; 00094 oBinPosArray[i]=iBinPosArray[i]*amount; 00095 } 00096 00097 //Apply original spectral shape and comb filter the residual 00098 if (isHarmonic) 00099 { 00100 if (haveEnvelope) 00101 mSpectralEnvelopeApply.Do(outPeaks,mSpectralEnvelope,outPeaks); 00102 if (false && !ignoreResidual) 00103 { 00104 mFDCombFilter.mFreq.DoControl(fundamental*amount); 00105 mFDCombFilter.Do(inRes,outRes); 00106 } 00107 } 00108 return true; 00109 } 00110 00111 bool SMSPitchShift::Do(const Frame& in, Frame& out) 00112 { 00113 return Do( in.GetSpectralPeakArray(), 00114 in.GetFundamental(), 00115 in.GetResidualSpec(), 00116 out.GetSpectralPeakArray(), 00117 out.GetFundamental(), 00118 out.GetResidualSpec()); 00119 } 00120 00121 00122 } 00123