SMSHarmonizer.cxx

Go to the documentation of this file.
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 }

Generated on Tue Aug 12 22:33:44 2008 for CLAM by  doxygen 1.5.5