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(
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 }
Generated by  doxygen 1.6.3