pl-nk v0.4.5
Plonk|Plink|Plank are a set of cross-platform C/C++ frameworks for audio software development
plonk_DelayFormCombFB.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_DELAYFORMCOMBFB_H
00040 #define PLONK_DELAYFORMCOMBFB_H
00041 
00042 #include "../channel/plonk_ChannelInternalCore.h"
00043 #include "plonk_DelayForwardDeclarations.h"
00044 
00045 template<class SampleType, Interp::TypeCode InterpTypeCode>
00046 class DelayFormCombFB
00047 :   public DelayForm<SampleType, DelayFormType::CombFB, 2, 2>
00048 {
00049 public:
00050     typedef DelayForm<SampleType, DelayFormType::CombFB, 2, 2>      Base;
00051     
00052     enum InParams
00053     {
00054         DurationIn,
00055         FeedbackIn,
00056         NumInParams
00057     };
00058     
00059     enum OutParams
00060     {
00061         DurationInSamplesOut,
00062         FeedbackOut,
00063         NumOutParams
00064     };
00065 
00066     typedef typename Base::Data                                     Data;
00067     typedef typename Data::DelayState                               DelayState;
00068     typedef DelayFormCombFB                                         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                                              FeedbackType;    
00084     typedef UnitBase<FeedbackType>                                  FeedbackUnitType;
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::Feedback);
00100         return keys;
00101     }    
00102     
00103     static inline void inputIgnore (Data&, DelayState&) throw() { }
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[FeedbackOut] * 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     static inline void outputIgnore (Data&, DelayState&) throw() { }
00128     static inline void outputWrite (Data&, DelayState& state) throw()
00129     {
00130         state.outputValue = state.readValue;
00131         *state.outputSamples++ = state.outputValue;
00132         state.writePosition++;
00133     }
00134     
00135     static inline void param1Ignore (Data&, DelayState&, DurationType const&) throw() { }
00136     static inline void param1Process (Data& data, DelayState& state, DurationType const& duration) throw()
00137     {
00138         state.paramsIn[DurationIn] = duration;
00139         state.paramsOut[DurationInSamplesOut] = DurationType (duration * data.base.sampleRate);
00140         plonk_assert (state.paramsOut[DurationInSamplesOut] >= 0 && 
00141                       state.paramsOut[DurationInSamplesOut] <= state.bufferLengthIndex);
00142     }
00143     
00144     static inline void param2Ignore (Data&, DelayState&, FeedbackType const&) throw() { }
00145     static inline void param2Process (Data&, DelayState& state, FeedbackType const& feedback) throw()
00146     {                                
00147         state.paramsIn[FeedbackIn] = state.paramsOut[FeedbackOut] = feedback; // probably faster not to check
00148     }
00149     
00150     template<InputFunction inputFunction, 
00151              ReadFunction readFunction,
00152              WriteFunction writeFunction,
00153              OutputFunction outputFunction>
00154     static inline void tick (Data& data, DelayState& state) throw()
00155     {
00156         inputFunction (data, state);
00157         readFunction (data, state);
00158         writeFunction (data, state);
00159         outputFunction (data, state);
00160     }
00161     
00162     static inline UnitType ar (UnitType const& input,
00163                                DurationUnitType const& duration,
00164                                FeedbackUnitType const& feedback,
00165                                const DurationType maximumDuration,
00166                                UnitType const& mul,
00167                                UnitType const& add,
00168                                BlockSize const& preferredBlockSize,
00169                                SampleRate const& preferredSampleRate) throw()
00170     {             
00171         const Data data = { { -1.0, -1.0 }, maximumDuration, 0 };
00172         
00173         const int numInputChannels = input.getNumChannels();
00174         const int numDurationChannels = duration.getNumChannels();
00175         const int numFeedbackChannels = feedback.getNumChannels();
00176         const int numChannels = plonk::max (numInputChannels, numDurationChannels, numFeedbackChannels);
00177         
00178         UnitType mainUnit = UnitType::emptyChannels (numChannels);
00179         
00180         for (int i = 0; i < numChannels; ++i)
00181         {
00182             Inputs inputs;
00183             inputs.put (IOKey::Generic, input[i]);
00184             inputs.put (IOKey::Duration, duration[i]);
00185             inputs.put (IOKey::Feedback, feedback[i]);
00186             
00187             UnitType unit = UnitType::template proxiesFromInputs<DelayInternal> (inputs, 
00188                                                                                  data,
00189                                                                                  preferredBlockSize,
00190                                                                                  preferredSampleRate);
00191             mainUnit.put (i, unit);
00192         }
00193         
00194         return UnitType::applyMulAdd (mainUnit, mul, add);
00195     }
00196 };
00197 
00198 
00199 //------------------------------------------------------------------------------
00200 
00201 
00219 template<class SampleType, Interp::TypeCode InterpTypeCode>
00220 class CombFBUnit
00221 {
00222 public:    
00223     typedef DelayFormCombFB<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              FeedbackType;
00233     typedef UnitBase<FeedbackType>                          FeedbackUnitType;
00234     
00235     typedef CombFBUnit<SampleType, Interp::Lagrange3>       HQ;
00236     typedef CombFBUnit<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 ("CombFB", "A comb filter setting the feedback amount 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::Feedback,           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                         FeedbackUnitType const& feedback = FeedbackType (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, feedback, maximumDuration, mul, add, preferredBlockSize, preferredSampleRate);
00273     }
00274     
00275 };
00276 
00277 typedef CombFBUnit<PLONK_TYPE_DEFAULT> CombFB;
00278 
00279 
00280 #endif // PLONK_DELAYFORMCOMBFB_H
00281 
 All Classes Functions Typedefs Enumerations Enumerator Properties