BEAST/BSE - Better Audio System and Sound Engine
0.8.2
|
00001 // Licensed GNU LGPL v2.1 or later: http://www.gnu.org/licenses/lgpl.html 00002 #ifndef __BSE_MATH_H__ 00003 #define __BSE_MATH_H__ 00004 00005 #include <bse/bsedefs.hh> 00006 #include <bse/bseieee754.hh> /* provides math.h */ 00007 00008 G_BEGIN_DECLS 00009 00010 /* --- constants --- */ 00011 /* PI is defined in bseieee754.hh */ 00012 #define BSE_1_DIV_PI (0.3183098861837906715377675267450287240689) // 1/pi 00013 #define BSE_PI_DIV_2 (1.570796326794896619231321691639751442099) // pi/2 00014 #define BSE_2_DIV_PI (0.6366197723675813430755350534900574481378) // 2/pi 00015 #define BSE_2_DIV_SQRT_PI (1.128379167095512573896158903121545171688) // 2/sqrt(pi) 00016 #define BSE_2_DIV_LN2 (2.88539008177792681471984936200378427485329) // 2/ln(2) 00017 #define BSE_PI_DIV_4 (0.7853981633974483096156608458198757210493) // pi/4 00018 #define BSE_E (2.718281828459045235360287471352662497757) // e^1 00019 #define BSE_LOG2E (1.442695040888963407359924681001892137427) // log_2(e^1) 00020 #define BSE_LOG10E (0.4342944819032518276511289189166050822944) // log_10(e^1) 00021 #define BSE_LN2 (0.6931471805599453094172321214581765680755) // ln(2) 00022 #define BSE_SQRT2 (1.41421356237309504880168872420969807857) // sqrt(2) 00023 #define BSE_1_DIV_SQRT2 (0.7071067811865475244008443621048490392848) // 1/sqrt(2) 00024 #define BSE_LN4 (1.386294361119890618834464242916353136151) // ln(4) 00025 #define BSE_LN10 (2.302585092994045684017991454684364207601) // ln(10) 00026 #define BSE_LOG2_10 (3.321928094887362347870319429489390175865) // log_2(10) 00027 #define BSE_LOG2POW20_10 (0.1660964047443681173935159714744695087932) // log_2(10)/20 00028 #define BSE_2_POW_1_DIV_12 (1.059463094359295264561825294946341700779) // 2^(1/12) 00029 #define BSE_LN_2_POW_1_DIV_12 (5.776226504666210911810267678818138067296e-2) // ln(2^(1/12)) 00030 #define BSE_LN_2_POW_1_DIV_1200_d (5.776226504666210911810267678818138067296e-4) // ln(2^(1/1200)) 00031 #define BSE_2_POW_1_DIV_72 (1.009673533228510862192521401118605073603) // 2^(1/72) 00032 #define BSE_LN_2_POW_1_DIV_72 (9.62704417444368485301711279803023011216e-3) // ln(2^(1/72)) 00033 #define BSE_DECIBEL20_FACTOR (8.68588963806503655302257837833210164588794) // 20.0 / ln (10.0) 00034 #define BSE_DECIBEL10_FACTOR (4.34294481903251827651128918916605082294397) // 10.0 / ln (10.0) 00035 #define BSE_1_DIV_DECIBEL20_FACTOR (0.1151292546497022842008995727342182103801) // ln (10) / 20 00036 #define BSE_COMPLEX_ONE (bse_complex (1, 0)) 00037 00038 /* --- structures --- */ 00039 typedef struct { 00040 double re; 00041 double im; 00042 } BseComplex; 00043 00044 /* --- complex numbers --- */ 00045 static inline BseComplex bse_complex (double re, 00046 double im); 00047 static inline BseComplex bse_complex_polar (double abs, 00048 double arg); 00049 static inline BseComplex bse_complex_add (BseComplex c1, 00050 BseComplex c2); 00051 static inline BseComplex bse_complex_add3 (BseComplex c1, 00052 BseComplex c2, 00053 BseComplex c3); 00054 static inline BseComplex bse_complex_sub (BseComplex c1, 00055 BseComplex c2); 00056 static inline BseComplex bse_complex_sub3 (BseComplex c1, 00057 BseComplex c2, 00058 BseComplex c3); 00059 static inline BseComplex bse_complex_scale (BseComplex c1, 00060 double scale); 00061 static inline BseComplex bse_complex_mul (BseComplex c1, 00062 BseComplex c2); 00063 static inline BseComplex bse_complex_mul3 (BseComplex c1, 00064 BseComplex c2, 00065 BseComplex c3); 00066 static inline BseComplex bse_complex_div (BseComplex a, 00067 BseComplex b); 00068 static inline BseComplex bse_complex_reciprocal (BseComplex c); 00069 static inline BseComplex bse_complex_sqrt (BseComplex z); 00070 static inline BseComplex bse_complex_conj (BseComplex c); /* {re, -im} */ 00071 static inline BseComplex bse_complex_id (BseComplex c); 00072 static inline BseComplex bse_complex_inv (BseComplex c); /* {-re, -im} */ 00073 static inline double bse_complex_abs (BseComplex c); 00074 static inline double bse_complex_arg (BseComplex c); 00075 static inline BseComplex bse_complex_sin (BseComplex c); 00076 static inline BseComplex bse_complex_cos (BseComplex c); 00077 static inline BseComplex bse_complex_tan (BseComplex c); 00078 static inline BseComplex bse_complex_sinh (BseComplex c); 00079 static inline BseComplex bse_complex_cosh (BseComplex c); 00080 static inline BseComplex bse_complex_tanh (BseComplex c); 00081 std::string bse_complex_str (BseComplex c); 00082 std::string bse_complex_list (uint n_points, 00083 BseComplex *points, 00084 const std::string &indent); 00085 void bse_complex_gnuplot (const char *file_name, 00086 uint n_points, 00087 BseComplex *points); 00088 std::string bse_string_from_double (long double value); 00089 00090 /* --- polynomials --- */ 00091 /* example, degree=2: 5+2x+7x^2 => a[0..degree] = { 5, 2, 7 } */ 00092 static inline void bse_poly_add (uint degree, 00093 double *a, /* a[0..degree] */ 00094 double *b); 00095 static inline void bse_poly_sub (uint order, 00096 double *a, /* [0..degree] */ 00097 double *b); 00098 static inline void bse_poly_mul (double *p, /* out:[0..aorder+border] */ 00099 uint aorder, 00100 const double *a, /* in:[0..aorder] */ 00101 uint border, 00102 const double *b); /* in:[0..border] */ 00103 static inline void bse_poly_scale (uint order, 00104 double *a, /* [0..degree] */ 00105 double scale); 00106 static inline void bse_poly_xscale (uint order, 00107 double *a, /* [0..degree] */ 00108 double xscale); 00109 static inline double bse_poly_eval (uint degree, 00110 double *a, /* [0..degree] */ 00111 double x); 00112 void bse_poly_complex_roots (uint poly_degree, 00113 double *a, /* [0..degree] (degree+1 elements) */ 00114 BseComplex *roots); /* [degree] */ 00115 void bse_poly_from_re_roots (uint poly_degree, 00116 double *a, /* [0..degree] */ 00117 BseComplex *roots); 00118 void bse_cpoly_from_roots (uint poly_degree, 00119 BseComplex *c, /* [0..degree] */ 00120 BseComplex *roots); 00121 static inline void bse_cpoly_mul_monomial (uint degree, /* _new_ degree */ 00122 BseComplex *c, /* in:[0..degree-1] out:[0..degree] */ 00123 BseComplex root); /* c(x) *= (x^1 - root) */ 00124 static inline void bse_cpoly_mul_reciprocal (uint degree, /* _new_ degree */ 00125 BseComplex *c, /* in:[0..degree-1] out:[0..degree] */ 00126 BseComplex root); /* c(x) *= (1 - root * x^-1) */ 00127 static inline void bse_cpoly_mul (BseComplex *p, /* out:[0..aorder+border] */ 00128 uint aorder, 00129 BseComplex *a, /* in:[0..aorder] */ 00130 uint border, 00131 BseComplex *b); /* in:[0..border] */ 00132 gboolean bse_poly2_droots (gdouble roots[2], 00133 gdouble a, 00134 gdouble b, 00135 gdouble c); 00136 std::string bse_poly_str (uint degree, 00137 double *a, 00138 const std::string &var); 00139 std::string bse_poly_str1 (uint degree, 00140 double *a, 00141 const std::string &var); 00142 00143 /* --- transformations --- */ 00144 double bse_temp_freq (double kammer_freq, 00145 int semitone_delta); 00146 00147 /* --- miscellaneous --- */ 00148 double bse_bit_depth_epsilon (guint n_bits); /* 1..32 */ 00149 gint bse_rand_int (void); /* +-G_MAXINT */ 00150 gfloat bse_rand_float (void); /* -1.0..1.0 */ 00151 gint bse_rand_bool (void); /* random bit */ 00152 void bse_float_gnuplot (const char *file_name, 00153 double xstart, 00154 double xstep, 00155 uint n_ypoints, 00156 const float *ypoints); 00157 00158 00159 /* --- implementations --- */ 00160 static inline BseComplex 00161 bse_complex (double re, 00162 double im) 00163 { 00164 BseComplex r; 00165 r.re = re; 00166 r.im = im; 00167 return r; 00168 } 00169 static inline BseComplex 00170 bse_complex_polar (double abs, 00171 double arg) 00172 { 00173 return bse_complex (abs * cos (arg), abs * sin (arg)); 00174 } 00175 static inline BseComplex 00176 bse_complex_add (BseComplex c1, 00177 BseComplex c2) 00178 { 00179 return bse_complex (c1.re + c2.re, c1.im + c2.im); 00180 } 00181 static inline BseComplex 00182 bse_complex_add3 (BseComplex c1, 00183 BseComplex c2, 00184 BseComplex c3) 00185 { 00186 return bse_complex (c1.re + c2.re + c3.re, c1.im + c2.im + c3.im); 00187 } 00188 static inline BseComplex 00189 bse_complex_sub (BseComplex c1, 00190 BseComplex c2) 00191 { 00192 return bse_complex (c1.re - c2.re, c1.im - c2.im); 00193 } 00194 static inline BseComplex 00195 bse_complex_sub3 (BseComplex c1, 00196 BseComplex c2, 00197 BseComplex c3) 00198 { 00199 return bse_complex (c1.re - c2.re - c3.re, c1.im - c2.im - c3.im); 00200 } 00201 static inline BseComplex 00202 bse_complex_scale (BseComplex c1, 00203 double scale) 00204 { 00205 return bse_complex (c1.re * scale, c1.im * scale); 00206 } 00207 static inline BseComplex 00208 bse_complex_mul (BseComplex c1, 00209 BseComplex c2) 00210 { 00211 return bse_complex (c1.re * c2.re - c1.im * c2.im, c1.re * c2.im + c1.im * c2.re); 00212 } 00213 static inline BseComplex 00214 bse_complex_mul3 (BseComplex c1, 00215 BseComplex c2, 00216 BseComplex c3) 00217 { 00218 double aec = c1.re * c2.re * c3.re; 00219 double bde = c1.im * c2.im * c3.re; 00220 double adf = c1.re * c2.im * c3.im; 00221 double bcf = c1.im * c2.re * c3.im; 00222 double ade = c1.re * c2.im * c3.re; 00223 double bce = c1.im * c2.re * c3.re; 00224 double acf = c1.re * c2.re * c3.im; 00225 double bdf = c1.im * c2.im * c3.im; 00226 00227 return bse_complex (aec - bde - adf - bcf, ade + bce + acf - bdf); 00228 } 00229 static inline BseComplex 00230 bse_complex_div (BseComplex a, 00231 BseComplex b) 00232 { 00233 BseComplex c; 00234 if (fabs (b.re) >= fabs (b.im)) 00235 { 00236 double r = b.im / b.re, den = b.re + r * b.im; 00237 c.re = (a.re + r * a.im) / den; 00238 c.im = (a.im - r * a.re) / den; 00239 } 00240 else 00241 { 00242 double r = b.re / b.im, den = b.im + r * b.re; 00243 c.re = (a.re * r + a.im) / den; 00244 c.im = (a.im * r - a.re) / den; 00245 } 00246 return c; 00247 } 00248 static inline BseComplex 00249 bse_complex_reciprocal (BseComplex c) 00250 { 00251 if (fabs (c.re) >= fabs (c.im)) 00252 { 00253 double r = c.im / c.re, den = c.re + r * c.im; 00254 c.re = 1. / den; 00255 c.im = - r / den; 00256 } 00257 else 00258 { 00259 double r = c.re / c.im, den = c.im + r * c.re; 00260 c.re = r / den; 00261 c.im = - 1. / den; 00262 } 00263 return c; 00264 } 00265 static inline BseComplex 00266 bse_complex_sqrt (BseComplex z) 00267 { 00268 if (z.re == 0.0 && z.im == 0.0) 00269 return z; 00270 else 00271 { 00272 BseComplex c; 00273 double w, x = fabs (z.re), y = fabs (z.im); 00274 if (x >= y) 00275 { 00276 double r = y / x; 00277 w = sqrt (x) * sqrt (0.5 * (1.0 + sqrt (1.0 + r * r))); 00278 } 00279 else 00280 { 00281 double r = x / y; 00282 w = sqrt (y) * sqrt (0.5 * (r + sqrt (1.0 + r * r))); 00283 } 00284 if (z.re >= 0.0) 00285 { 00286 c.re = w; 00287 c.im = z.im / (2.0 * w); 00288 } 00289 else 00290 { 00291 c.im = z.im >= 0 ? w : -w; 00292 c.re = z.im / (2.0 * c.im); 00293 } 00294 return c; 00295 } 00296 } 00297 static inline BseComplex 00298 bse_complex_conj (BseComplex c) 00299 { 00300 return bse_complex (c.re, -c.im); 00301 } 00302 static inline BseComplex 00303 bse_complex_inv (BseComplex c) 00304 { 00305 return bse_complex (-c.re, -c.im); 00306 } 00307 static inline BseComplex 00308 bse_complex_id (BseComplex c) 00309 { 00310 return c; 00311 } 00312 static inline double 00313 bse_complex_abs (BseComplex c) 00314 { 00315 /* compute (a^2 + b^2)^(1/2) without destructive underflow or overflow */ 00316 double absa = fabs (c.re), absb = fabs (c.im); 00317 return (absa > absb ? 00318 absb == 0.0 ? absa : 00319 absa * sqrt (1.0 + (absb / absa) * (absb / absa)) : 00320 absb == 0.0 ? 0.0 : 00321 absb * sqrt (1.0 + (absa / absb) * (absa / absb))); 00322 } 00323 static inline double 00324 bse_complex_arg (BseComplex c) 00325 { 00326 double a = atan2 (c.im, c.re); 00327 return a; 00328 } 00329 static inline BseComplex 00330 bse_complex_sin (BseComplex c) 00331 { 00332 return bse_complex (sin (c.re) * cosh (c.im), cos (c.re) * sinh (c.im)); 00333 } 00334 static inline BseComplex 00335 bse_complex_cos (BseComplex c) 00336 { 00337 return bse_complex (cos (c.re) * cosh (c.im), - sin (c.re) * sinh (c.im)); 00338 } 00339 static inline BseComplex 00340 bse_complex_tan (BseComplex c) 00341 { 00342 return bse_complex_div (bse_complex (tan (c.re), tanh (c.im)), 00343 bse_complex (1.0, -tan (c.re) * tanh (c.im))); 00344 } 00345 static inline BseComplex 00346 bse_complex_sinh (BseComplex c) 00347 { 00348 return bse_complex (sinh (c.re) * cos (c.im), cosh (c.re) * sin (c.im)); 00349 } 00350 static inline BseComplex 00351 bse_complex_cosh (BseComplex c) 00352 { 00353 return bse_complex (cosh (c.re) * cos (c.im), sinh (c.re) * sin (c.im)); 00354 } 00355 static inline BseComplex 00356 bse_complex_tanh (BseComplex c) 00357 { 00358 return bse_complex_div (bse_complex_sinh (c), 00359 bse_complex_cosh (c)); 00360 } 00361 static inline void 00362 bse_poly_add (uint degree, 00363 double *a, 00364 double *b) 00365 { 00366 uint i; 00367 00368 for (i = 0; i <= degree; i++) 00369 a[i] += b[i]; 00370 } 00371 static inline void 00372 bse_poly_sub (uint degree, 00373 double *a, 00374 double *b) 00375 { 00376 uint i; 00377 00378 for (i = 0; i <= degree; i++) 00379 a[i] -= b[i]; 00380 } 00381 static inline void 00382 bse_poly_mul (double *p, /* out:[0..aorder+border] */ 00383 uint aorder, 00384 const double *a, /* in:[0..aorder] */ 00385 uint border, 00386 const double *b) /* in:[0..border] */ 00387 { 00388 uint i; 00389 00390 for (i = aorder + border; i > 0; i--) 00391 { 00392 uint j; 00393 double t = 0; 00394 00395 for (j = i - MIN (border, i); j <= MIN (aorder, i); j++) 00396 t += a[j] * b[i - j]; 00397 p[i] = t; 00398 } 00399 p[0] = a[0] * b[0]; 00400 } 00401 static inline void 00402 bse_cpoly_mul_monomial (uint degree, 00403 BseComplex *c, 00404 BseComplex root) 00405 { 00406 uint j; 00407 00408 c[degree] = c[degree - 1]; 00409 for (j = degree - 1; j >= 1; j--) 00410 c[j] = bse_complex_sub (c[j - 1], bse_complex_mul (c[j], root)); 00411 c[0] = bse_complex_mul (c[0], bse_complex_inv (root)); 00412 } 00413 static inline void 00414 bse_cpoly_mul_reciprocal (uint degree, 00415 BseComplex *c, 00416 BseComplex root) 00417 { 00418 uint j; 00419 00420 c[degree] = bse_complex_mul (c[degree - 1], bse_complex_inv (root)); 00421 for (j = degree - 1; j >= 1; j--) 00422 c[j] = bse_complex_sub (c[j], bse_complex_mul (c[j - 1], root)); 00423 /* c[0] = c[0]; */ 00424 } 00425 static inline void 00426 bse_cpoly_mul (BseComplex *p, /* [0..aorder+border] */ 00427 uint aorder, 00428 BseComplex *a, 00429 uint border, 00430 BseComplex *b) 00431 { 00432 uint i; 00433 00434 for (i = aorder + border; i > 0; i--) 00435 { 00436 BseComplex t; 00437 uint j; 00438 00439 t = bse_complex (0, 0); 00440 for (j = i - MIN (i, border); j <= MIN (aorder, i); j++) 00441 t = bse_complex_add (t, bse_complex_mul (a[j], b[i - j])); 00442 p[i] = t; 00443 } 00444 p[0] = bse_complex_mul (a[0], b[0]); 00445 } 00446 static inline void 00447 bse_poly_scale (uint degree, 00448 double *a, 00449 double scale) 00450 { 00451 uint i; 00452 00453 for (i = 0; i <= degree; i++) 00454 a[i] *= scale; 00455 } 00456 static inline void 00457 bse_poly_xscale (uint degree, 00458 double *a, 00459 double xscale) 00460 { 00461 double scale = xscale; 00462 uint i; 00463 00464 for (i = 1; i <= degree; i++) 00465 { 00466 a[i] *= scale; 00467 scale *= xscale; 00468 } 00469 } 00470 static inline double 00471 bse_poly_eval (uint degree, 00472 double *a, 00473 double x) 00474 { 00475 double sum = a[degree]; 00476 00477 while (degree--) 00478 sum = sum * x + a[degree]; 00479 return sum; 00480 } 00481 00482 G_END_DECLS 00483 00484 #endif /* __BSE_MATH_H__ */ /* vim: set ts=8 sw=2 sts=2: */