/*---------------------------------------------------------------------------*/
/*
  File: sdsputil.h

  SDSP utilities.
*/
/*---------------------------------------------------------------------------*/

#ifndef SDSPUTIL_H_
#define SDSPUTIL_H_

#ifdef __cplusplus
extern "C" {
#endif
/*---------------------------------------------------------------------------*/
#ifndef _LANGUAGE_ASM

#define SDSP_FRAMER_TYPE_HDLC               0
#define SDSP_FRAMER_TYPE_TRANSPARENT        1
#define SDSP_FRAMER_TYPE_ASYNC              2
#define SDSP_FRAMER_TYPE_COUNT              3

#define SDSP_ASYNC_PARITY_OPTION_NONE       0
#define SDSP_ASYNC_PARITY_OPTION_ODD        1
#define SDSP_ASYNC_PARITY_OPTION_EVEN       2
#define SDSP_ASYNC_PARITY_OPTION_MARK       3
#define SDSP_ASYNC_PARITY_OPTION_SPACE      4

#define SDSP_ASYNC_ONE_STOP_BIT             0
#define SDSP_ASYNC_ONE_POINT_FIVE_STOP_BITS 1
#define SDSP_ASYNC_TWO_STOP_BITS            2


typedef struct complex_short_s
{
  short re;
  short im;
} t_complex_short;

typedef struct sdsp_biquad_coeffs
{
  short b2;
  short b1;
  short b0;
  short a2;
  short a1;
  short d2;
  short d1;
  short d0;
  short c2;
  short c1;
} t_sdsp_biquad_coeffs;

typedef struct sdsp_biquad_vars
{
  short x2;
  short x1;
  short y2;
  short y1;
  short z2;
  short z1;
} t_sdsp_biquad_vars;


extern const byte sdsp_reverse_table[0x100];

#define sdsp_byte_reverse(b) (sdsp_reverse_table[(b)])
#define sdsp_word_reverse(w)\
  (sdsp_reverse_table[(w) >> 8] | (((word)(sdsp_reverse_table[(byte)(w)])) << 8))
#define sdsp_dword_reverse(d)\
  (sdsp_reverse_table[(d) >> 24] |\
   (((word)(sdsp_reverse_table[(byte)((d) >> 16)])) << 8) |\
   (((dword)(sdsp_reverse_table[(byte)((d) >> 8)])) << 16) |\
   (((dword)(sdsp_reverse_table[(byte)(d)])) << 24))

#define SDSP_BYTE_REVERSE(b)\
  ((((b) & 0x01) << 7) | (((b) & 0x02) << 5) | (((b) & 0x04) << 3) | (((b) & 0x08) << 1) |\
   (((b) & 0x10) >> 1) | (((b) & 0x20) >> 3) | (((b) & 0x40) >> 5) | (((b) & 0x80) >> 7))
#define SDSP_WORD_REVERSE(w)\
  ((((w) & 0x0001) << 15) | (((w) & 0x0002) << 13) | (((w) & 0x0004) << 11) | (((w) & 0x0008) << 9)  |\
   (((w) & 0x0010) << 7)  | (((w) & 0x0020) << 5)  | (((w) & 0x0040) << 3)  | (((w) & 0x0080) << 1)  |\
   (((w) & 0x0100) >> 1)  | (((w) & 0x0200) >> 3)  | (((w) & 0x0400) >> 5)  | (((w) & 0x0800) >> 7)  |\
   (((w) & 0x1000) >> 9)  | (((w) & 0x2000) >> 11) | (((w) & 0x4000) >> 13) | (((w) & 0x8000) >> 15))
#define SDSP_DWORD_REVERSE(d)\
  ((((d) & 0x00000001) << 31) | (((d) & 0x00000002) << 29) | (((d) & 0x00000004) << 27) | (((d) & 0x00000008) << 25) |\
   (((d) & 0x00000010) << 23) | (((d) & 0x00000020) << 21) | (((d) & 0x00000040) << 19) | (((d) & 0x00000080) << 17) |\
   (((d) & 0x00000100) << 15) | (((d) & 0x00000200) << 13) | (((d) & 0x00000400) << 11) | (((d) & 0x00000800) << 9)  |\
   (((d) & 0x00001000) << 7)  | (((d) & 0x00002000) << 5)  | (((d) & 0x00004000) << 3)  | (((d) & 0x00008000) << 1)  |\
   (((d) & 0x00010000) >> 1)  | (((d) & 0x00020000) >> 3)  | (((d) & 0x00040000) >> 5)  | (((d) & 0x00080000) >> 7)  |\
   (((d) & 0x00100000) >> 9)  | (((d) & 0x00200000) >> 11) | (((d) & 0x00400000) >> 13) | (((d) & 0x00800000) >> 15) |\
   (((d) & 0x01000000) >> 17) | (((d) & 0x02000000) >> 19) | (((d) & 0x04000000) >> 21) | (((d) & 0x08000000) >> 23) |\
   (((d) & 0x10000000) >> 25) | (((d) & 0x20000000) >> 27) | (((d) & 0x40000000) >> 29) | (((d) & 0x80000000) >> 31))


extern const byte sdsp_trailing_zeroes_table[0x100];

#define sdsp_byte_trailing_zeroes(b) (sdsp_trailing_zeroes_table[(b)])
#define sdsp_word_trailing_zeroes(w)\
  (((w) & 0xff) ? sdsp_trailing_zeroes_table[(w) & 0xff] : sdsp_trailing_zeroes_table[(w) >> 8] + 8)
#define sdsp_dword_trailing_zeroes(d)\
  (((d) & 0x0000ffffL) ?\
    (((d) & 0x000000ffL) ? sdsp_trailing_zeroes_table[(d) & 0xff] : sdsp_trailing_zeroes_table[((d) >> 8) & 0xff] + 8) :\
    (((d) & 0x00ffffffL) ? sdsp_trailing_zeroes_table[((d) >> 16) & 0xff] + 16 : sdsp_trailing_zeroes_table[(d) >> 24] + 24))


extern const byte sdsp_leading_zeroes_table[0x100];

#define sdsp_byte_leading_zeroes(b) (sdsp_leading_zeroes_table[(b)])
#define sdsp_word_leading_zeroes(w)\
  (((w) & 0xff00) ? sdsp_leading_zeroes_table[(w) >> 8] : 8 + sdsp_leading_zeroes_table[(w)])
#define sdsp_dword_leading_zeroes(d)\
  (((d) & 0xffff0000L) ?\
    (((d) & 0xff000000L) ? sdsp_leading_zeroes_table[(d) >> 24] : 8 + sdsp_leading_zeroes_table[(d) >> 16]) :\
    (((d) & 0xff00) ? 16 + sdsp_leading_zeroes_table[(d) >> 8] : 24 + sdsp_leading_zeroes_table[(d)]))


#define SDSP_PARAMETER_EXP_TABLE_WORDS  135
extern const word sdsp_parameter_exp_table[SDSP_PARAMETER_EXP_TABLE_WORDS];

#define sdsp_parameter_exp(x)\
  (((x) >= SDSP_PARAMETER_EXP_TABLE_WORDS - 1) ? 0xffff : sdsp_parameter_exp_table[(x)])

#define sdsp_digital_gain_exp(x)\
  (((x) >= ((SDSP_PARAMETER_EXP_TABLE_WORDS - 1) << 8)) ? 0xffff : sdsp_parameter_exp_table[(byte)((x) >> 8)] +\
   ((word)((((int32)(sdsp_parameter_exp_table[((byte)((x) >> 8)) + 1] - sdsp_parameter_exp_table[(byte)((x) >> 8)])) *\
            ((int32)((x) & 0xff))) >> 8)))

#define SGAUSS_DISTRIBUTE_TABLE_SIZE_EXP 8
#define SGAUSS_DISTRIBUTE_TABLE_SIZE     ((1 << SGAUSS_DISTRIBUTE_TABLE_SIZE_EXP) + 1)
extern const short sgauss_distribute_table[SGAUSS_DISTRIBUTE_TABLE_SIZE];

void sdsp_fill_uniform_noise (short *sample_buffer, word sample_count,
  word level_multiplier, dword *p_random_number_seed);
void sdsp_fill_gaussian_noise (short *sample_buffer, word sample_count,
  word level_multiplier, dword *p_random_number_seed);
void sdsp_biquad (t_sdsp_biquad_vars *p_vars, const t_sdsp_biquad_coeffs *p_coeffs,
  short *in_sample_buffer, short *out_sample_buffer, word sample_count);

short sdsp_sin (word angle);
short sdsp_cos (word angle);
word sdsp_sqrt (dword x);
word sdsp_cbrt (dword hi, word lo);
void sdsp_norm_vector (short re, short im, short *norm_re, short *norm_im);
short sdsp_fir (const short *coefs, const short *buffer, word pos, word size);
short sdsp_fir_half_coefs (const short *coefs, const short *buffer, word pos, word size);
short sdsp_fir_half_plus1_coefs (const short *coefs, const short *buffer, word pos, word size);
int32 sdsp_decimation_fir (const short *coefs, const short *buffer, word pos, word size, word taps, word buffer_step);
int32 sdsp_interpolation_fir (const short *coefs, const short *buffer, word pos, word size, word taps, word coef_step);
void sdsp_demod_fir (const short *coefs, const short *buffer, word pos, word size, int32 *p_re, int32 *p_im);
short sdsp_pitch_fir (const short *coefs_half, const short *buffer, word pos, word size,
  word taps_half, word coef_offs, word coef_step, word gain_compensation);
void sdsp_correlation (const short *buffer1, const short *buffer2, word size, dword *p_res_low, signed char *p_res_high);
int32 sdsp_correlation_32 (const short *buffer1, const short *buffer2, word size);

#endif
/*---------------------------------------------------------------------------*/
#ifdef __cplusplus
}
#endif

#endif

/*---------------------------------------------------------------------------*/
