![]() |
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_UNARYOPCHANNEL_H 00040 #define PLONK_UNARYOPCHANNEL_H 00041 00042 #include "../../maths/plonk_InlineUnaryOps.h" 00043 #include "../channel/plonk_ChannelInternalCore.h" 00044 #include "../plonk_GraphForwardDeclarations.h" 00045 00046 template<class SampleType> 00047 class UnaryOpUtility 00048 { 00049 private: 00050 typedef SampleType (*Function)(SampleType const&); 00051 typedef typename UnaryOpFunctionsHelper<SampleType>::UnaryOpFunctionsType UnaryOpFunctionsType; 00052 00053 UnaryOpUtility() throw() 00054 { 00055 names.put (&UnaryOpFunctionsType::move, "move"); 00056 names.put (&UnaryOpFunctionsType::inc, "inc"); 00057 names.put (&UnaryOpFunctionsType::dec, "dec"); 00058 names.put (&UnaryOpFunctionsType::abs, "abs"); 00059 names.put (&UnaryOpFunctionsType::log2, "log2"); 00060 names.put (&UnaryOpFunctionsType::neg, "neg"); 00061 names.put (&UnaryOpFunctionsType::reciprocal, "reciprocal"); 00062 names.put (&UnaryOpFunctionsType::sin, "sin"); 00063 names.put (&UnaryOpFunctionsType::cos, "cos"); 00064 names.put (&UnaryOpFunctionsType::tan, "tan"); 00065 names.put (&UnaryOpFunctionsType::asin, "asin"); 00066 names.put (&UnaryOpFunctionsType::acos, "acos"); 00067 names.put (&UnaryOpFunctionsType::atan, "atan"); 00068 names.put (&UnaryOpFunctionsType::sinh, "sinh"); 00069 names.put (&UnaryOpFunctionsType::cosh, "cosh"); 00070 names.put (&UnaryOpFunctionsType::tanh, "tanh"); 00071 names.put (&UnaryOpFunctionsType::sqrt, "sqrt"); 00072 names.put (&UnaryOpFunctionsType::log, "log"); 00073 names.put (&UnaryOpFunctionsType::log10, "log10"); 00074 names.put (&UnaryOpFunctionsType::exp, "exp"); 00075 names.put (&UnaryOpFunctionsType::squared, "squared"); 00076 names.put (&UnaryOpFunctionsType::cubed, "cubed"); 00077 names.put (&UnaryOpFunctionsType::ceil, "ceil"); 00078 names.put (&UnaryOpFunctionsType::floor, "floor"); 00079 names.put (&UnaryOpFunctionsType::frac, "frac"); 00080 names.put (&UnaryOpFunctionsType::sign, "sign"); 00081 names.put (&UnaryOpFunctionsType::m2f, "MIDI to frequency"); 00082 names.put (&UnaryOpFunctionsType::f2m, "Frequency to MIDI"); 00083 names.put (&UnaryOpFunctionsType::a2dB, "Amplitude to dB"); 00084 names.put (&UnaryOpFunctionsType::dB2a, "dB to Amplitude"); 00085 names.put (&UnaryOpFunctionsType::d2r, "Degrees to Radians"); 00086 names.put (&UnaryOpFunctionsType::r2d, "Radians to Degrees"); 00087 names.put (&UnaryOpFunctionsType::distort, "distort"); 00088 names.put (&UnaryOpFunctionsType::zap, "zap"); 00089 } 00090 00091 public: 00092 inline Text getName (Function function) const throw() 00093 { 00094 return names[function]; 00095 } 00096 00097 inline void add (Function function, Text const& name) throw() 00098 { 00099 names.put (function, name); 00100 } 00101 00102 static UnaryOpUtility& global() throw() 00103 { 00104 static UnaryOpUtility util; 00105 return util; 00106 } 00107 00108 private: 00109 Dictionary<Text, Function> names; 00110 }; 00111 00112 00113 //------------------------------------------------------------------------------ 00114 00115 00117 template<class SampleType, PLONK_UNARYOPFUNCTION(SampleType, op)> 00118 class UnaryOpChannelInternal 00119 : public ChannelInternal<SampleType, ChannelInternalCore::Data> 00120 { 00121 public: 00122 typedef typename ChannelInternalCore::Data Data; 00123 typedef typename UnaryOpFunctionsHelper<SampleType>::UnaryOpFunctionsType UnaryOpFunctionsType; 00124 00125 typedef ChannelBase<SampleType> ChannelType; 00126 typedef UnaryOpChannelInternal<SampleType,op> UnaryOpInternal; 00127 typedef ChannelInternal<SampleType,Data> Internal; 00128 typedef ChannelInternalBase<SampleType> InternalBase; 00129 typedef UnitBase<SampleType> UnitType; 00130 typedef InputDictionary Inputs; 00131 typedef NumericalArray<SampleType> Buffer; 00132 typedef UnaryOpUtility<SampleType> UtilityType; 00133 00134 00135 UnaryOpChannelInternal (Inputs const& inputs, 00136 Data const& data, 00137 BlockSize const& blockSize, 00138 SampleRate const& sampleRate) throw() 00139 : Internal (inputs, data, blockSize, sampleRate) 00140 { 00141 } 00142 00143 Text getName() const throw() 00144 { 00145 Text variant = UtilityType::global().getName (op); 00146 00147 if (variant.length() < 1) 00148 variant = "unknown type"; 00149 00150 return "Unary Operator (" + variant + ")"; 00151 } 00152 00153 IntArray getInputKeys() const throw() 00154 { 00155 const IntArray keys (IOKey::Generic); 00156 return keys; 00157 } 00158 00159 InternalBase* getChannel (const int index) throw() 00160 { 00161 const Inputs channelInputs = this->getInputs().getChannel (index); 00162 return new UnaryOpInternal (channelInputs, 00163 this->getState(), 00164 this->getBlockSize(), 00165 this->getSampleRate()); 00166 } 00167 00168 void initChannel (const int channel) throw() 00169 { 00170 const UnitType& input = this->getInputAsUnit (IOKey::Generic); 00171 const SampleType sourceValue = input.getValue (channel); 00172 00173 this->setBlockSize (BlockSize::decide (input.getBlockSize (channel), 00174 this->getBlockSize())); 00175 this->setSampleRate (SampleRate::decide (input.getSampleRate (channel), 00176 this->getSampleRate())); 00177 00178 this->setOverlap (input.getOverlap (channel)); 00179 00180 this->initValue (op (sourceValue)); 00181 } 00182 00183 void process (ProcessInfo& info, const int channel) throw() 00184 { 00185 UnitType& operandUnit (this->getInputAsUnit (IOKey::Generic)); 00186 const Buffer& operandBuffer (operandUnit.process (info, channel)); 00187 00188 SampleType* const outputSamples = this->getOutputSamples(); 00189 const int outputBufferLength = this->getOutputBuffer().length(); 00190 00191 const SampleType* const operandSamples = operandBuffer.getArray(); 00192 const int operandBufferLength = operandBuffer.length(); 00193 00194 int i; 00195 00196 if (operandBufferLength == outputBufferLength) 00197 { 00198 NumericalArrayUnaryOp<SampleType,op>::calc (outputSamples, operandSamples, outputBufferLength); 00199 } 00200 else if (operandBufferLength == 1) 00201 { 00202 NumericalArrayFiller<SampleType>::fill (outputSamples, operandSamples[0], outputBufferLength); 00203 } 00204 else 00205 { 00206 double operandPosition = 0.0; 00207 const double operandIncrement = double (operandBufferLength) / double (outputBufferLength); 00208 00209 for (i = 0; i < outputBufferLength; ++i) 00210 { 00211 outputSamples[i] = op (operandSamples[int (operandPosition)]); 00212 operandPosition += operandIncrement; 00213 } 00214 } 00215 } 00216 }; 00217 00218 00219 #endif // PLONK_UNARYOPCHANNEL_H