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