summaryrefslogtreecommitdiffstats
path: root/flow/gsl/gslsignal.c
diff options
context:
space:
mode:
Diffstat (limited to 'flow/gsl/gslsignal.c')
-rw-r--r--flow/gsl/gslsignal.c258
1 files changed, 258 insertions, 0 deletions
diff --git a/flow/gsl/gslsignal.c b/flow/gsl/gslsignal.c
new file mode 100644
index 0000000..9afc5bb
--- /dev/null
+++ b/flow/gsl/gslsignal.c
@@ -0,0 +1,258 @@
+/* GSL - Generic Sound Layer
+ * Copyright (C) 2001-2002 Tim Janik and Stefan Westerfeld
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This library 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 Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#include "gslsignal.h"
+
+#include "gslcommon.h"
+
+
+/* --- frequency modulation --- */
+void
+gsl_frequency_modulator (const GslFrequencyModulator *fm,
+ guint n_values,
+ const gfloat *ifreq,
+ const gfloat *ifmod,
+ gfloat *fm_buffer)
+{
+ gfloat *bound, fine_tune, fm_strength;
+ gboolean with_fine_tune;
+
+ fine_tune = gsl_cent_factor (fm->fine_tune);
+ with_fine_tune = fm->fine_tune != 0;
+ fm_strength = fm->fm_strength;
+
+ bound = fm_buffer + n_values;
+ if (ifreq && ifmod)
+ {
+ if (fm->exponential_fm)
+ {
+ if (with_fine_tune)
+ do {
+ *fm_buffer++ = *ifreq++ * gsl_approx_exp2 (fm_strength * *ifmod++) * fine_tune;
+ } while (fm_buffer < bound);
+ else
+ do {
+ *fm_buffer++ = *ifreq++ * gsl_approx_exp2 (fm_strength * *ifmod++);
+ } while (fm_buffer < bound);
+ }
+ else
+ {
+ if (with_fine_tune)
+ do {
+ *fm_buffer++ = *ifreq++ * (1 + fm_strength * *ifmod++) * fine_tune;
+ } while (fm_buffer < bound);
+ else
+ do {
+ *fm_buffer++ = *ifreq++ * (1 + fm_strength * *ifmod++);
+ } while (fm_buffer < bound);
+ }
+ }
+ else if (ifmod)
+ {
+ gfloat signal_freq = fm->signal_freq * fine_tune;
+
+ if (fm->exponential_fm)
+ do {
+ *fm_buffer++ = signal_freq * gsl_approx_exp2 (fm_strength * *ifmod++);
+ } while (fm_buffer < bound);
+ else
+ do {
+ *fm_buffer++ = signal_freq * (1 + fm_strength * *ifmod++);
+ } while (fm_buffer < bound);
+ }
+ else if (ifreq)
+ {
+ if (with_fine_tune)
+ do {
+ *fm_buffer++ = *ifreq++ * fine_tune;
+ } while (fm_buffer < bound);
+ else
+ do {
+ *fm_buffer++ = *ifreq++;
+ } while (fm_buffer < bound);
+ }
+ else
+ {
+ gfloat signal_freq = fm->signal_freq * fine_tune;
+
+ do {
+ *fm_buffer++ = signal_freq;
+ } while (fm_buffer < bound);
+ }
+}
+
+
+/* --- windows --- */
+double
+gsl_window_bartlett (double x) /* triangle */
+{
+ if (fabs (x) > 1)
+ return 0;
+
+ return 1.0 - fabs (x);
+}
+
+double
+gsl_window_blackman (double x)
+{
+ if (fabs (x) > 1)
+ return 0;
+
+ return 0.42 + 0.5 * cos (GSL_PI * x) + 0.08 * cos (2.0 * GSL_PI * x);
+}
+
+double
+gsl_window_cos (double x) /* von Hann window */
+{
+ if (fabs (x) > 1)
+ return 0;
+
+ return 0.5 * cos (x * GSL_PI) + 0.5;
+}
+
+double
+gsl_window_hamming (double x) /* sharp (rectangle) cutoffs at boundaries */
+{
+ if (fabs (x) > 1)
+ return 0;
+
+ return 0.54 + 0.46 * cos (GSL_PI * x);
+}
+
+double
+gsl_window_sinc (double x) /* noramlied C. Lanczos window */
+{
+ if (fabs (x) > 1)
+ return 0;
+ x = x * GSL_PI;
+ if (fabs (x) < 1e-12)
+ return 1.0;
+ else
+ return sin (x) / x;
+}
+
+double
+gsl_window_rect (double x) /* a square */
+{
+ if (fabs (x) > 1)
+ return 0;
+ return 1.0;
+}
+
+/*
+cos_roll_off(x)= x>fh?0:x<fl?1:cos(pi/2.*((fl-x)/(fh-fl)))
+*/
+
+
+/* --- cents & init --- */
+const gdouble *gsl_cent_table = NULL;
+#define GSL_2_RAISED_TO_1_OVER_1200_d ( /* 2^(1/1200) */ \
+ 1.0005777895065548488418016859213821589946746826171875)
+void
+_gsl_init_signal (void)
+{
+ static gdouble cent_table_space[201];
+ gint i;
+
+ /* cent table initialization,
+ * allow negative indexing within [-100..+100]
+ */
+ gsl_cent_table = cent_table_space + 100;
+ for (i = -100; i <= 100; i++)
+ cent_table_space[100 + i] = pow (GSL_2_RAISED_TO_1_OVER_1200_d, i);
+}
+
+
+/* --- gsl_approx_atan1() --- */
+double
+gsl_approx_atan1_prescale (double boost_amount)
+{
+ double max_boost_factor = 100; /* atan1(x*100) gets pretty close to 1 for x=1 */
+ double recip_tan_1_div_0_75 = 0.24202942695518667705824990442766; /* 1/tan(1/0.75) */
+ double scale;
+
+ g_return_val_if_fail (boost_amount >= 0 && boost_amount <= 1.0, 1.0);
+
+ /* scale boost_amount from [0..1] to -1..1 */
+ boost_amount = boost_amount * 2 - 1.0;
+
+ /* prescale factor for atan1(x*prescale), ranges from 1/max_boost_factor..max_boost_factor */
+ scale = pow (max_boost_factor, tan (boost_amount / 0.75) * recip_tan_1_div_0_75);
+
+ return scale;
+}
+
+
+/* --- exp2f() approximation taylor coefficients finder --- */
+#if 0
+#include <stdio.h>
+double
+exp2coeff (int n)
+{
+ double r = 1;
+ int i;
+
+ for (i = 1; i <= n; i++)
+ {
+ r *= GSL_LN2;
+ r /= i;
+ }
+ return r;
+}
+/* generate taylor coefficients */
+int
+main (int argc,
+ char *argv[])
+{
+ int i;
+
+ for (i = 0; i < 20; i++)
+ printf ("#define EXP2_TAYLOR_COEFF_%u\t(%.40f)\n", i, exp2coeff (i));
+
+ return 0;
+}
+/* test/bench program */
+#define _GNU_SOURCE
+#include <math.h>
+int
+main (int argc,
+ char *argv[])
+{
+ double x, dummy = 0, l = 4;
+
+ if (1) /* print errors */
+ for (x = -3; x < 3.01; x += 0.1)
+ {
+ g_print ("%+f %+1.20f \t (%.20f - %.20f)\n",
+ x, exp (x * GSL_LN2) - gsl_signal_exp2 (x),
+ exp (x * GSL_LN2), gsl_signal_exp2 (x));
+ }
+
+ if (0) /* bench test */
+ for (x = -l; x < l; x += 0.000001)
+ {
+ dummy += gsl_signal_exp2 (x);
+ // dummy += exp2f (x);
+ }
+
+ g_print ("%f\r \n", dummy);
+
+ return 0;
+}
+#endif /* coeff generation */
+