pl-nk v0.4.5
Plonk|Plink|Plank are a set of cross-platform C/C++ frameworks for audio software development
plonk_DelayFormDelay.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_DELAYFORMDELAY_H
00040 #define PLONK_DELAYFORMDELAY_H
00041 
00042 #include "../channel/plonk_ChannelInternalCore.h"
00043 #include "plonk_DelayForwardDeclarations.h"
00044 
00045 
00046 template<class SampleType, Interp::TypeCode InterpTypeCode>
00047 class DelayFormDelay
00048 :   public DelayForm<SampleType, DelayFormType::Delay, 1, 1>
00049 {
00050 public:
00051     typedef DelayForm<SampleType, DelayFormType::Delay, 1, 1>       Base;
00052     
00053     enum InParams
00054     {
00055         Duration,
00056         NumInParams
00057     };
00058     
00059     enum OutParams
00060     {
00061         DurationInSamples,
00062         NumOutParams
00063     };
00064 
00065     typedef typename Base::Data                                     Data;
00066     typedef typename Data::DelayState                               DelayState;
00067     typedef DelayFormDelay                                          FormType;
00068  
00069     typedef SampleType                                              SampleDataType;
00070     typedef Delay1ParamChannelInternal<FormType>                    DelayInternal;
00071     typedef ChannelBase<SampleType>                                 ChannelType;
00072     typedef ChannelInternal<SampleType,Data>                        Internal;
00073     typedef UnitBase<SampleType>                                    UnitType;
00074     typedef InputDictionary                                         Inputs;
00075     typedef NumericalArray<SampleType>                              Buffer;
00076     
00077     typedef typename TypeUtility<SampleType>::IndexType             Param1Type;  
00078     typedef Param1Type                                              DurationType;    
00079     typedef UnitBase<DurationType>                                  DurationUnitType;
00080     typedef NumericalArray<DurationType>                            DurationBufferType;
00081     typedef ChannelBase<DurationType>                               DurationChannelType;
00082     typedef NumericalArray2D<DurationChannelType,DurationUnitType>  DurationUnitArrayType;
00083     
00084     typedef NumericalArray2D<ChannelType,UnitType>                  UnitArrayType;
00085     typedef InterpSelect<SampleType,DurationType,InterpTypeCode>    InterpSelectType;
00086     typedef typename InterpSelectType::InterpType                   InterpType;
00087     typedef typename InterpType::ExtensionBuffer                    ExtensionBuffer;
00088 
00089     typedef void (*InputFunction)  (Data&, DelayState&);
00090     typedef void (*ReadFunction)   (Data&, DelayState&);
00091     typedef void (*WriteFunction)  (Data&, DelayState&);
00092     typedef void (*OutputFunction) (Data&, DelayState&);
00093     typedef void (*Param1Function) (Data&, DelayState&, Param1Type const&);
00094 
00095     static inline IntArray getInputKeys() throw()
00096     {
00097         const IntArray keys (IOKey::Generic, IOKey::Duration);
00098         return keys;
00099     }    
00100     
00101     static inline void inputIgnore (Data&, DelayState&) throw() { }
00102     static inline void inputRead (Data&, DelayState& state) throw()
00103     {
00104         state.inputValue = *state.inputSamples++;
00105     }
00106     
00107     static inline void readIgnore (Data&, DelayState&) throw() { }
00108     static inline void readRead (Data&, DelayState& state) throw()
00109     {
00110         DurationType readPosition = DurationType (state.writePosition) - state.paramsOut[DurationInSamples] + state.bufferLengthIndex;
00111 //        plonk_assert (readPosition >= 0 && readPosition <= state.bufferLengthIndex);
00112         state.readValue = InterpType::lookup (state.bufferSamples, readPosition);
00113     }
00114         
00115     static inline void writeIgnore (Data&, DelayState&) throw() { }
00116     static inline void writeWrite (Data&, DelayState& state) throw()
00117     {
00118         plonk_assert (state.writePosition >= 0 && state.writePosition < state.bufferLength);
00119         state.writeValue = state.inputValue;
00120         state.bufferSamples[state.writePosition] = state.writeValue;
00121         state.bufferSamples[state.writePosition + state.bufferLength] = state.writeValue; // for interpolation
00122         state.bufferSamples[state.writePosition + state.bufferLength + state.bufferLength] = state.writeValue; // for interpolation
00123     }
00124     
00125     static inline void outputIgnore (Data&, DelayState&) throw() { }
00126     static inline void outputWrite (Data&, DelayState& state) throw()
00127     {
00128         state.outputValue = state.readValue;
00129         *state.outputSamples++ = state.outputValue;
00130         state.writePosition++;
00131     }
00132     
00133     static inline void param1Ignore (Data&, DelayState&, DurationType const&) throw() { }
00134     static inline void param1Process (Data& data, DelayState& state, DurationType const& duration) throw()
00135     {
00136         state.paramsIn[Duration] = duration;
00137         state.paramsOut[DurationInSamples] = DurationType (duration * data.base.sampleRate);
00138         plonk_assert (state.paramsOut[DurationInSamples] >= 0 && 
00139                       state.paramsOut[DurationInSamples] <= state.bufferLengthIndex);
00140     }
00141     
00142     template<InputFunction inputFunction, 
00143              ReadFunction readFunction,
00144              WriteFunction writeFunction,
00145              OutputFunction outputFunction>
00146     static inline void tick (Data& data, DelayState& state) throw()
00147     {
00148         inputFunction (data, state);
00149         writeFunction (data, state);
00150         readFunction (data, state);  
00151         outputFunction (data, state);
00152     }
00153     
00154     static inline UnitType ar (UnitType const& input,
00155                                DurationUnitType const& duration,
00156                                const DurationType maximumDuration,
00157                                UnitType const& mul,
00158                                UnitType const& add,
00159                                BlockSize const& preferredBlockSize,
00160                                SampleRate const& preferredSampleRate) throw()
00161     {             
00162         const Data data = { { -1.0, -1.0 }, maximumDuration, 0, };
00163         
00164         const int numInputChannels = input.getNumChannels();
00165         const int numDurationChannels = duration.getNumChannels();
00166         const int numChannels = plonk::max (numInputChannels, numDurationChannels);
00167         
00168         if (numChannels == 1)
00169         {
00170             Inputs inputs;
00171             inputs.put (IOKey::Generic, input);
00172             inputs.put (IOKey::Duration, duration);
00173             inputs.put (IOKey::Multiply, mul);
00174             inputs.put (IOKey::Add, add);
00175             
00176             return UnitType::template proxiesFromInputs<DelayInternal> (inputs,
00177                                                                         data, 
00178                                                                         preferredBlockSize, 
00179                                                                         preferredSampleRate);
00180         }
00181         else
00182         {
00183             DurationUnitArrayType durationsGrouped = duration.deinterleave (numInputChannels);
00184             UnitArrayType resultGrouped;
00185             
00186             for (int i = 0; i < numInputChannels; ++i)
00187             {
00188                 Inputs inputs;
00189                 inputs.put (IOKey::Generic, input[i]);
00190                 inputs.put (IOKey::Duration, durationsGrouped.wrapAt (i));
00191                 
00192                 UnitType unit = UnitType::template proxiesFromInputs<DelayInternal> (inputs,
00193                                                                                      data,
00194                                                                                      preferredBlockSize,
00195                                                                                      preferredSampleRate);
00196                 resultGrouped.add (unit);
00197             }
00198             
00199             const UnitType mainUnit (resultGrouped.interleave());
00200             plonk_assert (mainUnit.getNumChannels() == numChannels);
00201             return UnitType::applyMulAdd (mainUnit, mul, add);
00202         }
00203     }
00204 
00205 };
00206 
00207 //------------------------------------------------------------------------------
00208 
00224 template<class SampleType, Interp::TypeCode InterpTypeCode>
00225 class DelayUnit
00226 {
00227 public:    
00228     typedef DelayFormDelay<SampleType,InterpTypeCode>   FormType;
00229     
00230     typedef Delay1ParamChannelInternal<FormType>        DelayInternal;
00231     typedef UnitBase<SampleType>                        UnitType;
00232     typedef InputDictionary                             Inputs;
00233     
00234     typedef typename DelayInternal::Param1Type          DurationType;
00235     typedef UnitBase<DurationType>                      DurationUnitType;
00236 
00237     typedef DelayUnit<SampleType, Interp::Lagrange3>    HQ;
00238     typedef DelayUnit<SampleType, Interp::None>         N;
00239     
00240     static inline UnitInfos getInfo() throw()
00241     {
00242         const double blockSize = (double)BlockSize::getDefault().getValue();
00243         const double sampleRate = SampleRate::getDefault().getValue();
00244         
00245         return UnitInfo ("Delay", "A simple delay processor.",
00246                          
00247                          // output
00248                          ChannelCount::VariableChannelCount, 
00249                          IOKey::Generic,            Measure::None,      0.0,                IOLimit::None,                         
00250                          IOKey::End,
00251                          
00252                          // inputs
00253                          IOKey::Generic,            Measure::None,      IOInfo::NoDefault,  IOLimit::None,
00254                          IOKey::Duration,           Measure::Seconds,   0.5,                IOLimit::Minimum,   Measure::Seconds,   0.0,
00255                          IOKey::MaximumDuration,    Measure::Seconds,   1.0,                IOLimit::Minimum,   Measure::Samples,   1.0,
00256                          IOKey::Multiply,           Measure::Factor,    1.0,                IOLimit::None,
00257                          IOKey::Add,                Measure::None,      0.0,                IOLimit::None,
00258                          IOKey::BlockSize,          Measure::Samples,   blockSize,          IOLimit::Minimum,   Measure::Samples,   1.0,
00259                          IOKey::SampleRate,         Measure::Hertz,     sampleRate,         IOLimit::Minimum,   Measure::Hertz,     0.0,
00260                          IOKey::End);
00261     }
00262     
00263     static UnitType ar (UnitType const& input,
00264                         DurationUnitType const& duration = DurationType (0.5),
00265                         const DurationType maximumDuration = DurationType (1.0),
00266                         UnitType const& mul = SampleType (1),
00267                         UnitType const& add = SampleType (0),
00268                         BlockSize const& preferredBlockSize = BlockSize::getDefault(),
00269                         SampleRate const& preferredSampleRate = SampleRate::getDefault()) throw()
00270     {             
00271         return FormType::ar (input, duration, maximumDuration, mul, add, preferredBlockSize, preferredSampleRate);
00272     }
00273     
00274 };
00275 
00276 typedef DelayUnit<PLONK_TYPE_DEFAULT> Delay;
00277 
00278 
00279 
00280 #endif // PLONK_DELAYFORMDELAY_H
00281 
 All Classes Functions Typedefs Enumerations Enumerator Properties