Main Page   Modules   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

/root/src/subsynth/syn/Util/Math.h

Go to the documentation of this file.
00001 
00002 /****************** <SYN heading BEGIN do not edit this line> *****************
00003  *
00004  * subsynth - modular audio synthesizer
00005  * subsynth is (C) Copyright 2001-2002 by Kevin Meinert
00006  *
00007  * Original Author: Kevin Meinert
00008  *
00009  * This library is free software; you can redistribute it and/or
00010  * modify it under the terms of the GNU Library General Public
00011  * License as published by the Free Software Foundation; either
00012  * version 2 of the License, or (at your option) any later version.
00013  *
00014  * This library is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017  * Library General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU Library General Public
00020  * License along with this library; if not, write to the
00021  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00022  * Boston, MA 02111-1307, USA.
00023  *
00024  * -----------------------------------------------------------------
00025  * File:          $RCSfile: Math.h,v $
00026  * Date modified: $Date: 2002/04/14 19:55:49 $
00027  * Version:       $Revision: 1.9 $
00028  * -----------------------------------------------------------------
00029  *
00030  ****************** <SYN heading END do not edit this line> ******************/
00031 #ifndef SYNMATH
00032 #define SYNMATH
00033 #include <assert.h>
00034 #include <math.h>
00035 namespace syn
00036 {
00037    namespace Math
00038    {
00040       struct ADDEQUAL { inline static void oper( float& i, const float o ) { i += o; } };
00041 
00043       struct EQUAL { inline static void oper( float& i, const float o ) { i = o; } };
00044 
00046       struct MULTEQUAL { inline static void oper( float& i, const float o ) { i *= o; } };
00047 
00048       const float PI = 3.14159265358979323846f; //3.14159265358979323846264338327950288419716939937510;
00049       const float PI_OVER_2 = 1.57079632679489661923f;
00050       const float PI_OVER_4 = 0.78539816339744830962f;
00051 
00052       //----------------------------------------------------------------------------
00054       template <class T>
00055       inline T Min( const T& x, const T& y )
00056       {
00057          return ( x > y ) ? y : x;
00058       }
00060       template <class T>
00061       inline T Min( const T& x, const T& y, const T& z )
00062       {
00063          return Math::Min( Math::Min( x, y ), z );
00064       }
00066       template <class T>
00067       inline T Min( const T& w, const T& x, const T& y, const T& z )
00068       {
00069          return Math::Min( Math::Min( w, x ), Math::Min( y, z ) );
00070       }
00071 
00073       template <class T>
00074       inline T Max( const T& x, const T& y )
00075       {
00076          return ( x > y ) ? x : y;
00077       }
00079       template <class T>
00080       inline T Max( const T& x, const T& y, const T& z )
00081       {
00082          return Math::Max( Math::Max( x, y ), z );
00083       }
00085       template <class T>
00086       inline T Max( const T& w, const T& x, const T& y, const T& z )
00087       {
00088          return Math::Max( Math::Max( w, x ), Math::Max( y, z ) );
00089       }
00093       template <class T, typename U>
00094       inline void lerp( T& result, const U& lerp, const T& a, const T& b )
00095       {
00096           T size = b - a;
00097           result = ((U)a) + (((U)size) * lerp);
00098       }
00099       //----------------------------------------------------------------------------
00101       template <class T>
00102       inline T trunc( T val )
00103       {
00104          return T( (val < ((T)0)) ? Math::ceil( val ) : Math::floor( val ) );
00105       }
00107       template <class T>
00108       inline T round( T p )
00109       {
00110          return T( Math::floor( p + (T)0.5 ) );
00111       }
00112       /*
00113       inline float unitRandom()
00114       {
00115           //return float(random())/float(RAND_MAX);
00116          float ret_val;
00117          ret_val = drand48();
00118          assert( (ret_val >= 0.0f) && (ret_val <= 1.0f) );
00119          return drand48();
00120       }
00121       */
00122 
00126       /*
00127       inline float rangeRandom( float x1, float x2 )
00128       {
00129          float r = Math::unitRandom();
00130          float size = x2 - x1;
00131          return float( r * size + x1 );
00132       }
00133       */
00134       //----------------------------------------------------------------------------
00135       // don't allow non-float types, because their ret val wont be correct
00136       // i.e. with int, the int retval will be rounded up or down.
00137       //      we'd need a float retval to do it right, but we can't specialize by ret
00138       template <typename T>
00139       inline T aCos( T fValue );
00140       inline float aCos( float fValue )
00141       {
00142           if ( -1.0f < fValue )
00143           {
00144               if ( fValue < 1.0f )
00145                   return float( ::acosf( fValue ) );
00146               else
00147                   return 0.0f;
00148           }
00149           else
00150           {
00151               return (float)Math::PI;
00152           }
00153       }
00154       inline double aCos( double fValue )
00155       {
00156           if ( -1.0 < fValue )
00157           {
00158               if ( fValue < 1.0 )
00159                   return double( ::acos( fValue ) );
00160               else
00161                   return 0.0;
00162           }
00163           else
00164           {
00165               return (double)PI;
00166           }
00167       }
00168       //----------------------------------------------------------------------------
00169       template <typename T>
00170       inline T aSin( T fValue );
00171       inline float aSin( float fValue )
00172       {
00173           if ( -1.0f < fValue )
00174           {
00175               if ( fValue < 1.0f )
00176                   return float( ::asinf( fValue ) );
00177               else
00178                   return (float)-PI_OVER_2;
00179           }
00180           else
00181           {
00182               return (float)PI_OVER_2;
00183           }
00184       }
00185       inline double aSin( double fValue )
00186       {
00187           if ( -1.0 < fValue )
00188           {
00189               if ( fValue < 1.0 )
00190                   return double( ::asin( fValue ) );
00191               else
00192                   return (double)-PI_OVER_2;
00193           }
00194           else
00195           {
00196               return (double)PI_OVER_2;
00197           }
00198       }
00199       template <typename T>
00200       inline T aTan( T fValue );
00201       inline float aTan( float fValue )
00202       {
00203           return float( ::atanf( fValue ) );
00204       }
00205       inline double aTan( double fValue )
00206       {
00207           return ::atan( fValue );
00208       }
00209       //----------------------------------------------------------------------------
00210       template <typename T>
00211       inline T atan2( T fY, T fX );
00212       inline float aTan2( float fY, float fX )
00213       {
00214           return float( ::atan2f( fY, fX ) );
00215       }
00216       inline double aTan2( double fY, double fX )
00217       {
00218           return double( ::atan2( fY, fX ) );
00219       }
00220       //----------------------------------------------------------------------------
00221       template <typename T>
00222       inline T cos( T fValue );
00223       inline float cos( float fValue )
00224       {
00225           return float( ::cosf( fValue ) );
00226       }
00227       inline double cos( double fValue )
00228       {
00229           return double( ::cos( fValue ) );
00230       }
00231       //----------------------------------------------------------------------------
00232       template <typename T>
00233       inline T exp( T fValue );
00234       inline float exp( float fValue )
00235       {
00236           return float( ::expf( fValue ) );
00237       }
00238       inline double exp( double fValue )
00239       {
00240           return double( ::exp( fValue ) );
00241       }
00242       //----------------------------------------------------------------------------
00243       template <typename T>
00244       inline T log( T fValue );
00245       inline double log( double fValue )
00246       {
00247           return double( ::log( fValue ) );
00248       }
00249       inline float log( float fValue )
00250       {
00251           return float( ::logf( fValue ) );
00252       }
00253       //----------------------------------------------------------------------------
00254       inline double pow( double fBase, double fExponent)
00255       {
00256           return double( ::pow( fBase, fExponent ) );
00257       }
00258       inline float pow( float fBase, float fExponent)
00259       {
00260           return float( ::powf( fBase, fExponent ) );
00261       }
00262       template <typename T>
00263       inline T sin( T fValue );
00264       inline double sin( double fValue )
00265       {
00266           return double( ::sin( fValue ) );
00267       }
00268       inline float sin( float fValue )
00269       {
00270           return float( ::sinf( fValue ) );
00271       }
00272       template <typename T>
00273       inline T tan( T fValue );
00274       inline double tan( double fValue )
00275       {
00276           return double( ::tan( fValue ) );
00277       }
00278       inline float tan( float fValue )
00279       {
00280           return float( ::tanf( fValue ) );
00281       }
00282       template <typename T>
00283       inline T sqr( T fValue )
00284       {
00285           return T( fValue * fValue );
00286       }
00287       template <typename T>
00288       inline T sqrt( T fValue )
00289       {
00290           return T( ::sqrtf( ((float)fValue) ) );
00291       }
00292       inline double sqrt( double fValue )
00293       {
00294           return double( ::sqrt( fValue ) );
00295       }
00296       
00297       template <typename T>
00298       inline T abs( T iValue )
00299       {
00300          return T( iValue >= ((T)0) ? iValue : -iValue );
00301       }
00302 
00308       inline double fast_exp2( const double val ) 
00309       {
00310          // is the machine little endian?
00311          union
00312          {
00313             short   val;
00314             char    ch[sizeof( short )];
00315          } un;
00316          un.val = 256; // 0x10;
00317          // if un.ch[1] == 1 then we're little
00318 
00319          // return 2 to the power of val (exp base2)
00320          int    e;
00321          double ret;
00322 
00323          if (val >= 0)
00324          {
00325             e = int (val);
00326             ret = val - (e - 1);
00327 
00328             if (un.ch[1] == 1)
00329                ((*(1 + (int *) &ret)) &= ~(2047 << 20)) += (e + 1023) << 20;
00330             else
00331                ((*((int *) &ret)) &= ~(2047 << 20)) += (e + 1023) << 20;
00332          }
00333          else
00334          {
00335             e = int (val + 1023);
00336             ret = val - (e - 1024);
00337 
00338             if (un.ch[1] == 1)
00339                ((*(1 + (int *) &ret)) &= ~(2047 << 20)) += e << 20;
00340             else
00341                ((*((int *) &ret)) &= ~(2047 << 20)) += e << 20;
00342          }
00343 
00344          return ret;
00345       }
00346 
00354       inline float fast_log2( const float f )
00355       {
00356         assert( f > 0. );
00357         //assert( sizeof(f) == sizeof(int) );
00358         //assert( sizeof(f) == 4 );
00359         int i = (*(int *)&f);
00360         return (((i&0x7f800000)>>23)-0x7f)+(i&0x007fffff)/(float)0x800000;
00361       }
00362       
00365       template <typename T>
00366       inline T log2( const T f )
00367       {
00368         static const double conversion = ::log10( 2.0f );
00369         return (T)log10( (double)f ) / conversion;
00370       }
00371 
00372       //First the easy way which is usually good enough:
00373       //just use x squared or x cubed.
00374 
00375       //Second the more complicated way:
00376       /*
00377 
00378       These two functions reproduce a traditional professional
00379       mixer fader taper.
00380 
00381       VolumeToDB converts volume (0 to 100%) starting from the
00382       bottom of the fader into decibels. 
00383       DBtoVolume is the inverse.
00384 
00385       The taper is as follows from the top:
00386       The top of the fader is +10 dB
00387       100 to 52 : -5 dB per 12
00388       52 to 16 : -10 dB per 12
00389       16 to 4 : -20 dB per 12
00390       4 to 0 : fade to zero. (in these functions I go to -200dB
00391       which is effectively zero for up to 32 bit audio.)
00392 
00393       */
00394 
00395       inline float volumeToDB( float vol )
00396       {
00397               float db;
00398 
00399               vol = 100.0f - vol;
00400 
00401               if (vol <= 0.0f) {
00402                       db = 10.0f;
00403               } else if (vol < 48.0f) {
00404                       db = 10.0f - 5.0f/12.0f * vol;
00405               } else if (vol < 84.0f) {
00406                       db = -10.0f - 10.0f/12.0f * (vol - 48.0f);
00407               } else if (vol < 96.0f) {
00408                       db = -40.0f - 20.0f/12.0f * (vol - 84.0f);
00409               } else if (vol < 100.0f) {
00410                       db = -60.0f - 35.0f * (vol - 96.0f);
00411               } else db = -200.0f;
00412               return db;
00413       }
00414 
00415       inline float DBtoVolume( float db )
00416       {
00417               float vol;
00418               if (db >= 10.0f) {
00419                       vol = 0.0f;
00420               } else if (db > -10.0f) {
00421                       vol = -12.0f/5.0f * (db - 10.0f);
00422               } else if (db > -40.0f) {
00423                       vol = 48.0f - 12.0f/10.0f * (db + 10.0f);
00424               } else if (db > -60.0f) {
00425                       vol = 84.0f - 12.0f/20.0f * (db + 40.0f);
00426               } else if (db > -200.0f) {
00427                       vol = 96.0f - 1.0f/35.0f * (db + 60.0f);
00428               } else vol = 100.0f;
00429 
00430               vol = 100.0f - vol;
00431 
00432               return vol;
00433       }
00434    } // end of Math namespace
00435 } // end of syn namespace
00436 
00437 #endif

Generated at Mon Apr 15 09:26:08 2002 for subsynth by doxygen1.2.8.1 written by Dimitri van Heesch, © 1997-2001