/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A.-----------------------------------------------------------------------------*///-----------------------------------------------------------------------------// name: util_math.c// desc: ...//// author: Ge Wang (gewang@cs.princeton.edu)// Perry R. Cook (prc@cs.princeton.edu)// Philip Davidson (philipd@alumni.princeton.edu)// date: Spring 2004//-----------------------------------------------------------------------------#include "util_math.h"#include <math.h>#include <random>// windows / visual c++#ifdef __PLATFORM_WIN32__#ifdef __CK_MATH_DEFINE_ROUND_TRUNC__//-----------------------------------------------------------------------------// name: round()// desc: ...//-----------------------------------------------------------------------------double round( double a ){ if( a >= 0 ) return (double)(t_CKINT)( a + .5 ); else return (double)(t_CKINT)( a - .5 );}//-----------------------------------------------------------------------------// name: trunc()// desc: ...//-----------------------------------------------------------------------------double trunc( double a ){ return (double)(long)a;}#endif // #ifdef __CK_MATH_DEFINE_ROUND_TRUNC#endif//-----------------------------------------------------------------------------#ifndef __OLDSCHOOL_RANDOM__ // not using old school, pre-c++11 compatibility//-----------------------------------------------------------------------------// name: ck_random() and ck_srandom()// desc: chuck wrappers for random number generators// 1.5.0.1 (ge) using mt19937 (requires c++11)//-----------------------------------------------------------------------------// mersenne twister RNG, based on the Mersenne prime (2^19937-1)static std::mt19937 g_ck_global_rng;// ck_random() returns a signed int no greater than CK_RANDOM_MAX// to maintain parity between 64-bit and 32-bit systems, CK_RANDOM_MAX is set// to 0x7fffffff (or 2,147,483,647--the largest 32-bit signed number) rather// than mt19937's actual max of 0xffffffff (or 4,294,967,295, 2^32-1); this// is ensured using modulo; the slight skewing of the resulting RNG distribution// is considered acceptablet_CKINT ck_random() { return g_ck_global_rng() % CK_RANDOM_MAX; }// seed the random number generatorvoid ck_srandom( unsigned s ) { g_ck_global_rng.seed(s); }//-----------------------------------------------------------------------------#else // using old school random (pre-c++11)//-----------------------------------------------------------------------------// name: ck_random() and ck_srandom()// desc: chuck wrappers for random number generators | 1.4.2.0 (ge)//-----------------------------------------------------------------------------#ifndef __PLATFORM_WIN32__ t_CKINT ck_random() { return random(); } void ck_srandom( unsigned s ) { srandom( s ); }#else // __WINDOWS_DS__ t_CKINT ck_random() { return rand(); } void ck_srandom( unsigned s ) { srand( s ); }#endif//-----------------------------------------------------------------------------#endif // __OLDSCHOOL_RANDOM__//-----------------------------------------------------------------------------// name: ck_remainder()// desc: ...//-----------------------------------------------------------------------------double ck_remainder( double a, double b ){#ifdef __PLATFORM_WIN32__ t_CKINT div = a/b; return a - b*div;#else return remainder( a, b );#endif}// the following 6 functions are lifted from PD source// specifically x_acoustics.c// http://puredata.info/downloads#define LOGTWO 0.69314718055994528623#define LOGTEN 2.302585092994//-----------------------------------------------------------------------------// name: mtof()// desc: midi to freq//-----------------------------------------------------------------------------double mtof( double f ){ if( f <= -1500 ) return (0); else if( f > 1499 ) return (mtof(1499)); // else return (8.17579891564 * exp(.0577622650 * f)); // TODO: optimize else return ( pow(2,(f-69)/12.0) * 440.0 );}//-----------------------------------------------------------------------------// name: ftom()// desc: freq to midi//-----------------------------------------------------------------------------double ftom( double f ){ // return (f > 0 ? 17.3123405046 * log(.12231220585 * f) : -1500); // TODO: optimize return (f > 0 ? (log(f/440.0) / LOGTWO) * 12.0 + 69 : -1500);}//-----------------------------------------------------------------------------// name: powtodb()// desc: ...//-----------------------------------------------------------------------------double powtodb( double f ){ if( f <= 0 ) return (0); else { double val = 100 + 10./LOGTEN * log(f); return (val < 0 ? 0 : val); }}//-----------------------------------------------------------------------------// name: rmstodb()// desc: ...//-----------------------------------------------------------------------------double rmstodb( double f ){ if( f <= 0 ) return (0); else { double val = 100 + 20./LOGTEN * log(f); return (val < 0 ? 0 : val); }}//-----------------------------------------------------------------------------// name: dbtopow()// desc: ...//-----------------------------------------------------------------------------double dbtopow( double f ){ if( f <= 0 ) return (0); else { if( f > 870 ) f = 870; return (exp((LOGTEN * 0.1) * (f-100.))); }}//-----------------------------------------------------------------------------// name: dbtorms()// desc: ...//-----------------------------------------------------------------------------double dbtorms( double f ){ if( f <= 0 ) return (0); else { if( f > 485 ) f = 485; return (exp((LOGTEN * 0.05) * (f-100.))); }}//-----------------------------------------------------------------------------// name: nextpow2()// desc: ...//-----------------------------------------------------------------------------unsigned long nextpow2( unsigned long n ){ unsigned long nn = n; for( ; n &= n-1; nn = n ); return nn * 2;}//-----------------------------------------------------------------------------// name: ensurepow2()// desc: ...//-----------------------------------------------------------------------------unsigned long ensurepow2( unsigned long n ){ return nextpow2( n-1 );}
/*----------------------------------------------------------------------------
ChucK Concurrent, On-the-fly Audio Programming Language
Compiler and Virtual Machine
Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved.
http://chuck.cs.princeton.edu/
http://soundlab.cs.princeton.edu/
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
U.S.A.
-----------------------------------------------------------------------------*/
//-----------------------------------------------------------------------------
// name: util_math.c
// desc: ...
//
// author: Ge Wang (gewang@cs.princeton.edu)
// Perry R. Cook (prc@cs.princeton.edu)
// Philip Davidson (philipd@alumni.princeton.edu)
// date: Spring 2004
//-----------------------------------------------------------------------------
#include "util_math.h"
#include <math.h>
#include <random>
// windows / visual c++
#ifdef __PLATFORM_WIN32__
#ifdef __CK_MATH_DEFINE_ROUND_TRUNC__
//-----------------------------------------------------------------------------
// name: round()
// desc: ...
//-----------------------------------------------------------------------------
double round( double a )
{
if( a >= 0 ) return (double)(t_CKINT)( a + .5 );
else return (double)(t_CKINT)( a - .5 );
}
//-----------------------------------------------------------------------------
// name: trunc()
// desc: ...
//-----------------------------------------------------------------------------
double trunc( double a )
{
return (double)(long)a;
}
#endif // #ifdef __CK_MATH_DEFINE_ROUND_TRUNC
#endif
//-----------------------------------------------------------------------------
#ifndef __OLDSCHOOL_RANDOM__ // not using old school, pre-c++11 compatibility
//-----------------------------------------------------------------------------
// name: ck_random() and ck_srandom()
// desc: chuck wrappers for random number generators
// 1.5.0.1 (ge) using mt19937 (requires c++11)
//-----------------------------------------------------------------------------
// mersenne twister RNG, based on the Mersenne prime (2^19937-1)
static std::mt19937 g_ck_global_rng;
// ck_random() returns a signed int no greater than CK_RANDOM_MAX
// to maintain parity between 64-bit and 32-bit systems, CK_RANDOM_MAX is set
// to 0x7fffffff (or 2,147,483,647--the largest 32-bit signed number) rather
// than mt19937's actual max of 0xffffffff (or 4,294,967,295, 2^32-1); this
// is ensured using modulo; the slight skewing of the resulting RNG distribution
// is considered acceptable
t_CKINT ck_random() { return g_ck_global_rng() % CK_RANDOM_MAX; }
// seed the random number generator
void ck_srandom( unsigned s ) { g_ck_global_rng.seed(s); }
//-----------------------------------------------------------------------------
#else // using old school random (pre-c++11)
//-----------------------------------------------------------------------------
// name: ck_random() and ck_srandom()
// desc: chuck wrappers for random number generators | 1.4.2.0 (ge)
//-----------------------------------------------------------------------------
#ifndef __PLATFORM_WIN32__
t_CKINT ck_random() { return random(); }
void ck_srandom( unsigned s ) { srandom( s ); }
#else // __WINDOWS_DS__
t_CKINT ck_random() { return rand(); }
void ck_srandom( unsigned s ) { srand( s ); }
#endif
//-----------------------------------------------------------------------------
#endif // __OLDSCHOOL_RANDOM__
//-----------------------------------------------------------------------------
// name: ck_remainder()
// desc: ...
//-----------------------------------------------------------------------------
double ck_remainder( double a, double b )
{
#ifdef __PLATFORM_WIN32__
t_CKINT div = a/b;
return a - b*div;
#else
return remainder( a, b );
#endif
}
// the following 6 functions are lifted from PD source
// specifically x_acoustics.c
// http://puredata.info/downloads
#define LOGTWO 0.69314718055994528623
#define LOGTEN 2.302585092994
//-----------------------------------------------------------------------------
// name: mtof()
// desc: midi to freq
//-----------------------------------------------------------------------------
double mtof( double f )
{
if( f <= -1500 ) return (0);
else if( f > 1499 ) return (mtof(1499));
// else return (8.17579891564 * exp(.0577622650 * f));
// TODO: optimize
else return ( pow(2,(f-69)/12.0) * 440.0 );
}
//-----------------------------------------------------------------------------
// name: ftom()
// desc: freq to midi
//-----------------------------------------------------------------------------
double ftom( double f )
{
// return (f > 0 ? 17.3123405046 * log(.12231220585 * f) : -1500);
// TODO: optimize
return (f > 0 ? (log(f/440.0) / LOGTWO) * 12.0 + 69 : -1500);
}
//-----------------------------------------------------------------------------
// name: powtodb()
// desc: ...
//-----------------------------------------------------------------------------
double powtodb( double f )
{
if( f <= 0 ) return (0);
else
{
double val = 100 + 10./LOGTEN * log(f);
return (val < 0 ? 0 : val);
}
}
//-----------------------------------------------------------------------------
// name: rmstodb()
// desc: ...
//-----------------------------------------------------------------------------
double rmstodb( double f )
{
if( f <= 0 ) return (0);
else
{
double val = 100 + 20./LOGTEN * log(f);
return (val < 0 ? 0 : val);
}
}
//-----------------------------------------------------------------------------
// name: dbtopow()
// desc: ...
//-----------------------------------------------------------------------------
double dbtopow( double f )
{
if( f <= 0 )
return (0);
else
{
if( f > 870 ) f = 870;
return (exp((LOGTEN * 0.1) * (f-100.)));
}
}
//-----------------------------------------------------------------------------
// name: dbtorms()
// desc: ...
//-----------------------------------------------------------------------------
double dbtorms( double f )
{
if( f <= 0 )
return (0);
else
{
if( f > 485 ) f = 485;
return (exp((LOGTEN * 0.05) * (f-100.)));
}
}
//-----------------------------------------------------------------------------
// name: nextpow2()
// desc: ...
//-----------------------------------------------------------------------------
unsigned long nextpow2( unsigned long n )
{
unsigned long nn = n;
for( ; n &= n-1; nn = n );
return nn * 2;
}
//-----------------------------------------------------------------------------
// name: ensurepow2()
// desc: ...
//-----------------------------------------------------------------------------
unsigned long ensurepow2( unsigned long n )
{
return nextpow2( n-1 );
}