|
CLAM-Development
1.3
|
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 "SMSHarmonizer.hxx" 00023 #include "ProcessingFactory.hxx" 00024 00025 namespace CLAM 00026 { 00027 00028 namespace Hidden 00029 { 00030 static const char * metadata[] = { 00031 "key", "SMSHarmonizer", 00032 "category", "SMS Transformations", 00033 "description", "SMSHarmonizer", 00034 0 00035 }; 00036 static FactoryRegistrator<ProcessingFactory, SMSHarmonizer> reg = metadata; 00037 } 00038 00039 bool SMSHarmonizer::ConcreteConfigure(const ProcessingConfig& config) 00040 { 00041 CopyAsConcreteConfig( mConfig, config ); 00042 00043 if ( mConfig.GetNumberOfVoices()==0 ) 00044 { 00045 AddConfigErrorMessage("The provided config object lacked NumberOfVoices value"); 00046 return false; 00047 } 00048 00049 mIgnoreResidual = mConfig.GetIgnoreResidual(); 00050 00051 mPitchShift.Configure( FrameTransformationConfig() ); 00052 SendFloatToInControl(mPitchShift,"IgnoreResidual",mIgnoreResidual); 00053 00054 mInputVoiceGain.SetBounds(-2.,2.); 00055 mInputVoiceGain.SetDefaultValue(0.); 00056 mInputVoiceGain.DoControl(0.); 00057 00058 int n_voices = mConfig.GetNumberOfVoices(); 00059 00060 if (n_voices>MAX_AMOUNT_OF_VOICES) n_voices = MAX_AMOUNT_OF_VOICES; 00061 00062 mVoicesPitch.Resize(n_voices, "Pitch", this); 00063 mVoicesGain.Resize(n_voices, "Gain", this); 00064 mVoicesDetuningAmount.Resize(n_voices, "Voice Detuning", this); 00065 mVoicesDelay.Resize(n_voices, "Voice Delay", this); 00066 for (int i=0; i < mVoicesPitch.Size(); i++) 00067 { 00068 mVoicesGain[i].SetBounds(0.,2.); 00069 mVoicesGain[i].SetDefaultValue(0.); 00070 mVoicesGain[i].DoControl(0.); 00071 00072 mVoicesPitch[i].SetBounds(-24.,24.); 00073 mVoicesPitch[i].SetDefaultValue(0.); //no pitch shift 00074 mVoicesPitch[i].DoControl(0.); 00075 00076 mVoicesDetuningAmount[i].SetBounds(0.,1.); 00077 mVoicesDetuningAmount[i].SetDefaultValue(0.); 00078 mVoicesDetuningAmount[i].DoControl(0.); 00079 00080 mVoicesDelay[i].SetBounds(0.,1.); 00081 mVoicesDelay[i].SetDefaultValue(0.); 00082 mVoicesDelay[i].DoControl(0.); 00083 } 00084 00085 return true; 00086 } 00087 00088 bool SMSHarmonizer::Do(const Frame& in, Frame& out) 00089 { 00090 return Do( in.GetSpectralPeakArray(), 00091 in.GetFundamental(), 00092 in.GetResidualSpec(), 00093 00094 out.GetSpectralPeakArray(), 00095 out.GetFundamental(), 00096 out.GetResidualSpec() 00097 ); 00098 } 00099 00100 bool SMSHarmonizer::Do( 00101 const SpectralPeakArray& inPeaks, 00102 const Fundamental& inFund, 00103 const Spectrum& inSpectrum, 00104 SpectralPeakArray& outPeaks, 00105 Fundamental& outFund, 00106 Spectrum& outSpectrum 00107 ) 00108 { 00109 outPeaks = inPeaks; 00110 outFund = inFund; 00111 outSpectrum = inSpectrum; //residual processing is ignored by default, so the output residual is the input one 00112 00113 TData gain0 = mInputVoiceGain.GetLastValue(); 00114 SendFloatToInControl(mSinusoidalGain,"Gain",gain0); 00115 mSinusoidalGain.Do(outPeaks,outPeaks); 00116 //TODO add detuning and delay for input voice? 00117 00118 SpectralPeakArray mtmpPeaks; 00119 Fundamental mtmpFund; 00120 Spectrum mtmpSpectrum; 00121 00122 for (int i=0; i < mVoicesPitch.Size(); i++) 00123 { 00124 TData gain = mVoicesGain[i].GetLastValue(); 00125 if (gain<0.01) //means voice OFF 00126 continue; 00127 00128 TData amount = mVoicesPitch[i].GetLastValue() + frand()*mVoicesDetuningAmount[i].GetLastValue(); //detuning 00129 amount = CLAM_pow( 2., amount/12. ); //adjust to equal-tempered scale semitones 00130 00131 SendFloatToInControl(mPitchShift,"PitchSteps",amount); 00132 mPitchShift.Do( inPeaks, 00133 inFund, 00134 inSpectrum, 00135 mtmpPeaks, 00136 mtmpFund, 00137 mtmpSpectrum); 00138 00139 SendFloatToInControl(mSinusoidalGain,"Gain",gain); 00140 mSinusoidalGain.Do(mtmpPeaks,mtmpPeaks); 00141 00142 TData delay = mVoicesDelay[i].GetLastValue(); 00143 if (delay>0.) 00144 { 00145 SendFloatToInControl(mPeaksDelay,"Delay Control",delay); 00146 mPeaksDelay.Do(mtmpPeaks, mtmpPeaks); 00147 } 00148 00149 outPeaks = outPeaks + mtmpPeaks; 00150 00151 if (!mIgnoreResidual) 00152 mSpectrumAdder.Do(outSpectrum, mtmpSpectrum, outSpectrum); 00153 } 00154 return true; 00155 } 00156 00157 }
1.7.6.1