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