#ifndef CMUS_H_LOADED
#define CMUS_H_LOADED

#if defined(HAVE_CONFIG_H)
  #include "config.h"
#endif

#define one_pi 3.141592653589793
#define two_pi 6.283185307179586
#define minus_two_pi -6.283185307179586
#define half_pi 1.5707963267948966
#define three_half_pi 4.71238898038469
#define inverse_pi 0.15915494309189535

#ifndef PI
  #define PI 3.141592653589793
#endif
#ifndef NULL
  #define NULL 0
#endif

#define cl_false (-1)
#define cl_true  1

#define SND_CLM_FIFO "snd_clm_fifo"
#define CLM_SND_FIFO "clm_snd_fifo"

#define ERROR_C 10
#define BREAK_C 11
#define FUNCTION_C 12
#define SIGINT_C 13

/* io file structure reflected in datai */
#define io_fd 0
#define io_chans 1
#define io_size 2
#define io_beg 3
#define io_end 4
#define io_bufsiz 5
#define io_data_start 6
#define io_data_end 7
#define io_open_index 8
#define io_dir 9
#define io_loc 10
#define io_hdr_end 11
#define io_incr 12
#define io_dats 13

#define c_aref_block 0
#define c_aref_type 1
#define c_aref_size 2
#define c_aref_element_size 3
#define c_aref_dims 4
#define c_aref_dim_list_adr 5

#define io_in_f 0
#define io_out_f 1

#define CLM_SHM_KEY 0x00636c6d

void make_sound_file(char *filename, float *data, int len, int srate, int channels);
#ifndef MACOS
  sigfnc *clm_signal(int signo, sigfnc *fnc);
#endif
void clm_file_reset(int loc0, int *io, int *datai);
void clm_full_file_reset(int loc, int *io, int *datai);
void c_newline(void);
void c_init_sine (void);
float c_sin_lookup(float phase);
float c_frandom(float amp);
float c_random(float amp);
void c_srand(int val);
void c_fft_window(float *rl, float *win, int size);
void c_clear_block(float *rl, int size);
void c_blti(int *arr0, int beg, int *arr1, int len);
void c_bltf(float *arr0, int beg, float *arr1, int len);
int c_gcd(int a, int b);
int c_lcm(int a, int b);
float c_table_interp (float *fn, float xx, int len);
float c_table_lookup (int *tbl, float *datar, float fm);
float c_direct_flt (int m, float input, float *flt_a, float *flt_b, float *flt_d);
float c_lattice_flt (int m, float input, float *flt_a, float *flt_b, float *flt_d);
float c_ladder_flt (int m, float input, float so, float *flt_a, float *flt_b, float *flt_c, float *flt_d);
int c_y_or_n_p (void);
int c_yes_or_no_p (void);
void c_fft (float* rl, float* im, int n, int isign, int ipow);
void convolve (float* rl1, float* rl2, int n, int ipow);
void c_env_restart (float *ef, int *ei, float *data);
float c_env (float *ef, int *ei, float *data);
void c_access_env (int val, float *ef, int *ei, float *data);
double jv_exp(double x);
float c_run_block (int *blk, float *fblk, float *buf);
void c_base_run_block (int *blk, float *fblk, float *buf);
float c_readin (int *rd, int *io, int *datai);
float c_src(int *rd, int *rio, int *datai, float *srf, int *sri, float *data, float fm, float *sinc, float *fblk, float *buf);
float c_spd (int *rddat, int *spidat, float *spfdat, int *io, int *datai, float *b, float *fblk, float *buf);
void set_expansion_triggers (int *rddat, int *spidat, float *fblk, float *buf);
void add_one_segment (int *rd, int *spidat, float *spfdat, int *rio, int *datai, float *b, float *buf);
float c_fft_filter (int *rddat, int *io, int *iobufs, int *runblk, float *fblk, int *fftdat,
		    float *runbuf, float *datar, float *datai, float *fenv, float *rfblk, float *rbuf);
void c_convolve (char *fname, 
		 int filec, int filehdr,
		 int filterc, int filterhdr, int filtersize,
		 int start, int fftsize, int ipow, int chans, int chan);
float c_convolve_or_readin (int *rddat, int *io, int *iobufs, int *runblk, float *fblk, int *fftdat,
			    float *runbuf, float *datar, float *datai, float *filtr, int filti, float *rfblk, float *rbuf);
void lpc_out(int order,float *coeffs,float *Zs,float *values);
void lpc_in(int order, int block_size, int hop_size, float *data, float *out_data, float *values);
void load_one_sine (float partial, float amp, float *table, int table_size, float phase);
void initialize_pool (void);
void c_add_pool_open_index (int n);
int c_read_pool_open_index(int *inds);
void finalize_ins (int id);
int c_scheduler_active (void);
void finalize_pool (int outadr, int revadr, int *datai);
void initialize_ins (int beg_sample, int end_sample, int out_adr, int rev_adr,
		     int *datai, int leni, float *datar, int lenr, 
		     int (*loop_function)());

void set_clm_var_table_size (int size);
void allocate_clm_var (int index, int type, int size, int cleared);
int get_clm_var_table_size (void);
int get_int_clm_var (int index, int type);
int get_int_aref_clm_var (int index, int arrind, int type);
int set_int_clm_var (int index, int val, int type);
int set_int_aref_clm_var (int index, int arrind, int val, int type);
float get_float_clm_var (int index, int type);
float get_float_aref_clm_var (int index, int arrind, int type);
float set_float_clm_var (int index, float val, int type);
float set_float_aref_clm_var (int index, int arrind, float val, int type);
void create_sine_table (void);
void make_sines(int length);
void c_fht (int powerOfFour, float *array);
void c_fft_magnitude(float *rl, float *im, int size);
void c_spectrum(float *rdat, float *idat, float *window, int n, int type);
void create_pool (void);
void reset_pool (void);

int c_fasmix(char *ofile, char *ifile, int osample, int isample, int samples, int *channel_matrix, int *datai, float *datar);
void c_mixem (int **obuf, int **ibuf, int obeg, int beg, int oend, int *datai, float *datar, int *channel_matrix, int ochans, int ichans);
void fasmix_read_header(int fd);
void create_fasmix_arrays (void);
int c_find_max_amp(char *ifile, int *vals);

#ifdef MAC_PPC
void mcl_get_float_clm_var (int index, int type, float *df);
void mcl_get_float_aref_clm_var (int index, int arrind, int type, float *df);
void mcl_set_float_clm_var (int index, float *val, int type);
void mcl_set_float_aref_clm_var (int index, int arrind, float *val, int type);
void mcl_clm_output_scaler (float *df);
void mcl_set_clm_output_scaler (float *df);
int c_dax (char *ifile, float *vals, int times);
int record (char *name, int srate, int channels, int line, int bytes);
#endif

/* the connection to Snd and the CLM real-time widgetry depend on too many
 * things to try to handle them automatically via autoconf.  As I port
 * this stuff to other systems, I'll add them here by hand.
 */
/* pipe.c */
#if defined(SGI) || defined(LINUX)
  int write_snd_fifo(char *buf, int len);
  float c_control (int n);
  float c_set_control (int n, float val);
  int c_open_controls (int size);
  void c_close_controls (void);
  int c_control_size(void);
  int c_attach_controls (int size);
  void c_detach_controls (void);
#endif

int c_driving(void);
void c_set_driving(int on);
int temporize_pool (int sample, int out_adr, int rev_adr, int *datai);
int c_fasdax(char *ifile, float start, float end, float srx, float amp, int times, long (*lf)());
int c_pool_active(void);

#endif
