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