![]() |
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_INLINEMISCOPS_H 00040 #define PLONK_INLINEMISCOPS_H 00041 00042 #include "plonk_Constants.h" 00043 #include "plonk_InlineUnaryOps.h" 00044 00045 //------------------------------------------------------------------------------ 00046 00054 template<class Type> inline Type clip (Type const& value, Type const& lower, Type const& upper) throw() { return min (max (lower, value), upper); } 00055 00056 inline int wrap (int value, int lower, int upper) throw() 00057 { 00058 int range; 00059 00060 if (value >= upper) 00061 { 00062 range = upper - lower; 00063 value -= range; 00064 00065 if (value < upper) 00066 return value; 00067 } 00068 else if (value < lower) 00069 { 00070 range = upper - lower; 00071 value += range; 00072 00073 if (value >= lower) 00074 return value; 00075 } 00076 else 00077 { 00078 return value; 00079 } 00080 00081 if (upper == lower) 00082 return lower; 00083 else 00084 return value % range + lower; 00085 } 00086 00087 template<class Type> 00088 inline Type wrap (Type const& v, Type const& lower, Type const& upper) throw() 00089 { 00090 Type range; 00091 Type value = v; 00092 00093 if (value >= upper) 00094 { 00095 range = upper - lower; 00096 value -= range; 00097 00098 if (value < upper) 00099 return value; 00100 } 00101 else if (value < lower) 00102 { 00103 range = upper - lower; 00104 value += range; 00105 00106 if (value >= lower) 00107 return value; 00108 } 00109 else 00110 { 00111 return value; 00112 } 00113 00114 if (upper == lower) 00115 return lower; 00116 else 00117 return value - range * floor ((value - lower) / range); 00118 } 00119 00120 00121 00122 template<class Type> 00123 inline Type linlin (Type const& input, 00124 Type const& inLow, Type const& inHigh, 00125 Type const& outLow, Type const& outHigh) throw() 00126 { 00127 const Type inRange = inHigh - inLow; 00128 const Type outRange = outHigh - outLow; 00129 return (input - inLow) * outRange / inRange + outLow; 00130 } 00131 00132 template<class Type> 00133 inline Type linlin2 (Type const& input, 00134 Type const& inLow, Type const& inRange, 00135 Type const& outLow, Type const& outRange) throw() 00136 { 00137 return (input - inLow) * outRange / inRange + outLow; 00138 } 00139 00140 template<class Type> 00141 inline Type linsin (Type const& input, 00142 Type const& inLow, Type const& inHigh, 00143 Type const& outLow, Type const& outHigh) throw() 00144 { 00145 const Type inRange = inHigh - inLow; 00146 const Type outRange = outHigh - outLow; 00147 00148 const Type inPhase = (input - inLow) * Math<Type>::getPi() / inRange + Math<Type>::getPi(); 00149 const Type cosInPhase = cos (inPhase) * Math<Type>::get0_5() + Math<Type>::get0_5(); 00150 00151 return cosInPhase * outRange + outLow; 00152 } 00153 00154 template<class Type> 00155 inline Type linsin2 (Type const& input, 00156 Type const& inLow, Type const& inRange, 00157 Type const& outLow, Type const& outRange) throw() 00158 { 00159 const Type inPhase = (input - inLow) * Math<Type>::getPi() / inRange + Math<Type>::getPi(); 00160 const Type cosInPhase = cos (inPhase) * Math<Type>::get0_5() + Math<Type>::get0_5(); 00161 return cosInPhase * outRange + outLow; 00162 } 00163 00164 template<class Type> 00165 inline Type linexp (Type const& input, 00166 Type const& inLow, Type const& inHigh, 00167 Type const& outLow, Type const& outHigh) throw() 00168 { 00169 const Type outRatio = outHigh / outLow; 00170 const Type reciprocalInRange = Math<Type>::get1() / (inHigh - inLow); 00171 const Type inLowOverInRange = reciprocalInRange * inLow; 00172 return outLow * pow (outRatio, input * reciprocalInRange - inLowOverInRange); 00173 } 00174 00175 template<class Type> 00176 inline Type linexp2 (Type const& input, 00177 Type const& reciprocalInRange, Type const& inLowOverInRange, 00178 Type const& outLow, Type const& outRatio) throw() 00179 { 00180 return outLow * pow (outRatio, input * reciprocalInRange - inLowOverInRange); 00181 } 00182 00183 template<class Type> 00184 inline Type linwelch (Type const& input, 00185 Type const& inLow, Type const& inHigh, 00186 Type const& outLow, Type const& outHigh) throw() 00187 { 00188 const Type inRange = inHigh - inLow; 00189 const Type outRange = outHigh - outLow; 00190 const Type inPos = (input - inLow) / inRange; 00191 00192 if (outLow < outHigh) 00193 return outLow + outRange * sin (Math<Type>::getPi_2() * inPos); 00194 else 00195 return outHigh - outRange * sin (Math<Type>::getPi_2() - Math<Type>::getPi_2() * inPos); 00196 } 00197 00198 //template<class Type> 00199 //inline Type explin (Type const& input, 00200 // Type const& inLow, Type const& inHigh, 00201 // Type const& outLow, Type const& outHigh) 00202 //{ 00203 // if (input <= inLow) 00204 // return outLow; 00205 // 00206 // if (input >= inHigh) 00207 // return outHigh; 00208 // 00209 // return log (input / inLow) / log (inHigh / inLow) * (outHigh - outLow) + outLow; 00210 //} 00211 00212 template<class Type> 00213 inline Type explin (Type const& input, 00214 Type const& inLow, Type const& inHigh, 00215 Type const& outLow, Type const& outHigh) 00216 { 00217 const Type clipped = clip (input, inLow, inHigh); 00218 return log (clipped / inLow) / log (inHigh / inLow) * (outHigh - outLow) + outLow; 00219 } 00220 00221 //------------------------------------------------------------------------------ 00222 00223 template<class ValueType, class IndexType, signed Extension, signed Offset> class InterpBase; 00224 template<class ValueType, class IndexType> class InterpNone; 00225 template<class ValueType, class IndexType> class InterpLinear; 00226 template<class ValueType, class IndexType> class InterpLagrange3; 00227 00228 class Interp 00229 { 00230 public: 00231 enum TypeCode 00232 { 00233 None, 00234 Linear, 00235 Lagrange3, 00236 NumTypes 00237 }; 00238 }; 00239 00240 template<class ValueType, class IndexType, Interp::TypeCode TypeCode> 00241 class InterpSelect 00242 { 00243 }; 00244 00245 template<class ValueType, class IndexType> 00246 class InterpSelect<ValueType, IndexType, Interp::None> 00247 { 00248 public: 00249 typedef InterpNone<ValueType,IndexType> InterpType; 00250 }; 00251 00252 template<class ValueType, class IndexType> 00253 class InterpSelect<ValueType, IndexType, Interp::Linear> 00254 { 00255 public: 00256 typedef InterpLinear<ValueType,IndexType> InterpType; 00257 }; 00258 00259 template<class ValueType, class IndexType> 00260 class InterpSelect<ValueType, IndexType, Interp::Lagrange3> 00261 { 00262 public: 00263 typedef InterpLagrange3<ValueType,IndexType> InterpType; 00264 }; 00265 00266 00267 template<class ValueType, class IndexType, signed Extension, signed Offset> 00268 class InterpBase : public Interp 00269 { 00270 public: 00271 struct ExtensionBuffer 00272 { 00273 ValueType buffer[Extension]; 00274 }; 00275 00276 static inline int getExtension() throw() { return Extension; } 00277 static inline int getOffset() throw() { return Offset; } 00278 static inline const IndexType& getExtensionAsIndex() throw() { static const IndexType v (Extension); return v; } 00279 static inline const IndexType& getOffsetAsIndex() throw() { static const IndexType v (Offset); return v; } 00280 }; 00281 00282 template<class ValueType, class IndexType> 00283 class InterpNone : public InterpBase<ValueType,IndexType,0,0> 00284 { 00285 public: 00286 static inline ValueType lookup (const ValueType* table, IndexType const& index) throw() 00287 { 00288 return table[int (index)]; 00289 } 00290 }; 00291 00292 template<class ValueType, class IndexType> 00293 class InterpLinear : public InterpBase<ValueType,IndexType,1,0> 00294 { 00295 public: 00296 static inline ValueType interp (ValueType const& value0, ValueType const& value1, IndexType const& frac) throw() 00297 { 00298 return value0 + ValueType ((value1 - value0) * frac); 00299 } 00300 00301 static inline ValueType lookup (const ValueType* table, IndexType const& index) throw() 00302 { 00303 const int index0 = int (index); 00304 const int index1 = index0 + 1; 00305 const IndexType frac = index - IndexType (index0); 00306 return interp (table[index0], table[index1], frac); 00307 } 00308 }; 00309 00310 template<class ValueType> 00311 class InterpLinear<ValueType,int> : public InterpBase<ValueType,int,1,0> 00312 { 00313 public: 00314 typedef int IndexType; 00315 00316 static inline ValueType interp (ValueType const& value0, ValueType const& value1, IndexType const& frac) throw() 00317 { 00318 (void)value1; 00319 (void)frac; 00320 return value0; 00321 } 00322 00323 static inline ValueType lookup (const ValueType* table, IndexType const& index) throw() 00324 { 00325 return table[index]; 00326 } 00327 }; 00328 00329 template<class ValueType, class IndexType> 00330 class InterpLagrange3 : public InterpBase<ValueType,IndexType,4,1> 00331 { 00332 public: 00333 static inline ValueType interp (ValueType const& value_1, 00334 ValueType const& value0, 00335 ValueType const& value1, 00336 ValueType const& value2, 00337 IndexType const& frac) throw() 00338 { 00339 const ValueType half = Math<ValueType>::get0_5(); 00340 const ValueType third = Math<ValueType>::get1_3(); 00341 const ValueType sixth = Math<ValueType>::get1_6(); 00342 const ValueType c0 = value0; 00343 const ValueType c1 = value1 - third * value_1 - half * value0 - sixth * value2; 00344 const ValueType c2 = half * (value_1 + value1) - value0; 00345 const ValueType c3 = sixth * (value2 - value_1) + half * (value0 - value1); 00346 return ((c3 * frac + c2) * frac + c1) * frac + c0; 00347 } 00348 00349 static inline ValueType lookup (const ValueType* table, IndexType const& index) throw() 00350 { 00351 const int index0 = int (index); 00352 const int index1 = index0 + 1; 00353 const int index_1 = index0 - 1; 00354 const int index2 = index1 + 1; 00355 const IndexType frac = index - IndexType (index0); 00356 return interp (table[index_1], table[index0], table[index1], table[index2], frac); 00357 } 00358 }; 00359 00360 template<class ValueType> 00361 class InterpLagrange3<ValueType,int> : public InterpBase<ValueType,int,4,1> 00362 { 00363 public: 00364 typedef int IndexType; 00365 00366 static inline ValueType interp (ValueType const& value_1, 00367 ValueType const& value0, 00368 ValueType const& value1, 00369 ValueType const& value2, 00370 IndexType const& frac) throw() 00371 { 00372 (void)value_1; 00373 (void)value1; 00374 (void)value2; 00375 (void)frac; 00376 return value0; 00377 } 00378 00379 static inline ValueType lookup (const ValueType* table, IndexType const& index) throw() 00380 { 00381 return table[index]; 00382 } 00383 }; 00384 00385 00386 template<class Type, signed NumBits> 00387 class BitsBase 00388 { 00389 public: 00390 }; 00391 00392 00393 #define PLONK_BITSBASE_DECLARE(TypeCode,TypeSize)\ 00394 template<class Type>\ 00395 class BitsBase<Type,TypeSize>\ 00396 {\ 00397 public:\ 00398 typedef PlankU##TypeCode InternalType;\ 00399 \ 00400 static inline Type countOnes (Type const& value) throw() { return (Type)pl_CountOnesU##TypeCode ((InternalType)value); }\ 00401 static inline Type countLeadingZeros (Type const& value) throw() { return (Type)pl_CountLeadingZerosU##TypeCode ((InternalType)value); }\ 00402 static inline Type countTrailingZeroes (Type const& value) throw() { return (Type)pl_CountTrailingZerosU##TypeCode ((InternalType)value); }\ 00403 static inline Type countLeadingOnes (Type const& value) throw() { return (Type)pl_CountLeadingOnesU##TypeCode ((InternalType)value); }\ 00404 static inline Type countTrailingOnes (Type const& value) throw() { return (Type)pl_CountTrailingOnesU##TypeCode ((InternalType)value); }\ 00405 static inline Type numBitsRequired (Type const& value) throw() { return (Type)pl_NumBitsRequiredU##TypeCode ((InternalType)value); }\ 00406 static inline Type nextPowerOf2 (Type const& value) throw() { return (Type)pl_NextPowerOf2U##TypeCode ((InternalType)value); }\ 00407 static inline bool isPowerOf2 (Type const& value) throw() { return (Type)pl_IsPowerOf2U##TypeCode ((InternalType)value); }\ 00408 } 00409 00410 PLONK_BITSBASE_DECLARE(C,1); 00411 PLONK_BITSBASE_DECLARE(S,2); 00412 PLONK_BITSBASE_DECLARE(I,4); 00413 PLONK_BITSBASE_DECLARE(LL,8); 00414 00415 00417 class Bits 00418 { 00419 public: 00420 template<class Type> static inline Type countOnes (Type const& value) throw() { return BitsBase<Type,sizeof(Type)>::countOnes (value); } 00421 template<class Type> static inline Type countLeadingZeros (Type const& value) throw() { return BitsBase<Type,sizeof(Type)>::countLeadingZeros (value); } 00422 template<class Type> static inline Type countTrailingZeroes (Type const& value) throw() { return BitsBase<Type,sizeof(Type)>::countTrailingZeroes (value); } 00423 template<class Type> static inline Type countLeadingOnes (Type const& value) throw() { return BitsBase<Type,sizeof(Type)>::countLeadingOnes (value); } 00424 template<class Type> static inline Type countTrailingOnes (Type const& value) throw() { return BitsBase<Type,sizeof(Type)>::countTrailingOnes (value); } 00425 template<class Type> static inline Type numBitsRequired (Type const& value) throw() { return BitsBase<Type,sizeof(Type)>::numBitsRequired (value); } 00426 template<class Type> static inline Type nextPowerOf2 (Type const& value) throw() { return BitsBase<Type,sizeof(Type)>::nextPowerOf2 (value); } 00427 template<class Type> static inline bool isPowerOf2 (Type const& value) throw() { return BitsBase<Type,sizeof(Type)>::isPowerOf2 (value); } 00428 }; 00429 00430 00432 class NumericalConverter 00433 { 00434 public: 00435 template<class InType, class OutType> 00436 static inline void roundCopy (const InType inValue, OutType& outValue) throw() { outValue = OutType (inValue); } 00437 00438 static inline void roundCopy (const double inValue, char& outValue) throw() { outValue = char (inValue + 0.5); } 00439 static inline void roundCopy (const double inValue, short& outValue) throw() { outValue = short (inValue + 0.5); } 00440 static inline void roundCopy (const double inValue, int& outValue) throw() { outValue = int (inValue + 0.5); } 00441 static inline void roundCopy (const double inValue, Int24& outValue) throw() { outValue = Int24 (inValue + 0.5); } 00442 static inline void roundCopy (const double inValue, LongLong& outValue) throw() { outValue = LongLong (inValue + 0.5); } 00443 00444 static inline void roundCopy (const float inValue, char& outValue) throw() { outValue = char (inValue + 0.5f); } 00445 static inline void roundCopy (const float inValue, short& outValue) throw() { outValue = short (inValue + 0.5f); } 00446 static inline void roundCopy (const float inValue, int& outValue) throw() { outValue = int (inValue + 0.5f); } 00447 static inline void roundCopy (const float inValue, Int24& outValue) throw() { outValue = Int24 (inValue + 0.5f); } 00448 static inline void roundCopy (const float inValue, LongLong& outValue) throw() { outValue = LongLong (inValue + 0.5f); } 00449 }; 00450 00451 00452 00454 00455 #endif // PLONK_INLINEMISCOPS_H