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