![]() |
Mixxx
|
00001 /*************************************************************************** 00002 mathstuff.cpp - description 00003 ------------------- 00004 copyright : (C) 2002 by Tue and Ken Haste Andersen 00005 email : 00006 ***************************************************************************/ 00007 00008 /*************************************************************************** 00009 * * 00010 * This program is free software; you can redistribute it and/or modify * 00011 * it under the terms of the GNU General Public License as published by * 00012 * the Free Software Foundation; either version 2 of the License, or * 00013 * (at your option) any later version. * 00014 * * 00015 ***************************************************************************/ 00016 00017 #include "mathstuff.h" 00018 00019 // Defines modified Bessel function I_0(x) for any real x. 00020 // From Numerical Recipes in C, sec.ed., p.237. 00021 CSAMPLE besseli(CSAMPLE x) 00022 { 00023 CSAMPLE ax, ans; 00024 CSAMPLE y; 00025 00026 if ((ax=fabs(x)) < 3.75) 00027 { 00028 y = x/3.75f; 00029 y *= y; 00030 ans = 1.0f+y*(3.5156229f+y*(3.0899424f+y*(1.2067492f 00031 +y*(0.2659732f+y*(0.360768e-1+y*0.45813e-2))))); 00032 } 00033 else 00034 { 00035 y = 3.75f/ax; 00036 ans=(exp(ax)/sqrt(ax))*(0.39894228f+y*(0.1328592e-1 00037 +y*(0.225319e-2+y*(-0.157565e-2+y*(0.916281e-2 00038 +y*(-0.2057706e-1+y*(0.2635537e-1+y*(-0.1647633e-1 00039 +y*0.392377e-2)))))))); 00040 } 00041 return ans; 00042 } 00043 00044 // Returns the sing of the value X. 00045 int sign(CSAMPLE x) 00046 { 00047 if (fabs(x) == x) 00048 return 1; 00049 else 00050 return -1; 00051 } 00052 00053 // Returns the inverse of the matrix [m[0] m[1]; m[1] m[2]] (call by name). If the 00054 // operations is not possible -1 is returned, otherwise 0. 00055 int invmatrix(CSAMPLE * m) 00056 { 00057 CSAMPLE k = m[0]*m[2]-m[1]*m[1]; 00058 CSAMPLE tmp; 00059 00060 if (k == 0) 00061 return -1; 00062 else 00063 { 00064 tmp = m[2]/k; 00065 m[2] = m[0]/k; 00066 m[1] = -m[1]/k; 00067 m[0] = tmp; 00068 return 0; 00069 } 00070 } 00071 00072 // Finds coefficients of an n order polynominal. From NR p.121. 00073 void polcoe(CSAMPLE x[], CSAMPLE y[], int n, CSAMPLE cof[]) 00074 { 00075 int k,j,i; 00076 CSAMPLE phi, ff, b, * s; 00077 s = new CSAMPLE[n+1]; 00078 for (i=0; i<n; i++) 00079 s[i]=cof[i]=.0; 00080 s[n]= -x[0]; 00081 for (i=1; i<=n; ++i) 00082 { 00083 for (j=n-i; j<=n-1; j++) 00084 s[j] -= x[i]*s[j+1]; 00085 s[n] -= x[i]; 00086 } 00087 for (j=0; j<=n; ++j) 00088 { 00089 phi=n+1.f; 00090 for (k=n; k>=0; k--) 00091 phi=k*s[k]+x[j]*phi; 00092 ff=y[j]/phi; 00093 b=1.0; 00094 for (k=n; k>=0; k--) 00095 { 00096 cof[k] += b*ff; 00097 b = s[k]+x[j]*b; 00098 } 00099 } 00100 delete [] s; 00101 } 00102 00103 // Calculates the value x mod 2pi. Returns a value between -pi and pi. 00104 CSAMPLE mod2pi(CSAMPLE x) 00105 { 00106 // x += pi; 00107 x = x-floor(x/two_pi)*two_pi; 00108 CSAMPLE r = x; 00109 return(r); 00110 } 00111 00112 #ifdef __WINDOWS__ 00113 // Rounds a CSAMPLE to nearest integer, and returns as int 00114 int round(CSAMPLE x) 00115 { 00116 double y = x; 00117 double z; 00118 double rest = modf(y,&z); 00119 int reti = (int)z; 00120 if (rest>=.5) 00121 reti++; 00122 else if (rest<-.5) 00123 reti--; 00124 00125 return(reti); 00126 } 00127 #endif 00128 00129 // Fast arctan2 from http://www.dspguru.com/comp.dsp/tricks/alg/fxdatan2.htm 00130 CSAMPLE arctan2(CSAMPLE y, CSAMPLE x) 00131 { 00132 CSAMPLE r, angle; 00133 00134 const CSAMPLE coeff_1 = pi/4; 00135 const CSAMPLE coeff_2 = 3*coeff_1; 00136 00137 CSAMPLE abs_y = fabs(y)+1e-10f; // kludge to prevent 0/0 condition 00138 00139 if (x>=0) 00140 { 00141 r = (x - abs_y) / (x + abs_y); 00142 angle = coeff_1 - coeff_1 * r; 00143 } 00144 else 00145 { 00146 r = (x + abs_y) / (abs_y - x); 00147 angle = coeff_2 - coeff_1 * r; 00148 } 00149 00150 if (y < 0) 00151 return(-angle); // negate if in quad III or IV 00152 else 00153 return(angle); 00154 } 00155 00156 CSAMPLE wndKaiser(CSAMPLE * wnd, int size, CSAMPLE beta) 00157 { 00158 int m = size-1; 00159 CSAMPLE AFactor = 0.; 00160 00161 CSAMPLE t = besseli(beta); 00162 for (int k=0; k<size; ++k) 00163 { 00164 wnd[k] = besseli(2.*beta/m*sqrt((float)(k*(m-k))))/t; 00165 AFactor += wnd[k]; 00166 } 00167 return (2.f/AFactor); 00168 } 00169 00170 CSAMPLE wndKaiserSample(int size, CSAMPLE beta, int i) 00171 { 00172 int m = size-1; 00173 CSAMPLE t = besseli(beta); 00174 return besseli(2.*beta/m*sqrt((float)(i*(m-i))))/t; 00175 } 00176 00177 /* 00178 * // Calculate the derivative of the window in kaiser_wnd. 00179 // The result goes in kaiser_dwnd. 00180 void wndDwnd(CSAMPLE *wnd, CSAMPLE *dwnd, int size) 00181 { 00182 dwnd[0] = (wnd[1]-wnd[0])*SRATE; 00183 for (int k=0; k<size-1; k++) 00184 dwnd[k+1] = (wnd[k+1]-wnd[k])*SRATE; 00185 } 00186 */ 00187 00188 double qip(CSAMPLE x, unsigned int n) 00189 { 00190 double h = 1.; 00191 while (n) 00192 { 00193 if (n&1) h*=x; 00194 x*=x; 00195 n >>= 1; 00196 } 00197 return h; 00198 } 00199 00200 bool even(long n) 00201 { 00202 // if ((n/2) != (n+1)/2) 00203 if (n%2 != 0) 00204 return false; 00205 else 00206 return true; 00207 } 00208 00209 float sigmoid_zero(double t, double max_t) 00210 { 00211 //generates a sigmoid function but goes from 0 - t instead of 00212 //-t to +t. 00213 //furthermore we map t to a range of 0-5 00214 //center t around the half-way point 00215 double t1 = 10.0 * (t / max_t) - 5.0; 00216 return 1.0 / (1 + exp(0 - t1)); 00217 } 00218