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 "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( const SpectralPeakArray& inPeaks, 00101 const Fundamental& inFund, 00102 const Spectrum& inSpectrum, 00103 SpectralPeakArray& outPeaks, 00104 Fundamental& outFund, 00105 Spectrum& outSpectrum 00106 ) 00107 { 00108 outPeaks = inPeaks; 00109 outFund = inFund; 00110 outSpectrum = inSpectrum; //residual processing is ignored by default, so the output residual is the input one 00111 00112 TData gain0 = mInputVoiceGain.GetLastValue(); 00113 SendFloatToInControl(mSinusoidalGain,"Gain",gain0); 00114 mSinusoidalGain.Do(outPeaks,outPeaks); 00115 //TODO add detuning and delay for input voice? 00116 00117 SpectralPeakArray mtmpPeaks; 00118 Fundamental mtmpFund; 00119 Spectrum mtmpSpectrum; 00120 00121 for (int i=0; i < mVoicesPitch.Size(); i++) 00122 { 00123 TData gain = mVoicesGain[i].GetLastValue(); 00124 if (gain<0.01) //means voice OFF 00125 continue; 00126 00127 TData amount = mVoicesPitch[i].GetLastValue() + frand()*mVoicesDetuningAmount[i].GetLastValue(); //detuning 00128 amount = CLAM_pow( 2., amount/12. ); //adjust to equal-tempered scale semitones 00129 00130 SendFloatToInControl(mPitchShift,"PitchSteps",amount); 00131 mPitchShift.Do( inPeaks, 00132 inFund, 00133 inSpectrum, 00134 mtmpPeaks, 00135 mtmpFund, 00136 mtmpSpectrum); 00137 00138 SendFloatToInControl(mSinusoidalGain,"Gain",gain); 00139 mSinusoidalGain.Do(mtmpPeaks,mtmpPeaks); 00140 00141 TData delay = mVoicesDelay[i].GetLastValue(); 00142 if (delay>0.) 00143 { 00144 SendFloatToInControl(mPeaksDelay,"Delay Control",delay); 00145 mPeaksDelay.Do(mtmpPeaks, mtmpPeaks); 00146 } 00147 00148 outPeaks = outPeaks + mtmpPeaks; 00149 00150 if (!mIgnoreResidual) 00151 mSpectrumAdder.Do(outSpectrum, mtmpSpectrum, outSpectrum); 00152 } 00153 return true; 00154 } 00155 00156 }