pl-nk v0.4.5
Plonk|Plink|Plank are a set of cross-platform C/C++ frameworks for audio software development
plonk_FilterCoeffs3Param.h
00001 /*
00002  -------------------------------------------------------------------------------
00003  This file is part of the Plink, Plonk, Plank libraries
00004   by Martin Robinson
00005  
00006  http://code.google.com/p/pl-nk/
00007  
00008  Copyright University of the West of England, Bristol 2011-14
00009  All rights reserved.
00010  
00011  Redistribution and use in source and binary forms, with or without
00012  modification, are permitted provided that the following conditions are met:
00013  
00014  * Redistributions of source code must retain the above copyright
00015    notice, this list of conditions and the following disclaimer.
00016  * Redistributions in binary form must reproduce the above copyright
00017    notice, this list of conditions and the following disclaimer in the
00018    documentation and/or other materials provided with the distribution.
00019  * Neither the name of University of the West of England, Bristol nor 
00020    the names of its contributors may be used to endorse or promote products
00021    derived from this software without specific prior written permission.
00022  
00023  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
00024  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00025  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
00026  DISCLAIMED. IN NO EVENT SHALL UNIVERSITY OF THE WEST OF ENGLAND, BRISTOL BE 
00027  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
00028  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 
00029  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
00030  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
00031  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 
00032  OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
00033  
00034  This software makes use of third party libraries. For more information see:
00035  doc/license.txt included in the distribution.
00036  -------------------------------------------------------------------------------
00037  */
00038 
00039 #ifndef PLONK_FILTERCOEFFS3PARAM_H
00040 #define PLONK_FILTERCOEFFS3PARAM_H
00041 
00042 #include "../channel/plonk_ChannelInternalCore.h"
00043 #include "plonk_FilterForwardDeclarations.h"
00044 
00045 
00046 
00048 template<class ShapeType>
00049 class FilterCoeffs3ParamChannelInternal 
00050 :   public ProxyOwnerChannelInternal<typename ShapeType::SampleDataType, 
00051                                      typename ShapeType::Data>
00052 {
00053 public:
00054     typedef typename ShapeType::SampleDataType                  SampleType;
00055     typedef typename ShapeType::Data                            Data;
00056     typedef typename ShapeType::FormType                        FormType;
00057     
00058     typedef ChannelBase<SampleType>                             ChannelType;
00059     typedef ObjectArray<ChannelType>                            ChannelArrayType;
00060         
00061     typedef ProxyOwnerChannelInternal<SampleType,Data>          Internal;
00062     typedef UnitBase<SampleType>                                UnitType;
00063     typedef InputDictionary                                     Inputs;
00064     typedef NumericalArray<SampleType>                          Buffer;
00065         
00066     FilterCoeffs3ParamChannelInternal (Inputs const& inputs, 
00067                                        Data const& data, 
00068                                        BlockSize const& blockSize,
00069                                        SampleRate const& sampleRate,
00070                                        ChannelArrayType& channels) throw()
00071     :   Internal (FormType::NumCoeffs, inputs, data, blockSize, sampleRate, channels),
00072         inputKeys (ShapeType::getInputKeys())
00073     {
00074         plonk_assert (ShapeType::NumParams == 3);
00075 
00076         SampleRate& filterSampleRate = this->getInputAsSampleRate (IOKey::FilterSampleRate);
00077         filterSampleRate.addReceiver (this);
00078         
00079         updateFilterSampleRateInData();
00080     }
00081     
00082     ~FilterCoeffs3ParamChannelInternal()
00083     {
00084         SampleRate& filterSampleRate = this->getInputAsSampleRate (IOKey::FilterSampleRate);
00085         filterSampleRate.removeReceiver (this);
00086     }
00087             
00088     Text getName() const throw()
00089     {
00090         return "Filter Coeffs 3 Param (" + ShapeType::getFormName() + " / " + ShapeType::getShapeName() + ")";
00091     }       
00092     
00093     IntArray getInputKeys() const throw()
00094     {
00095         return inputKeys;
00096     }    
00097         
00098     void initChannel (const int channel) throw()
00099     {        
00100         plonk_assert (ShapeType::NumParams == 3);
00101 
00102         UnitType& param0Unit = this->getInputAsUnit (inputKeys.atUnchecked (0));
00103         UnitType& param1Unit = this->getInputAsUnit (inputKeys.atUnchecked (1));
00104         UnitType& param2Unit = this->getInputAsUnit (inputKeys.atUnchecked (2));
00105         
00106         plonk_assert (param0Unit.getOverlap (0) == Math<DoubleVariable>::get1());
00107         plonk_assert (param1Unit.getOverlap (0) == Math<DoubleVariable>::get1());
00108         plonk_assert (param2Unit.getOverlap (0) == Math<DoubleVariable>::get1());
00109 
00110         if ((channel % this->getNumChannels()) == 0)
00111         {
00112             this->setBlockSize (BlockSize::decide (param0Unit.getBlockSize (0),
00113                                                    this->getBlockSize()));
00114             this->setSampleRate (SampleRate::decide (param0Unit.getSampleRate (0),
00115                                                      this->getSampleRate()));
00116             
00117             Data& data = this->getState();
00118             data.params[0] = param0Unit.getValue (0);
00119             data.params[1] = param1Unit.getValue (0);
00120             data.params[2] = param2Unit.getValue (0);
00121             
00122             ShapeType::calculate (data);
00123             
00124             for (int i = 0; i < FormType::NumCoeffs; ++i)
00125                 this->initProxyValue (i, data.coeffs[i]);            
00126         }
00127     }    
00128     
00129     void changed (DoubleVariable::Sender const& source, Text const& message, Dynamic const& payload) throw()
00130     {        
00131         SampleRate sampleRateSource = static_cast<SampleRate> (source);
00132         
00133         if (sampleRateSource == this->getInputAsSampleRate (IOKey::FilterSampleRate))
00134         {
00135             this->updateFilterSampleRateInData();
00136             return;
00137         }
00138                 
00139         Internal::changed (source, message, payload); // process others
00140     }    
00141     
00142     void updateFilterSampleRateInData() throw()
00143     {
00144         const SampleRate& filterSampleRate = this->getInputAsSampleRate (IOKey::FilterSampleRate);
00145         Data& data = this->getState();
00146 
00147         data.filterSampleRate = filterSampleRate.getValue();
00148         data.filterSampleDuration = 1.0 / data.filterSampleRate;
00149     }
00150     
00151     void process (ProcessInfo& info, const int /*channel*/) throw()
00152     {   
00153         int i, j;
00154 
00155         Data& data = this->getState();
00156                             
00157         const int outputBufferLength = this->getOutputBuffer (0).length();
00158             
00159         UnitType& param0Unit = this->getInputAsUnit (inputKeys.atUnchecked (0));
00160         UnitType& param1Unit = this->getInputAsUnit (inputKeys.atUnchecked (1));
00161         UnitType& param2Unit = this->getInputAsUnit (inputKeys.atUnchecked (2));
00162         
00163         const Buffer& param0Buffer (param0Unit.process (info, 0));
00164         const Buffer& param1Buffer (param1Unit.process (info, 0));
00165         const Buffer& param2Buffer (param2Unit.process (info, 0));
00166         const SampleType* const param0Samples = param0Buffer.getArray();
00167         const SampleType* const param1Samples = param1Buffer.getArray();
00168         const SampleType* const param2Samples = param2Buffer.getArray();
00169         
00170         const int param0BufferLength = param0Buffer.length();
00171         const int param1BufferLength = param1Buffer.length();
00172         const int param2BufferLength = param2Buffer.length();
00173         
00174         if (outputBufferLength == param0BufferLength)
00175         {
00176             if ((outputBufferLength == param1BufferLength) &&
00177                 (outputBufferLength == param2BufferLength))
00178             {
00179                 // NNN
00180                 for (i = 0; i < outputBufferLength; ++i)
00181                 {
00182                     data.params[0] = param0Samples[i];
00183                     data.params[1] = param1Samples[i];
00184                     data.params[2] = param2Samples[i];
00185                     
00186                     ShapeType::calculate (data);
00187                     
00188                     for (j = 0; j < FormType::NumCoeffs; ++j)
00189                         this->getOutputSamples (j) [i] = data.coeffs[j];
00190                 }            
00191             }
00192             else if (param1BufferLength == 1)
00193             {
00194                 if (outputBufferLength == param2BufferLength)
00195                 {   
00196                     // N1N
00197                     data.params[1] = param1Samples[0];
00198 
00199                     for (i = 0; i < outputBufferLength; ++i)
00200                     {
00201                         data.params[0] = param0Samples[i];
00202                         data.params[2] = param2Samples[i];
00203                         
00204                         ShapeType::calculate (data);
00205                         
00206                         for (j = 0; j < FormType::NumCoeffs; ++j)
00207                             this->getOutputSamples (j) [i] = data.coeffs[j];
00208                     }            
00209                 }
00210                 else if (param2BufferLength == 1)
00211                 {
00212                     // N11
00213                     data.params[1] = param1Samples[0];
00214                     data.params[2] = param2Samples[0];
00215 
00216                     for (i = 0; i < outputBufferLength; ++i)
00217                     {
00218                         data.params[0] = param0Samples[i];
00219                         
00220                         ShapeType::calculate (data);
00221                         
00222                         for (j = 0; j < FormType::NumCoeffs; ++j)
00223                             this->getOutputSamples (j) [i] = data.coeffs[j];
00224                     }            
00225                 }
00226                 else goto fallback; // Nnn
00227             }
00228             else if (param2BufferLength == 1)
00229             {
00230                 if (outputBufferLength == param1BufferLength)
00231                 {
00232                     // NN1
00233                     data.params[2] = param2Samples[0];
00234 
00235                     for (i = 0; i < outputBufferLength; ++i)
00236                     {
00237                         data.params[0] = param0Samples[i];
00238                         data.params[1] = param1Samples[i];
00239                         
00240                         ShapeType::calculate (data);
00241                         
00242                         for (j = 0; j < FormType::NumCoeffs; ++j)
00243                             this->getOutputSamples (j) [i] = data.coeffs[j];
00244                     }            
00245                 }
00246                 else goto fallback; // Nn1
00247             }
00248             else goto fallback; //?
00249         }
00250         else if (param0BufferLength == 1)
00251         {
00252             if ((outputBufferLength == param1BufferLength) &&
00253                 (outputBufferLength == param2BufferLength))
00254             {
00255                 // 1NN
00256                 data.params[0] = param0Samples[0];
00257 
00258                 for (i = 0; i < outputBufferLength; ++i)
00259                 {
00260                     data.params[1] = param1Samples[i];
00261                     data.params[2] = param2Samples[i];
00262                     
00263                     ShapeType::calculate (data);
00264                     
00265                     for (j = 0; j < FormType::NumCoeffs; ++j)
00266                         this->getOutputSamples (j) [i] = data.coeffs[j];
00267                 }            
00268             }
00269             else if (param1BufferLength == 1)
00270             {
00271                 if (param2BufferLength == outputBufferLength)
00272                 {
00273                     // 11N
00274                     data.params[0] = param0Samples[0];
00275                     data.params[1] = param1Samples[0];
00276 
00277                     for (i = 0; i < outputBufferLength; ++i)
00278                     {
00279                         data.params[2] = param2Samples[i];
00280                         
00281                         ShapeType::calculate (data);
00282                         
00283                         for (j = 0; j < FormType::NumCoeffs; ++j)
00284                             this->getOutputSamples (j) [i] = data.coeffs[j];
00285                     }            
00286                 }
00287                 else if (param2BufferLength == 1)
00288                 {
00289                     // 111
00290                     data.params[0] = param0Samples[0];
00291                     data.params[1] = param1Samples[0];
00292                     data.params[2] = param2Samples[0];
00293                     
00294                     ShapeType::calculate (data);
00295 
00296                     for (i = 0; i < outputBufferLength; ++i)
00297                     {
00298                         for (j = 0; j < FormType::NumCoeffs; ++j)
00299                             this->getOutputSamples (j) [i] = data.coeffs[j];
00300                     }            
00301                 }
00302                 else goto fallback; // 11n
00303             }
00304             else if (param2BufferLength == 1)
00305             {
00306                 if (param1BufferLength == outputBufferLength)
00307                 {
00308                     // 1N1
00309                     data.params[0] = param0Samples[0];
00310                     data.params[2] = param2Samples[0];
00311 
00312                     for (i = 0; i < outputBufferLength; ++i)
00313                     {
00314                         data.params[1] = param1Samples[i];
00315                         
00316                         ShapeType::calculate (data);
00317                         
00318                         for (j = 0; j < FormType::NumCoeffs; ++j)
00319                             this->getOutputSamples (j) [i] = data.coeffs[j];
00320                     }            
00321                 }
00322                 goto fallback; // 1n1
00323             }
00324             else goto fallback; // 1nn
00325         }
00326         else goto fallback; // nnn
00327         
00328         return;
00329         
00330     fallback:
00331         {
00332             double param0Position = 0.0;
00333             const double param0Increment = double (param0BufferLength) / double (outputBufferLength);
00334             double param1Position = 0.0;
00335             const double param1Increment = double (param1BufferLength) / double (outputBufferLength);
00336             double param2Position = 0.0;
00337             const double param2Increment = double (param2BufferLength) / double (outputBufferLength);
00338             
00339             for (i = 0; i < outputBufferLength; ++i)
00340             {
00341                 data.params[0] = param0Samples[int (param0Position)];
00342                 data.params[1] = param1Samples[int (param1Position)];
00343                 data.params[2] = param2Samples[int (param2Position)];
00344                 
00345                 ShapeType::calculate (data);
00346                 
00347                 for (j = 0; j < FormType::NumCoeffs; ++j)
00348                     this->getOutputSamples (j) [i] = data.coeffs[j];
00349                 
00350                 param0Position += param0Increment;
00351                 param1Position += param1Increment;
00352                 param2Position += param2Increment;
00353             }        
00354         }
00355     }
00356     
00357 private:
00358     IntArray inputKeys;
00359 };
00360 
00361 
00362 
00363 
00364 
00367 template<class ShapeType>
00368 class FilterCoeffs3ParamUnit
00369 {
00370 public:        
00371     typedef typename ShapeType::SampleDataType              SampleType;
00372     typedef typename ShapeType::Data                        Data;
00373     typedef typename ShapeType::FormType                    FormType;
00374         
00375     typedef FilterCoeffs3ParamChannelInternal<ShapeType>    FilterCoeffsInternal;
00376     typedef ChannelBase<SampleType>                         ChannelType;
00377     typedef ChannelInternal<SampleType,Data>                Internal;
00378     typedef UnitBase<SampleType>                            UnitType;
00379     typedef InputDictionary                                 Inputs;
00380     
00381     static inline UnitInfos getInfo() throw()
00382     {
00383         const double sampleRate = SampleRate::getDefault().getValue();
00384         
00385         return UnitInfo ("Filter Coeffs 3 Param", "Filter coefficients generator for an IIR filter using three control parameters.",
00386                          
00387                          // output
00388                          FormType::NumCoeffs, 
00389                          IOKey::Coeffs,             Measure::Coeffs,    0.0,                IOLimit::None,
00390                          IOKey::End,
00391                          
00392                          // inputs
00393                          IOKey::Generic,            Measure::Unknown,   IOInfo::NoDefault,  IOLimit::None,
00394                          IOKey::Generic,            Measure::Unknown,   IOInfo::NoDefault,  IOLimit::None,
00395                          IOKey::Generic,            Measure::Unknown,   IOInfo::NoDefault,  IOLimit::None,
00396                          IOKey::FilterSampleRate,   Measure::Hertz,     sampleRate,         IOLimit::Minimum,   Measure::Hertz,             0.0,
00397                          IOKey::BlockSize,          Measure::Samples,   0.0,                IOLimit::Minimum,   Measure::Samples,           1.0,
00398                          IOKey::SampleRate,         Measure::Hertz,     -1.0,               IOLimit::Minimum,   Measure::Hertz,             0.0,
00399                          IOKey::End);
00400     }
00401     
00402     
00405     static UnitType ar (UnitType const& param0,
00406                         UnitType const& param1,
00407                         UnitType const& param2,
00408                         SampleRates const filterSampleRates = SampleRate::getDefault(),
00409                         BlockSize const& preferredBlockSize = BlockSize::noPreference(),
00410                         SampleRate const& preferredSampleRate = SampleRate::noPreference()) throw()
00411     {                
00412         const IntArray inputKeys = ShapeType::getInputKeys();
00413         
00414         plonk_assert (inputKeys.length() == 3);
00415         
00416         const int numInputChannels = plonk::max (param0.getNumChannels(), param1.getNumChannels(), param2.getNumChannels());
00417         const int numSampleRates = filterSampleRates.length();
00418         const int numChannels = filterSampleRates.areAllEqual() ? numInputChannels : plonk::max (numInputChannels, numSampleRates);
00419         UnitType result (UnitType::emptyWithAllocatedSize (numChannels * FormType::NumCoeffs));
00420         
00421         Data data;
00422         Memory::zero (data);
00423         data.base.sampleRate = -1.0;
00424         data.base.sampleDuration = -1.0;
00425 
00426         for (int i = 0; i < numChannels; ++i)
00427         {
00428             Inputs inputs;
00429             inputs.put (inputKeys.atUnchecked (0), param0[i]);
00430             inputs.put (inputKeys.atUnchecked (1), param1[i]);
00431             inputs.put (inputKeys.atUnchecked (2), param2[i]);
00432             inputs.put (IOKey::FilterSampleRate, filterSampleRates.wrapAt (i));
00433             
00434             result.add (UnitType::template proxiesFromInputs<FilterCoeffsInternal> (inputs, 
00435                                                                                     data, 
00436                                                                                     preferredBlockSize, 
00437                                                                                     preferredSampleRate));
00438         }
00439         
00440         return result;
00441     }
00442 };
00443 
00444 
00445 
00446 
00447 #endif // PLONK_FILTERCOEFFS3PARAM_H
00448 
 All Classes Functions Typedefs Enumerations Enumerator Properties