pl-nk v0.4.5
Plonk|Plink|Plank are a set of cross-platform C/C++ frameworks for audio software development
plonk_Delay4Param.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_DELAY4PARAM_H
00040 #define PLONK_DELAY4PARAM_H
00041 
00042 #include "../channel/plonk_ChannelInternalCore.h"
00043 #include "plonk_DelayForwardDeclarations.h"
00044 
00045 
00047 template<class FormType>
00048 class Delay4ParamChannelInternal
00049 :   public DelayChannelInternalBase<FormType>
00050 {
00051 public:
00052     typedef typename FormType::SampleDataType               SampleType;
00053     typedef typename FormType::Data                         Data;
00054     typedef typename FormType::DelayState                   DelayState;
00055 
00056     typedef ObjectArray<DelayState>                         DelayStateArray;
00057 
00058     typedef ChannelBase<SampleType>                         ChannelType;
00059     typedef ObjectArray<ChannelType>                        ChannelArrayType;
00060     typedef Delay4ParamChannelInternal<FormType>            DelayInternal;
00061     typedef DelayChannelInternalBase<FormType>              Internal;
00062     typedef ChannelInternalBase<SampleType>                 InternalBase;
00063     typedef UnitBase<SampleType>                            UnitType;
00064     typedef InputDictionary                                 Inputs;
00065     typedef NumericalArray<SampleType>                      Buffer;
00066     
00067     typedef typename TypeUtility<SampleType>::IndexType     DurationType;
00068     
00069     typedef typename FormType::Param1Type                   Param1Type;
00070     typedef UnitBase<Param1Type>                            Param1UnitType;
00071     typedef NumericalArray<Param1Type>                      Param1BufferType;
00072 
00073     typedef typename FormType::Param2Type                   Param2Type;
00074     typedef UnitBase<Param2Type>                            Param2UnitType;
00075     typedef NumericalArray<Param2Type>                      Param2BufferType;
00076 
00077     typedef typename FormType::Param3Type                   Param3Type;
00078     typedef UnitBase<Param3Type>                            Param3UnitType;
00079     typedef NumericalArray<Param3Type>                      Param3BufferType;
00080 
00081     typedef typename FormType::Param4Type                   Param4Type;
00082     typedef UnitBase<Param4Type>                            Param4UnitType;
00083     typedef NumericalArray<Param4Type>                      Param4BufferType;
00084 
00085     typedef typename FormType::InputFunction                InputFunction;
00086     typedef typename FormType::ReadFunction                 ReadFunction;
00087     typedef typename FormType::WriteFunction                WriteFunction;
00088     typedef typename FormType::OutputFunction               OutputFunction;
00089     typedef typename FormType::Param1Function               Param1Function;
00090     typedef typename FormType::Param2Function               Param2Function;
00091     typedef typename FormType::Param3Function               Param3Function;
00092     typedef typename FormType::Param4Function               Param4Function;
00093     
00094     enum Params
00095     {
00096         Param1,
00097         Param2, 
00098         Param3,
00099         Param4,
00100         NumParams
00101     };
00102     
00103     Delay4ParamChannelInternal (Inputs const& inputs, 
00104                                 Data const& data, 
00105                                 BlockSize const& blockSize,
00106                                 SampleRate const& sampleRate,
00107                                 ChannelArrayType& channels) throw()
00108     :   Internal (getNumChannelsFromInputs (inputs), // num proxies
00109                   inputs, data, blockSize, sampleRate, channels),
00110         inputKeys (FormType::getInputKeys())
00111     {
00112     }
00113         
00114     void process (ProcessInfo& info, const int /*channel*/) throw()
00115     {
00116         Data& data = this->getState();
00117         DelayStateArray& delayStates = this->getDelayStates();
00118 
00119         UnitType& inputUnit = this->getInputAsUnit (IOKey::Generic);
00120         const Buffer& inputBuffer (inputUnit.process (info, 0));
00121         Param1UnitType& param1Unit = ChannelInternalCore::getInputAs<Param1UnitType> (inputKeys.atUnchecked (1));
00122         Param2UnitType& param2Unit = ChannelInternalCore::getInputAs<Param2UnitType> (inputKeys.atUnchecked (2));
00123         Param3UnitType& param3Unit = ChannelInternalCore::getInputAs<Param3UnitType> (inputKeys.atUnchecked (3));
00124         Param4UnitType& param4Unit = ChannelInternalCore::getInputAs<Param4UnitType> (inputKeys.atUnchecked (4));
00125         
00126         plonk_assert (inputBuffer.length() == this->getOutputBuffer (0).length());
00127         
00128         const int writePosition = process<FormType::inputRead, 
00129                                           FormType::readRead, 
00130                                           FormType::writeWrite, 
00131                                           FormType::outputWrite,
00132                                           FormType::param1Process,
00133                                           FormType::param2Process,
00134                                           FormType::param3Process,
00135                                           FormType::param4Process>
00136                                     (this->getOutputSamples (0), 
00137                                      this->getOutputBuffer (0).length(), 
00138                                      inputBuffer.getArray(), 
00139                                      param1Unit,
00140                                      param2Unit,
00141                                      param3Unit,
00142                                      param4Unit,
00143                                      data, delayStates.atUnchecked (0), info, 0);
00144         
00145         const int numChannels = this->getNumChannels();
00146         
00147         for (int i = 1; i < numChannels; ++i)
00148         {
00149             plonk_assert (inputBuffer.length() == this->getOutputBuffer (i).length());
00150             
00151             process<FormType::inputIgnore, 
00152                     FormType::readRead, 
00153                     FormType::writeIgnore, 
00154                     FormType::outputWrite,
00155                     FormType::param1Process,
00156                     FormType::param2Process,
00157                     FormType::param3Process,
00158                     FormType::param4Process>
00159                 (this->getOutputSamples (i), 
00160                  this->getOutputBuffer (i).length(), 
00161                  0, 
00162                  param1Unit, 
00163                  param2Unit,
00164                  param3Unit,
00165                  param4Unit,
00166                  data, delayStates.atUnchecked (i), info, i);
00167         }
00168         
00169         data.writePosition = writePosition; // update the write position from the first channel write
00170     }
00171     
00172 
00173 private:
00174     IntArray inputKeys;
00175     
00176     static inline int getNumChannelsFromInputs (Inputs const& inputs) throw()
00177     {
00178         const int p1 = inputs[FormType::getInputKeys().atUnchecked (1)].template asUnchecked<Param1UnitType>().getNumChannels();
00179         const int p2 = inputs[FormType::getInputKeys().atUnchecked (2)].template asUnchecked<Param2UnitType>().getNumChannels();
00180         const int p3 = inputs[FormType::getInputKeys().atUnchecked (3)].template asUnchecked<Param3UnitType>().getNumChannels();
00181         const int p4 = inputs[FormType::getInputKeys().atUnchecked (4)].template asUnchecked<Param4UnitType>().getNumChannels();
00182         return plonk::max (p1, p2, p3, p4);
00183     }
00184         
00185     template<InputFunction inputFunction, 
00186              ReadFunction readFunction,
00187              WriteFunction writeFunction,
00188              OutputFunction outputFunction,
00189              Param1Function param1Function,
00190              Param2Function param2Function,
00191              Param3Function param3Function,
00192              Param4Function Param4Function>
00193     static int process (SampleType* const outputSamples,
00194                         const int outputBufferLength,
00195                         const SampleType* inputSamples,
00196                         Param1UnitType& param1Unit,
00197                         Param2UnitType& param2Unit,
00198                         Param3UnitType& param3Unit,
00199                         Param4UnitType& param4Unit,
00200                         Buffer& buffer,
00201                         Data& data,
00202                         DelayState& state,
00203                         ProcessInfo& info, 
00204                         const int channel) throw()
00205     {        
00206         state.outputSamples = outputSamples;
00207         state.outputBufferLength = outputBufferLength;
00208         state.inputSamples = inputSamples;
00209         state.writePosition = data.writePosition;
00210 
00211         const Param1BufferType& param1Buffer (param1Unit.process (info, channel));
00212         const Param1Type* param1Samples = param1Buffer.getArray();
00213         const int param1BufferLength = param1Buffer.length();
00214         
00215         const Param2BufferType& param2Buffer (param2Unit.process (info, channel));
00216         const Param2Type* param2Samples = param2Buffer.getArray();
00217         const int param2BufferLength = param2Buffer.length();
00218 
00219         const Param3BufferType& param3Buffer (param3Unit.process (info, channel));
00220         const Param3Type* param3Samples = param3Buffer.getArray();
00221         const int param3BufferLength = param3Buffer.length();
00222 
00223         const Param4BufferType& param4Buffer (param4Unit.process (info, channel));
00224         const Param4Type* param4Samples = param4Buffer.getArray();
00225         const int param4BufferLength = param4Buffer.length();
00226 
00227         int numSamplesToProcess = outputBufferLength;
00228         
00229         if ((param1BufferLength == outputBufferLength) && 
00230             (param2BufferLength == outputBufferLength) &&
00231             (param3BufferLength == outputBufferLength) &&
00232             (param4BufferLength == outputBufferLength))
00233         {            
00234             while (numSamplesToProcess > 0)
00235             {
00236                 int bufferSamplesRemaining = state.bufferLength - state.writePosition;
00237                 int numSamplesThisTime = plonk::min (bufferSamplesRemaining, numSamplesToProcess);
00238                 numSamplesToProcess -= numSamplesThisTime;
00239                 
00240                 while (numSamplesThisTime--) 
00241                 {
00242                     param1Function (data, state, *param1Samples++);  
00243                     param2Function (data, state, *param2Samples++);  
00244                     param3Function (data, state, *param3Samples++);                    
00245                     param4Function (data, state, *param4Samples++);                    
00246 
00247                     FormType::template tick<inputFunction, readFunction, writeFunction, outputFunction> (data, state);                    
00248                 }
00249                 
00250                 if (state.writePosition >= state.bufferLength)
00251                     state.writePosition = 0;
00252             }
00253         }
00254         else if ((param1BufferLength == 1) && 
00255                  (param2BufferLength == 1) && 
00256                  (param3BufferLength == 1) &&
00257                  (param4BufferLength == 1))
00258         {
00259             param1Function (data, state, param1Samples[0]);                    
00260             param2Function (data, state, param2Samples[0]);  
00261             param3Function (data, state, param3Samples[0]); 
00262             param4Function (data, state, param4Samples[0]);                    
00263             
00264             while (numSamplesToProcess > 0)
00265             {
00266                 int bufferSamplesRemaining = state.bufferLength - state.writePosition;
00267                 int numSamplesThisTime = plonk::min (bufferSamplesRemaining, numSamplesToProcess);
00268                 numSamplesToProcess -= numSamplesThisTime;
00269                 
00270                 while (numSamplesThisTime--) 
00271                     FormType::template tick<inputFunction, readFunction, writeFunction, outputFunction> (data, state);
00272                 
00273                 if (state.writePosition >= state.bufferLength)
00274                     state.writePosition = 0;
00275             }
00276         }
00277         else
00278         {                        
00279             double param1Position = 0.0;
00280             const double param1Increment = double (param1BufferLength) / double (outputBufferLength);
00281             double param2Position = 0.0;
00282             const double param2Increment = double (param2BufferLength) / double (outputBufferLength);
00283             double param3Position = 0.0;
00284             const double param3Increment = double (param3BufferLength) / double (outputBufferLength);
00285             double param4Position = 0.0;
00286             const double param4Increment = double (param4BufferLength) / double (outputBufferLength);
00287 
00288             while (numSamplesToProcess > 0)
00289             {
00290                 int bufferSamplesRemaining = state.bufferLength - state.writePosition;
00291                 int numSamplesThisTime = plonk::min (bufferSamplesRemaining, numSamplesToProcess);
00292                 numSamplesToProcess -= numSamplesThisTime;
00293                 
00294                 while (numSamplesThisTime--) 
00295                 {                    
00296                     param1Function (data, state, param1Samples[int (param1Position)]);   
00297                     param2Function (data, state, param2Samples[int (param2Position)]);       
00298                     param3Function (data, state, param3Samples[int (param3Position)]);       
00299                     param4Function (data, state, param4Samples[int (param4Position)]);                    
00300                     FormType::template tick<inputFunction, readFunction, writeFunction, outputFunction> (data, state);
00301                     param1Position += param1Increment;
00302                     param2Position += param2Increment;
00303                     param3Position += param3Increment;
00304                     param4Position += param4Increment;
00305                 }
00306                 
00307                 if (state.writePosition >= state.bufferLength)
00308                     state.writePosition = 0;
00309             }
00310         }
00311         
00312         return state.writePosition;
00313     }
00314 };
00315 
00316 
00317 #endif // PLONK_DELAY4PARAM_H
00318 
 All Classes Functions Typedefs Enumerations Enumerator Properties