![]() |
pl-nk v0.4.5
Plonk|Plink|Plank are a set of cross-platform C/C++ frameworks for audio software development
|
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