3 #ifndef SPECTMORPH_MATH_HH
4 #define SPECTMORPH_MATH_HH
11 #include <smmatharm.hh>
14 #include <xmmintrin.h>
36 sm_sincos (
double x,
double *s,
double *c)
74 template<
class Iterator,
int MODE>
76 internal_fast_vector_sin (
const VectorSinParams& params, Iterator begin, Iterator end)
78 g_return_if_fail (params.mix_freq > 0 && params.freq > 0 && params.phase > -99 && params.mag > 0);
80 const double phase_inc = params.freq / params.mix_freq * 2 * M_PI;
81 const double inc_re = cos (phase_inc);
82 const double inc_im = sin (phase_inc);
88 sm_sincos (params.phase, &state_im, &state_re);
89 state_re *= params.mag;
90 state_im *= params.mag;
92 for (Iterator x = begin; x != end; x++)
98 if ((n++ & 255) == 255)
100 sm_sincos (phase_inc * n + params.phase, &state_im, &state_re);
101 state_re *= params.mag;
102 state_im *= params.mag;
110 const double re = state_re * inc_re - state_im * inc_im;
111 const double im = state_re * inc_im + state_im * inc_re;
118 template<
class Iterator,
int MODE>
120 internal_fast_vector_sincos (
const VectorSinParams& params, Iterator sin_begin, Iterator sin_end, Iterator cos_begin)
122 g_return_if_fail (params.mix_freq > 0 && params.freq > 0 && params.phase > -99 && params.mag > 0);
124 const double phase_inc = params.freq / params.mix_freq * 2 * M_PI;
125 const double inc_re = cos (phase_inc);
126 const double inc_im = sin (phase_inc);
132 sm_sincos (params.phase, &state_im, &state_re);
133 state_re *= params.mag;
134 state_im *= params.mag;
136 for (Iterator x = sin_begin, y = cos_begin; x != sin_end; x++, y++)
148 if ((n++ & 255) == 255)
150 sm_sincos (phase_inc * n + params.phase, &state_im, &state_re);
151 state_re *= params.mag;
152 state_im *= params.mag;
160 const double re = state_re * inc_re - state_im * inc_im;
161 const double im = state_re * inc_im + state_im * inc_re;
168 template<
class Iterator>
170 fast_vector_sin (
const VectorSinParams& params, Iterator sin_begin, Iterator sin_end)
174 internal_fast_vector_sin<Iterator, VectorSinParams::ADD> (params, sin_begin, sin_end);
178 internal_fast_vector_sin<Iterator, VectorSinParams::REPLACE> (params, sin_begin, sin_end);
182 g_assert_not_reached();
186 template<
class Iterator>
188 fast_vector_sincos (
const VectorSinParams& params, Iterator sin_begin, Iterator sin_end, Iterator cos_begin)
192 internal_fast_vector_sincos<Iterator, VectorSinParams::ADD> (params, sin_begin, sin_end, cos_begin);
196 internal_fast_vector_sincos<Iterator, VectorSinParams::REPLACE> (params, sin_begin, sin_end, cos_begin);
200 g_assert_not_reached();
210 #if defined(__SSE__) || defined(SM_ARM_SSE)
216 template<
bool NEED_COS,
int MODE>
218 internal_fast_vector_sincosf (
const VectorSinParams& params,
float *sin_begin,
float *sin_end,
float *cos_begin)
220 #if defined(__SSE__) || defined(SM_ARM_SSE)
221 g_return_if_fail (params.mix_freq > 0 && params.freq > 0 && params.phase > -99 && params.mag > 0);
223 const int TABLE_SIZE = 32;
225 const double phase_inc = params.freq / params.mix_freq * 2 * M_PI;
226 const double inc_re16 = cos (phase_inc * TABLE_SIZE * 4);
227 const double inc_im16 = sin (phase_inc * TABLE_SIZE * 4);
233 sm_sincos (params.phase, &state_im, &state_re);
234 state_re *= params.mag;
235 state_im *= params.mag;
237 F4Vector incf_re[TABLE_SIZE];
238 F4Vector incf_im[TABLE_SIZE];
241 VectorSinParams table_params = params;
242 table_params.phase = 0;
243 table_params.mag = 1;
245 fast_vector_sincos (table_params, incf_im[0].f, (
float *) &incf_im[TABLE_SIZE], incf_re[0].f);
248 int todo = sin_end - sin_begin;
249 while (todo >= 4 * TABLE_SIZE)
253 sf_re.f[0] = state_re;
254 sf_re.f[1] = state_re;
255 sf_re.f[2] = state_re;
256 sf_re.f[3] = state_re;
257 sf_im.f[0] = state_im;
258 sf_im.f[1] = state_im;
259 sf_im.f[2] = state_im;
260 sf_im.f[3] = state_im;
268 F4Vector *new_im =
reinterpret_cast<F4Vector *
> (sin_begin + n);
269 F4Vector *new_re = NEED_COS ?
reinterpret_cast<F4Vector *
> (cos_begin + n) :
nullptr;
270 for (
int k = 0; k < TABLE_SIZE; k++)
276 new_re[k].v = _mm_add_ps (new_re[k].v, _mm_sub_ps (_mm_mul_ps (sf_re.v, incf_re[k].v),
277 _mm_mul_ps (sf_im.v, incf_im[k].v)));
279 new_im[k].v = _mm_add_ps (new_im[k].v, _mm_add_ps (_mm_mul_ps (sf_re.v, incf_im[k].v),
280 _mm_mul_ps (sf_im.v, incf_re[k].v)));
286 new_re[k].v = _mm_sub_ps (_mm_mul_ps (sf_re.v, incf_re[k].v),
287 _mm_mul_ps (sf_im.v, incf_im[k].v));
289 new_im[k].v = _mm_add_ps (_mm_mul_ps (sf_re.v, incf_im[k].v),
290 _mm_mul_ps (sf_im.v, incf_re[k].v));
300 const double re = state_re * inc_re16 - state_im * inc_im16;
301 const double im = state_re * inc_im16 + state_im * inc_re16;
305 todo -= 4 * TABLE_SIZE;
309 VectorSinParams rest_params = params;
310 rest_params.phase += n * phase_inc;
312 fast_vector_sincos (rest_params, sin_begin + n, sin_end, cos_begin + n);
314 fast_vector_sin (rest_params, sin_begin + n, sin_end);
317 fast_vector_sincos (params, sin_begin, sin_end, cos_begin);
319 fast_vector_sin (params, sin_begin, sin_end);
324 fast_vector_sincosf (
const VectorSinParams& params,
float *sin_begin,
float *sin_end,
float *cos_begin)
328 internal_fast_vector_sincosf<true, VectorSinParams::ADD> (params, sin_begin, sin_end, cos_begin);
332 internal_fast_vector_sincosf<true, VectorSinParams::REPLACE> (params, sin_begin, sin_end, cos_begin);
336 g_assert_not_reached();
341 fast_vector_sinf (
const VectorSinParams& params,
float *sin_begin,
float *sin_end)
345 internal_fast_vector_sincosf<false, VectorSinParams::ADD> (params, sin_begin, sin_end, NULL);
349 internal_fast_vector_sincosf<false, VectorSinParams::REPLACE> (params, sin_begin, sin_end, NULL);
353 g_assert_not_reached();
358 zero_float_block (
size_t n_values,
float *values)
360 memset (values, 0, n_values *
sizeof (
float));
366 extern float *int_sincos_table;
368 return int_sincos_table[i];
374 extern float *int_sincos_table;
377 return int_sincos_table[i];
383 extern float *int_sincos_table;
385 int_sincos_table = (
float *) malloc (
sizeof (
float) * 256);
386 for (
int i = 0; i < 256; i++)
387 int_sincos_table[i] = sin (
double (i / 256.0) * 2 * M_PI);
393 window_cos (
double x)
397 return 0.5 * cos (x * M_PI) + 0.5;
401 window_hamming (
double x)
406 return 0.54 + 0.46 * cos (M_PI * x);
410 window_blackman (
double x)
414 return 0.42 + 0.5 * cos (M_PI * x) + 0.08 * cos (2.0 * M_PI * x);
418 window_blackman_harris_92 (
double x)
423 const double a0 = 0.35875, a1 = 0.48829, a2 = 0.14128, a3 = 0.01168;
425 return a0 + a1 * cos (M_PI * x) + a2 * cos (2.0 * M_PI * x) + a3 * cos (3.0 * M_PI * x);
429 double db_to_factor (
double dB);
430 double db_from_factor (
double factor,
double min_dB);
432 #if defined (__i386__) && defined (__GNUC__)
433 static inline int G_GNUC_CONST
443 static inline int G_GNUC_CONST
454 sm_round_positive (
double d)
460 sm_round_positive (
float f)
466 sm_round_positive (
double d)
468 return int (d + 0.5);
472 sm_round_positive (
float f)
474 return int (f + 0.5f);
478 int sm_fpu_okround();
482 static float idb2f_high[256];
483 static float idb2f_low[256];
485 static float ifreq2f_high[256];
486 static float ifreq2f_low[256];
489 #define SM_IDB_CONST_M96 uint16_t ((512 - 96) * 64)
491 int sm_factor2delta_idb (
double factor);
492 double sm_idb2factor_slow (uint16_t idb);
496 uint16_t sm_freq2ifreq (
double freq);
497 double sm_ifreq2freq_slow (uint16_t ifreq);
500 sm_idb2factor (uint16_t idb)
502 return MathTables::idb2f_high[idb >> 8] * MathTables::idb2f_low[idb & 0xff];
506 sm_ifreq2freq (uint16_t ifreq)
508 return MathTables::ifreq2f_high[ifreq >> 8] * MathTables::ifreq2f_low[ifreq & 0xff];
512 sm_factor2idb (
double factor)
520 const double db = 20 * log10 (std::max (factor, 1e-25));
522 return sm_round_positive (db * 64 + 512 * 64);
525 double sm_lowpass1_factor (
double mix_freq,
double freq);
526 double sm_xparam (
double x,
double slope);
527 double sm_xparam_inv (
double x,
double slope);
528 float sm_freq_to_note (
float freq);
530 double sm_bessel_i0 (
double x);
531 double velocity_to_gain (
double velocity,
double vrange_db);
536 sm_bound (
const T& min_value,
const T& value,
const T& max_value)
538 return std::min (std::max (value, min_value), max_value);
543 sm_clamp (
const T& value,
const T& min_value,
const T& max_value)
545 return std::min (std::max (value, min_value), max_value);
Definition: smmath.hh:481
parameter structure for the various optimized vector sine functions
Definition: smmath.hh:52
double mag
the magnitude (amplitude) of the wave
Definition: smmath.hh:56
double mix_freq
the mix freq (sampling rate) of the sin (and cos) wave to be created
Definition: smmath.hh:53
double phase
the start phase of the wave
Definition: smmath.hh:55
@ REPLACE
replace values in the output array with computed values
Definition: smmath.hh:61
@ ADD
add computed values to the values that are in the output array
Definition: smmath.hh:60
double freq
the frequency of the sin (and cos) wave to be created
Definition: smmath.hh:54