BEAST/BSE - Better Audio System and Sound Engine  0.8.2
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
bsemathsignal.hh
Go to the documentation of this file.
00001  // Licensed GNU LGPL v2.1 or later: http://www.gnu.org/licenses/lgpl.html
00002 #ifndef __BSE_SIGNAL_H__
00003 #define __BSE_SIGNAL_H__
00004 
00005 #include <bse/bsemath.hh>
00006 #include <bse/bseglobals.hh>
00007 #include <bse/bsetype.hh> // for BseMusicalTuningType
00008 
00009 G_BEGIN_DECLS
00010 
00014 #define BSE_SIGNAL_EPSILON      (1.15e-14)      /* 1.16415321826934814453125e-9 ~= 1/2^33 */
00015 
00019 #define BSE_SIGNAL_KAPPA        (1.5)
00020 
00026 #define BSE_SIGNAL_RAISING_EDGE(v1,v2)  ((v1) < (v2))
00027 
00030 #define BSE_SIGNAL_FALLING_EDGE(v1,v2)  ((v1) > (v2))
00031 
00035 #define BSE_SIGNAL_FREQ_CHANGED(v1,v2)  (fabs ((v1) - (v2)) > 1e-7)
00036 
00039 #define BSE_SIGNAL_FREQ_EQUALS(v1,v2)   (!BSE_SIGNAL_FREQ_CHANGED (v1, v2))
00040 
00044 #define BSE_SIGNAL_MOD_CHANGED(v1,v2)   (fabs ((v1) - (v2)) > 1e-8)
00045 
00049 #define BSE_SIGNAL_GAIN_CHANGED(v1,v2)  (fabs ((v1) - (v2)) > 1e-8)
00050 
00054 #define BSE_SIGNAL_TO_FREQ_FACTOR       (BSE_MAX_FREQUENCY)
00055 #define BSE_SIGNAL_FROM_FREQ_FACTOR     (1.0 / BSE_MAX_FREQUENCY)
00056 #define BSE_SIGNAL_TO_FREQ(value)       (BSE_FREQ_FROM_VALUE (value))
00057 #define BSE_SIGNAL_FROM_FREQ(freq)      (BSE_VALUE_FROM_FREQ (freq))
00058 
00059 #define BSE_SIGNAL_CLIP(v)      bse_signal_value_clip (v)
00060 
00061 static inline double   bse_signal_value_clip (register double x)  G_GNUC_CONST;
00062 static inline double G_GNUC_CONST
00063 bse_signal_value_clip (register double x)
00064 {
00065   if (G_UNLIKELY (x > 1.0))
00066     return 1.0;
00067   if (G_UNLIKELY (x < -1.0))
00068     return -1.0;
00069   return x;
00070 }
00071 
00072 
00073 /* --- frequency modulation --- */
00074 typedef struct {
00075   gfloat        fm_strength;            /* linear: 0..1, exponential: n_octaves */
00076   guint         exponential_fm : 1;
00077   gfloat        signal_freq;            /* for ifreq == NULL (as BSE_SIGNAL_FROM_FREQ) */
00078   gint          fine_tune;              /* -100..+100 */
00079 } BseFrequencyModulator;
00080 
00081 void    bse_frequency_modulator (const BseFrequencyModulator    *fm,
00082                                  guint                           n_values,
00083                                  const gfloat                   *ifreq,
00084                                  const gfloat                   *ifmod,
00085                                  gfloat                         *fm_buffer);
00086 
00087 
00088 /* --- windows --- */
00089 double  bse_window_bartlett     (double x);     /* narrowest */
00090 double  bse_window_blackman     (double x);
00091 double  bse_window_cos          (double x);
00092 double  bse_window_hamming      (double x);
00093 double  bse_window_sinc         (double x);
00094 double  bse_window_rect         (double x);     /* widest */
00095 
00096 
00097 /* --- function approximations --- */
00098 
00110 static inline double    bse_approx_atan1          (register double x)  G_GNUC_CONST;
00111 
00120 double                  bse_approx_atan1_prescale (double          boost_amount);
00121 
00131 static inline double    bse_approx_qcircle1       (register double x)  G_GNUC_CONST;
00132 
00142 static inline double    bse_approx_qcircle2       (register double x)  G_GNUC_CONST;
00143 
00153 static inline double    bse_approx_qcircle3       (register double x)  G_GNUC_CONST;
00154 
00164 static inline double    bse_approx_qcircle4       (register double x)  G_GNUC_CONST;
00165 
00176 static inline double    bse_approx2_exp2        (float ex)      G_GNUC_CONST;
00177 
00188 static inline double    bse_approx3_exp2        (float ex)      G_GNUC_CONST;
00189 
00200 static inline double    bse_approx4_exp2        (float ex)      G_GNUC_CONST;
00201 
00212 static inline double    bse_approx5_exp2        (float ex)      G_GNUC_CONST;
00213 
00224 static inline double    bse_approx6_exp2        (float ex)      G_GNUC_CONST;
00225 
00236 static inline double    bse_approx7_exp2        (float ex)      G_GNUC_CONST;
00237 
00249 static inline double    bse_approx8_exp2        (float ex)      G_GNUC_CONST;
00250 
00262 static inline double    bse_approx9_exp2        (float ex)      G_GNUC_CONST;
00263 
00273 static inline double    bse_approx2_tanh        (float x)       G_GNUC_CONST;
00274 
00284 static inline double    bse_approx3_tanh        (float x)       G_GNUC_CONST;
00285 
00295 static inline double    bse_approx4_tanh        (float x)       G_GNUC_CONST;
00296 
00306 static inline double    bse_approx5_tanh        (float x)       G_GNUC_CONST;
00307 
00317 static inline double    bse_approx6_tanh        (float x)       G_GNUC_CONST;
00318 
00328 static inline double    bse_approx7_tanh        (float x)       G_GNUC_CONST;
00329 
00340 static inline double    bse_approx8_tanh        (float x)       G_GNUC_CONST;
00341 
00352 static inline double    bse_approx9_tanh        (float x)       G_GNUC_CONST;
00353 
00364 static inline double    bse_saturate_hard       (double value,
00365                                                  double limit)  G_GNUC_CONST;
00366 
00377 static inline double    bse_saturate_branching (double value,
00378                                                 double limit)   G_GNUC_CONST;
00379 
00380 /* --- semitone factors (for +-11 octaves) --- */
00381 const double* bse_semitone_table_from_tuning (BseMusicalTuningType musical_tuning); /* returns [-132..+132] */
00382 double        bse_transpose_factor           (BseMusicalTuningType musical_tuning,
00383                                               int                  index /* [-132..+132] */);
00384 
00385 /* --- cents (1/100th of a semitone) --- */
00386 
00387 double                  bse_cent_tune (double fine_tune);
00388 
00399 static inline double    bse_cent_tune_fast (int fine_tune /* -100..+100 */)   G_GNUC_CONST;
00400 
00401 /* --- implementation details --- */
00402 static inline double  G_GNUC_CONST
00403 bse_approx_atan1 (register double x)
00404 {
00405   if (x < 0)    /* make use of -atan(-x)==atan(x) */
00406     {
00407       register double numerator, denominator = -1.0;
00408 
00409       denominator += x * 0.81901156857081841441890603235599; /* d1 */
00410       numerator = x * 0.41156875521951602506487246309908; /* -n1 */
00411       denominator *= x;
00412       numerator  += -1.0091272542790025586079663559158; /* n2 */
00413       denominator += 1.0091272542790025586079663559158; /* d2 */
00414 
00415       return -1.0 - numerator / denominator;
00416     }
00417   else
00418     {
00419       register double numerator, denominator = 1.0;
00420 
00421       denominator += x * 0.81901156857081841441890603235599; /* d1 */
00422       numerator = x * -0.41156875521951602506487246309908; /* n1 */
00423       denominator *= x;
00424       numerator  += -1.0091272542790025586079663559158; /* n2 */
00425       denominator += 1.0091272542790025586079663559158; /* d2 */
00426 
00427       return 1.0 + numerator / denominator;
00428     }
00429   /* atan1_positive(x)=1+(x*-0.411568755219516-1.009127254279)/((1+x*0.81901156857)*x+1.009127254279)
00430    * atan1(x)=x<0 ? -atan1_positive(-x) : atan1_positive(x)
00431    */
00432 }
00433 
00434 static inline double    G_GNUC_CONST
00435 bse_approx_qcircle1 (register double x)
00436 {
00437   double numerator = 1.20460124790369468987715633298929 * x - 1.20460124790369468987715633298929;
00438   double denominator = x - 1.20460124790369468987715633298929;
00439   /* R1(x)=(1.2046012479036946898771563 * x - 1.2046012479036946898771563) / (x - 1.2046012479036946898771563) */
00440   return numerator / denominator;
00441 }
00442 
00443 static inline double    G_GNUC_CONST
00444 bse_approx_qcircle2 (register double x)
00445 {
00446   double numerator = 1.20460124790369468987715633298929*x;
00447   double denominator = x + 0.20460124790369468987715633298929;
00448   /* R2(x)=1.2046012479036946898771563*x/(x + 0.2046012479036946898771563) */
00449   return numerator / denominator;
00450 }
00451 
00452 static inline double    G_GNUC_CONST
00453 bse_approx_qcircle3 (register double x)
00454 {
00455   double numerator = 0.20460124790369468987715633298929 - 0.20460124790369468987715633298929 * x;
00456   double denominator = x + 0.20460124790369468987715633298929;
00457   /* R3(x)=(0.2046012479036946898771563 - 0.2046012479036946898771563 * x) / (x + 0.2046012479036946898771563) */
00458   return numerator / denominator;
00459 }
00460 
00461 static inline double    G_GNUC_CONST
00462 bse_approx_qcircle4 (register double x)
00463 {
00464   double numerator = -0.20460124790369468987715633298929 * x;
00465   double denominator = x - 1.20460124790369468987715633298929;
00466   /* R4(x)=-0.2046012479036946898771563 * x / (x - 1.2046012479036946898771563) */
00467   return numerator / denominator;
00468 }
00469 
00470 static inline double G_GNUC_CONST
00471 bse_approx2_exp2 (float ex)
00472 {
00473   register BseFloatIEEE754 fp = { 0, };
00474   register int i = bse_ftoi (ex);
00475   fp.mpn.biased_exponent = BSE_FLOAT_BIAS + i;
00476   register double x = ex - i;
00477   return fp.v_float * (1.0 + x * (0.69314718055994530941723212145818 +
00478                                   x * (0.24022650695910071233355126316333)));
00479 }
00480 
00481 static inline double G_GNUC_CONST
00482 bse_approx3_exp2 (float ex)
00483 {
00484   register BseFloatIEEE754 fp = { 0, };
00485   register int i = bse_ftoi (ex);
00486   fp.mpn.biased_exponent = BSE_FLOAT_BIAS + i;
00487   register double x = ex - i;
00488   return fp.v_float * (1.0 + x * (0.69314718055994530941723212145818 +
00489                                   x * (0.24022650695910071233355126316333 +
00490                                        x * (0.055504108664821579953142263768622))));
00491   /* exp2frac(x)=x-ftoi(x)
00492    * exp2a3(x)=2**ftoi(x)*(1+exp2frac(x)*(0.6931471805599453+exp2frac(x)*(0.2402265069591+exp2frac(x)*0.0555041086648)))
00493    */
00494 }
00495 
00496 static inline double G_GNUC_CONST
00497 bse_approx4_exp2 (float ex)
00498 {
00499   register BseFloatIEEE754 fp = { 0, };
00500   register int i = bse_ftoi (ex);
00501   fp.mpn.biased_exponent = BSE_FLOAT_BIAS + i;
00502   register double x = ex - i;
00503   return fp.v_float * (1.0 + x * (0.69314718055994530941723212145818 +
00504                                   x * (0.24022650695910071233355126316333 +
00505                                        x * (0.055504108664821579953142263768622 +
00506                                             x * (0.0096181291076284771619790715736589)))));
00507   /* ftoi(x)=int(x<-0.0 ? x - 0.5 : x + 0.5)
00508    * exp2frac(x)=x-ftoi(x)
00509    * exp2a4(x)=2**ftoi(x)*(1+exp2frac(x)*(0.6931471805599453+exp2frac(x)*(0.2402265069591+exp2frac(x)*(0.0555041086648+exp2frac(x)*0.009618129107628477))))
00510    */
00511 }
00512 
00513 static inline double G_GNUC_CONST
00514 bse_approx5_exp2 (float ex)
00515 {
00516   register BseFloatIEEE754 fp = { 0, };
00517   register int i = bse_ftoi (ex);
00518   fp.mpn.biased_exponent = BSE_FLOAT_BIAS + i;
00519   register double x = ex - i;
00520   return fp.v_float * (1.0 + x * (0.69314718055994530941723212145818 +
00521                                   x * (0.24022650695910071233355126316333 +
00522                                        x * (0.055504108664821579953142263768622 +
00523                                             x * (0.0096181291076284771619790715736589 +
00524                                                  x * (0.0013333558146428443423412221987996))))));
00525 }
00526 
00527 static inline double G_GNUC_CONST
00528 bse_approx6_exp2 (float ex)
00529 {
00530   register BseFloatIEEE754 fp = { 0, };
00531   register int i = bse_ftoi (ex);
00532   fp.mpn.biased_exponent = BSE_FLOAT_BIAS + i;
00533   register double x = ex - i;
00534   return fp.v_float * (1.0 + x * (0.69314718055994530941723212145818 +
00535                                   x * (0.24022650695910071233355126316333 +
00536                                        x * (0.055504108664821579953142263768622 +
00537                                             x * (0.0096181291076284771619790715736589 +
00538                                                  x * (0.0013333558146428443423412221987996 +
00539                                                       x * (0.00015403530393381609954437097332742)))))));
00540 }
00541 
00542 static inline double G_GNUC_CONST
00543 bse_approx7_exp2 (float ex)
00544 {
00545   register BseFloatIEEE754 fp = { 0, };
00546   register int i = bse_ftoi (ex);
00547   fp.mpn.biased_exponent = BSE_FLOAT_BIAS + i;
00548   register double x = ex - i;
00549   return fp.v_float * (1.0 + x * (0.69314718055994530941723212145818 +
00550                                   x * (0.24022650695910071233355126316333 +
00551                                        x * (0.055504108664821579953142263768622 +
00552                                             x * (0.0096181291076284771619790715736589 +
00553                                                  x * (0.0013333558146428443423412221987996 +
00554                                                       x * (0.00015403530393381609954437097332742 +
00555                                                            x * (0.00001525273380405984028002543901201))))))));
00556 }
00557 
00558 static inline double G_GNUC_CONST
00559 bse_approx8_exp2 (float ex)
00560 {
00561   register BseFloatIEEE754 fp = { 0, };
00562   register int i = bse_ftoi (ex);
00563   fp.mpn.biased_exponent = BSE_FLOAT_BIAS + i;
00564   register double x = ex - i;
00565   return fp.v_float * (1.0 + x * (0.69314718055994530941723212145818 +
00566                                   x * (0.24022650695910071233355126316333 +
00567                                        x * (0.055504108664821579953142263768622 +
00568                                             x * (0.0096181291076284771619790715736589 +
00569                                                  x * (0.0013333558146428443423412221987996 +
00570                                                       x * (0.00015403530393381609954437097332742 +
00571                                                            x * (0.00001525273380405984028002543901201 +
00572                                                                 x * (0.0000013215486790144309488403758228288)))))))));
00573 }
00574 
00575 static inline double G_GNUC_CONST
00576 bse_approx9_exp2 (float ex)
00577 {
00578   register BseFloatIEEE754 fp = { 0, };
00579   register int i = bse_ftoi (ex);
00580   fp.mpn.biased_exponent = BSE_FLOAT_BIAS + i;
00581   register double x = ex - i;
00582   return fp.v_float * (1.0 + x * (0.69314718055994530941723212145818 +
00583                                   x * (0.24022650695910071233355126316333 +
00584                                        x * (0.055504108664821579953142263768622 +
00585                                             x * (0.0096181291076284771619790715736589 +
00586                                                  x * (0.0013333558146428443423412221987996 +
00587                                                       x * (0.00015403530393381609954437097332742 +
00588                                                            x * (0.00001525273380405984028002543901201 +
00589                                                                 x * (0.0000013215486790144309488403758228288 +
00590                                                                      x * 0.00000010178086009239699727490007597745)))))))));
00591 }
00592 
00593 static inline double G_GNUC_CONST
00594 bse_approx2_tanh (float x)
00595 {
00596   if (G_UNLIKELY (x < -20))
00597     return -1;
00598   if (G_UNLIKELY (x > 20))
00599     return 1;
00600   register double bpot = bse_approx2_exp2 (x * BSE_2_DIV_LN2);
00601   return (bpot - 1) / (bpot + 1);
00602 }
00603 
00604 static inline double G_GNUC_CONST
00605 bse_approx3_tanh (float x)
00606 {
00607   if (G_UNLIKELY (x < -20))
00608     return -1;
00609   if (G_UNLIKELY (x > 20))
00610     return 1;
00611   register double bpot = bse_approx3_exp2 (x * BSE_2_DIV_LN2);
00612   return (bpot - 1) / (bpot + 1);
00613 }
00614 
00615 static inline double G_GNUC_CONST
00616 bse_approx4_tanh (float x)
00617 {
00618   if (G_UNLIKELY (x < -20))
00619     return -1;
00620   if (G_UNLIKELY (x > 20))
00621     return 1;
00622   register double bpot = bse_approx4_exp2 (x * BSE_2_DIV_LN2);
00623   return (bpot - 1) / (bpot + 1);
00624   /* tanha4(x)=x<-20 ? -1 : x>20 ? 1 : (exp2a4(x*2.885390081777926814719849362)-1) / (exp2a4(x*2.885390081777926814719849362)+1) */
00625 }
00626 
00627 static inline double G_GNUC_CONST
00628 bse_approx5_tanh (float x)
00629 {
00630   if (G_UNLIKELY (x < -20))
00631     return -1;
00632   if (G_UNLIKELY (x > 20))
00633     return 1;
00634   register double bpot = bse_approx5_exp2 (x * BSE_2_DIV_LN2);
00635   return (bpot - 1) / (bpot + 1);
00636 }
00637 
00638 static inline double G_GNUC_CONST
00639 bse_approx6_tanh (float x)
00640 {
00641   if (G_UNLIKELY (x < -20))
00642     return -1;
00643   if (G_UNLIKELY (x > 20))
00644     return 1;
00645   register double bpot = bse_approx6_exp2 (x * BSE_2_DIV_LN2);
00646   return (bpot - 1) / (bpot + 1);
00647 }
00648 
00649 static inline double G_GNUC_CONST
00650 bse_approx7_tanh (float x)
00651 {
00652   if (G_UNLIKELY (x < -20))
00653     return -1;
00654   if (G_UNLIKELY (x > 20))
00655     return 1;
00656   register double bpot = bse_approx7_exp2 (x * BSE_2_DIV_LN2);
00657   return (bpot - 1) / (bpot + 1);
00658 }
00659 
00660 static inline double G_GNUC_CONST
00661 bse_approx8_tanh (float x)
00662 {
00663   if (G_UNLIKELY (x < -20))
00664     return -1;
00665   if (G_UNLIKELY (x > 20))
00666     return 1;
00667   register double bpot = bse_approx8_exp2 (x * BSE_2_DIV_LN2);
00668   return (bpot - 1) / (bpot + 1);
00669 }
00670 
00671 static inline double G_GNUC_CONST
00672 bse_approx9_tanh (float x)
00673 {
00674   if (G_UNLIKELY (x < -20))
00675     return -1;
00676   if (G_UNLIKELY (x > 20))
00677     return 1;
00678   register double bpot = bse_approx9_exp2 (x * BSE_2_DIV_LN2);
00679   return (bpot - 1) / (bpot + 1);
00680 }
00681 
00682 static inline double G_GNUC_CONST
00683 bse_saturate_hard (double value,
00684                    double limit)
00685 {
00686   register double v1 = fabsf (value + limit);
00687   register double v2 = fabsf (value - limit);
00688   return 0.5 * (v1 - v2); /* CLAMP() without branching */
00689 }
00690 
00691 static inline double G_GNUC_CONST
00692 bse_saturate_branching (double value,
00693                         double limit)
00694 {
00695   if (G_UNLIKELY (value >= limit))
00696     return limit;
00697   if (G_UNLIKELY (value <= limit))
00698     return -limit;
00699   return value;
00700 }
00701 
00702 void    _bse_init_signal (void);
00703 
00704 extern const double * const bse_cent_table;
00705 
00706 static inline double G_GNUC_CONST
00707 bse_cent_tune_fast (int fine_tune)
00708 {
00709   return bse_cent_table[CLAMP (fine_tune, -100, 100)];
00710 }
00711 
00712 G_END_DECLS
00713 
00714 #endif /* __BSE_SIGNAL_H__ */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines