/* the "__" names are forward references used only in this file to avoid void* */
/* around 500 of the 750 or so global functions declared here and in snd-x1.h */
/* are actually only called in one other file than the one they're defined in, */
/* but I'd rather sacrifice modularity than try to keep track of a bunch of headers. */


#ifndef SND_1_H_LOADED
#define SND_1_H_LOADED

typedef struct {int op; void *op0; void *op1; float fval; int type;} sop;

typedef struct {
  int s_type;
  int size;
  int *fragments;
} ed_list;

typedef struct {
  int samps_per_bin; 
  int amp_env_size;
  int amp_ctr;
  int *data_max; 
  int *data_min;
} env_info;

typedef struct {
  int s_type;             /* run-time pointer type checks */
  char *name;             /* full name */
  int samples;            /* total samples = chans * samples/chan */
  int data_location;      /* bytes */
  int srate;
  int chans;
  int format;             /* data format (snd_16_linear etc) */
  int type;               /* header type (AIFF etc) */
  int distributed;        /* is header scattered around (1) or in one place (0) */
  int comment_start;      /* comment location (bytes) */
  int comment_end;
  int depth;              /* directory depth from top dir */
} file_info;

typedef struct {
  int s_type;
  int type;
  int *data;    
  int *io;      
  char *filename;
  file_info *hdr;
  int temporary;
  int edit_ctr;
  int open;
  int inuse;
  int copy;
} snd_data;

typedef struct {
  int s_type;
  ed_list *current_state;
  int *cb;
  int cbi;
  int eof;
  int *first;
  int *last;
  int *data;
  snd_data **sounds;
  snd_data *current_sound;
  int current_value;
  int beg,end;
  int direction;
  struct chan__info *cp;
} snd_fd;

extern snd_fd *snd_search_fd;
extern int snd_IO_error;

typedef struct {float freq; float amp;} fft_peak;

typedef struct {
  int s_type;
  float y0,y1;                         /* scroller-dependent axis bounds */
  double x0,x1;
  float xmin,xmax,ymin,ymax;           /* data-dependent absolute limits */
  float y_scale;
  double x_scale;
  char *xlabel,*ylabel;
  int y_label_x,y_label_y,x_label_x,x_label_y;
  int y_axis_x0,x_axis_x0,
      y_axis_y0,x_axis_y0,
      x_axis_x1,
      y_axis_y1;
  int graph_active;
  int losamp,hisamp;                   /* displayed x-axis bounds in terms of sound sample numbers */
  int graph_x0;                        /* x axis offset relative to window (for double graphs) */
  void *x_ticks,*y_ticks;              /* actual type is tick_descriptor local to snd-axis.c */
  axis_context *ax;
  int width,height;
  struct snd__state *ss;               /* back pointers for debugging and whatnot */
  struct chan__info *cp;
  float sx,sy,zx,zy;                   /* as set by user, 0.0 - 1.0 */
  int y_offset,window_width;
  int no_data;
} axis_info;

typedef struct {
  int samp;
  char *name;
  int visible;
} mark;

typedef struct {
  float *data;
  int pts,data_size;
} env;

typedef struct {
  unsigned int s_type;
  int size;
  int current_size;
  int window;              /* fft window in this case, not a display window */
  int ok;
  float beta;
  axis_info *axis;
  float *data;
  struct chan__info *chan;
} fft_info;

typedef struct {
  int s_type;
  int n;
  void *r;
  void *dp;
  struct snd__state *ss;
  void *rg;
} region_info;

typedef struct {
  int total_slices;        /* size of the data array (max for allocation checks) */
  int total_bins;          /* size other axis data array */
  int active_slices;       /* how many slices contain current data */
  int target_bins;         /* this many bins Y-side */
  int target_slices;       /* how many slices in full display (current) */
  float **data;            /* data[total_slices][bins] -> each is a spectral magnitude */
  int *begs;               /* associated begin times (for data reuse) */
  struct chan__info *cp;
  float scale;
} sono_info;

typedef struct chan__info {
  unsigned int s_type;     /* CHAN_INFO */
  int chan;                /* which chan are we */
  int *samples;            /* current length */
  int ffting;              /* f button state */
  int waving;              /* w button state */
  int ufuning;             /* external function display state */
  void *ui;
  int cursor_on;           /* channel's cursor */
  int cursor_visible;      /* for XOR decisions */
  int border_visible;
  int cursor;              /* sample */
  int cx,cy;               /* graph-relative cursor loc (for XOR) */
  int edit_ctr;            /* channel's edit history */
  int edit_size;           /* current edit list size */
  ed_list **edits;         /* the edit list */
  int sound_size;          /* edit_list associated temp sound buffers */
  int sound_ctr;           /* current location in sounds list */
  snd_data **sounds;       /* the associated temp buffer/file/struct list */
  fft_info *fft;           /* possibly null fft data */
  struct snd__info *sound;
  struct snd__state *state;
  axis_info *axis,*active_axis;
  mark ***marks;           /* current marks, indexed by edit_ctr, then mark_number, then the mark pointer */
  int marks_size;
  int *mark_size;
  int *mark_ctr;
  chan_context *cgx;       /* graphics/window context */
  chan_context *tcgx;      /* when combining chans, all should use chan[0]'s context */
  void *amp_env;
  void *original_env;
  void *sonogram_data;
  void *last_sonogram;
  void *fft_data;          /* parallels sonogram -- try to avoid repeating large ffts needlessly */
  int clear;
  int ps_fd;
  int printing;
  int drawing;
  float gsy,gzy;
  void *mixes;
  void *mix_dragging;
  int height;
  int original_cursor;
} chan_info;

typedef struct snd__info {
  unsigned int s_type;
  int inuse;
  int index;
  void *playing;
  mark *playing_mark;
  int syncing;
  int expanding;
  int contrasting;
  int reverbing;
  int filtering;
  int recording,replaying,applying;
  float amp;
  float srate;                  /* playback srate, not original */
  int last_srate,last_amp,last_expand,last_contrast,last_revlen,last_revscl;
  float expand,exp_seglen,exp_ramp,exp_hop;
  float contrast;
  float revlen,revscl,revfb,revlp;
  int filter_order;
  env *filter_env;
  int filter_is_envelope;
  int play_direction;
  int selected_channel;
  char *fullname;
  char *shortname;
  int nchans;
  sop *search_tree;
  char *search_expr;
  int searching,marking,evaling,filing,finding_mark,amping,reging,printing,loading,ufuning,macroing,grouping;
  sop *eval_tree;
  char *eval_expr;
  float *ufun_args;
  int ufun_nargs;
  void *ufunp;
  int auto_ufun;
  int minibuffer_on;
  int sx_scroll_max;
  int info_active;
  int read_only;
  chan_info **chans;
  struct snd__state *state;
  snd_context *sgx;
  file_info *hdr;             /* header of file that would be affected if we were to save current edits */
  void *actions;
  void *initial_controls;
  int env_anew;
  int apply_ok;
  float contrast_amp;
  time_t write_date;          /* check for change behind back while editing */
  int need_update;            /* current in-core data does not match actual file (someone wrote it behind our back) */
  char **debug_names;
  float *debug_amps;
  int combining;              /* 0:separate panes per chan, 1:all chans in one pane */
  int allocated_chans;        /* snd_info widget tree is never pruned -- can only grow */
  int cursor_follows_play;
} snd_info;

typedef struct snd__state {
  unsigned int s_type;        /* SND_STATE */
  int selected_sound;         /* NO_SELECTION = none selected = which sound is currently receiving user's attention */
  int active_sounds;
  int global_fft_size;
  int global_fft_window;
  int subsampling;
  int dBing;
  int logxing;
  int fft_style;
  int marks_visible;
  int zero_visible;
  int cursor_talks;
  int graph_style;
  int peaking;
  int viewing;
  int ctrls_height,channel_min_height; /* for user-customized start up decisions */
  int from_clm, to_clm, from_snd, clm_selectable; /* fifos for IPC (X window properties are a nightmare) */
  snd_info **sounds;
  sop *search_tree;
  char *search_expr;
  sop *eval_tree;
  char *eval_expr;
  int using_schemes;
  state_context *sgx;
  int editor_line_size;
  int place_scroll_size;
  void *help_monolog;
  char *init_file;
  char *backup_file;
  char *eps_file;
  int max_sounds;
  float color_scale;
  int color_inverted;
  float sonogram_cutoff;
  char *temp_dir;
  int play_start_time;
  float reverb_decay;
  int default_output_type;
  snd_info *mx_sp;
  int remember_state;
  char *pending_open;
  char *pending_change;
  char *pending_new;
  int auto_open;
  int fit_data;
  int global_combining;
  int consoling;
  int dot_size;
  int zoom_focus_anchor;
  int spectro_hop,wavo_hop,wavo,spectrogram_color,sonogram_color,wavo_trace;
  float spectro_xscl,spectro_yscl,spectro_zscl,spectro_zangle,spectro_xangle,spectro_yangle,color_cutoff;
  int ask_before_overwrite;
  int x_axis_style;
  int speed_style,speed_tones;
  float gexp_seglen,gexp_ramp,gexp_hop;
  float grevfb,grevlp;
  float initx0,initx1,inity0,inity1,xmin,xmax,ymin,ymax;
  char *session_name;
  int normalize_fft,zero_pad,ngroups,movies,mix_duration_brackets;
  int window_width,window_height;
  int filter_env_order;  /* for spectral envelopes from the envelope editor */
  int record_chans,record_srate,record_type,record_format,record_line_panel,record_mic_panel,
      record_out_panel,record_autoload,record_digital;
  int print_choice;
  float *record_amps;
  void *rec;
  int auto_resize,sinc_width,stopped_explicitly,checking_explicitly,env_graphing;
  int transform_type,wavelet_choice;
  /* there are 3 state/customization/initialization files --
   * init_file = .snd on home directory and contains customizations used all the time
   *             the options menu save-options choice appends to this file.
   * backup_file = .snd-backup on current directory and contains enough to restart current run in case of crash
   *               the backup file is deleted upon normal exit except when remember-state is non-zero.
   * session_name = <name>.snd-session and contains all state needed to restart later in same state
   *                several sessions can exist, this is independent of exit state and so on.
   * the init_file is loaded first, followed by either the session file (if it is specified) or the backup file (if it exists)
   */
} snd_state;

typedef struct {
  char **files;
  char *name;
  int len;
  int size;
} dir;

typedef struct {int srate; int channels; int slice; snd_state *ss;} dac_manager;

typedef struct {
  int chans;
  int *begs;
  chan_info **cps;
} sync_info;

typedef struct {
  int len;
  int *save;
  char **name;
} region_state;

typedef struct {         /* save one mix console state */
  int chans;             /* size of arrays in this struct */
  int edit_ctr;          /* cp edit_ctr at time of creation of this struct */
  int beg,end,orig,len;  /* samp positions in output (orig=where edit tree thinks it is) */
  int locked;            /* true if current mix cannot be changed until undo rewinds past us */
  int groups;
  int syncable;          /* are we an active member of a sync chain */
  float *scalers,*old_scalers,*scl_scalers;
  float speed,scl_speed;
  int old_speed;
  void *gs_amp_env;
  float gs_amp,gs_speed,gs_tempo;
} console_state;

typedef struct {
  int loc;                     /* our position in pool */
  snd_state *ss;
  chan_info *cp;
  mix_context *wg;             /* chan-graph (parent of widgets) */
  char *name;                  /* short name of input file/selection(?) */
  mixmark *mixer;              /* widgets */
  char *in_filename,*out_filename;
  int in_chans,in_samps;       /* in_samps needed to simplify speed changed duration calculations */
  int console_state_size;      /* current size of console_state list */
  console_state **states;      /* list of mixer states */
  console_state *current_cs;
  int anchor,orig_beg;         /* sample in in-data of console attachment */
  int curcons;
  int temporary;               /* in-filename was written by us and needs to be deleted when mix console is deleted */
  int out_temp;                /* out_file written as clm explode option, also needs deletion */
  snd_info *sub_snd,*add_snd;  /* readable snd_info structs for mix input */
                               /* two are needed to keep clm_file_reset buffer boundaries clean */
  int state,changed,out_chan,width,height,beg_in_samps,main_chan,sweep_tag;
  /* beg_in_samps = mix title time display choice (seconds or samples) */
  void *sync_out,*sync_back;
  int *rows;
} mixdata;

typedef struct {
  int widget_size;
  mixmark **widget_pool;
  int mix_size;
  mixdata **mix_pool;
} mix_state;

typedef struct {
  int active,chans,group,mixes,mix_size,unreadies;
  float speed,scl_speed,tempo,beg,end,old_tempo;
  int old_speed;
  float *amps,*old_amps;
  env *speed_env,*tempo_env;
  env **amp_envs;
  int playing,env_entire;
  mixdata **mds;
  chan_info **cps,**old_cps;
  mix_context **wgs;
  char **tempfile;
  snd_info **play_sps;
  char **env_strs;
} grp_info;

typedef struct {
  float x;
  float incr;
  int width;
  int len;
  float *data;
  snd_fd *sf;
  int sample;
} src_state;



char *get_graph_help(void);
char *get_file_menu_help(void);
char *get_edit_menu_help(void);
char *get_view_menu_help(void);
char *get_options_menu_help(void);
char *get_help_menu_help(void);
char *get_about_snd_help(void);
char *get_fft_menu_help(void);
char *get_fft_keypad_help(void);
char *get_find_menu_help(void);
char *get_undo_menu_help(void);
char *get_sync_menu_help(void);
char *get_speed_menu_help(void);
char *get_expand_menu_help(void);
char *get_reverb_menu_help(void);
char *get_contrast_menu_help(void);
char *get_env_menu_help(void);
char *get_format_menu_help(void);
char *get_info_help(void);
char *get_play_help(void);
char *get_mark_help(void);
char *get_mixing_help(void);
char *get_grouping_help(void);
char *get_init_file_help(void);
char *get_resource_help(void);
char *get_region_browser_help(void);
char *get_ufun_help(void);
char *get_expression_help(void);
char *get_recording_help(void);
char *get_envelope_editor_help(void);

sop *sop_parse(char *expr);
void free_sop(sop *tree);
float sop_eval(sop *tree);
char *sop_parse_error_name(void);
int sop_error(void);
void sop_add_id(char *name);
void sop_add_snd_id(char *name, int type);
float search_dot(int off);
float search_dot_assign(int off,float val);
int scan_tree_for_yn(sop *eval_tree);
float sop_yn(int chan, int off);
snd_fd **get_chans_needed_by_eval(snd_state *ss, chan_info *cp, sop *eval_tree, int start, int direction);
void next_samples_for_eval(snd_fd **afs);
void previous_samples_for_eval(snd_fd **afs);
void free_chans_for_eval(snd_fd **afs);

void save_parser_state (snd_state *ss, int fd);
void save_ufun_state(snd_state *ss, int fd);

int output_type_and_format_ok(int type, int format);
char *sound_type(int type);
char *sound_format (int format);
char *copy_string (char *str);
int round(float x);
void snd_error (char *msg);
char *filename_without_home_directory(char *name);
char *just_filename(char *name);
#ifndef sqr
  float sqr(float a);
#endif
float cube (float a);
char *prettyf(float num, int tens);

char *complete_filename(char *tok);
void snd_file_reset(snd_state *ss, snd_data *sd, int index);
int snd_open_read(snd_state *ss, char *arg);
int snd_open_write(snd_state *ss, char *arg);
int snd_create(snd_state *ss, char *arg);
int snd_reopen_write(snd_state *ss, char *arg);
void snd_close(int fd);
int snd_write_header(snd_state *ss, char *name, int type, int srate, int chans, int loc, int size, int format, char *comment, int len);

int snd_pointer_type(void *w);
void snd_pointer_error (char *msg, int good, void *w);
unsigned int make_snd_pointer_type (int type);


int find_and_sort_fft_peaks(float *buf, fft_peak *found, int num_peaks, int fftsize, int srate, float samps_per_pixel);
int find_and_sort_peaks(float *buf, fft_peak *found, int num_peaks, int size);
int fft_window_needs_beta (int window);
void fft_set_current_window_beta(float beta, int window);
float fft_window_beta(int window);
float fft_window_beta_max(int window);
int fftwincpy(char *s1, int type);
Boolean fft_in_slices(void *fftData);
Boolean sonogram_in_slices(void *sono);
fft_info *free_fft_info(fft_info *fp);
void *make_fft_state(chan_info *cp, int simple);
int default_fft_window(snd_state *ss);
void free_sono_info (chan_info *cp);
void make_sonogram_axes(chan_info *cp);
void *make_sonogram_state(chan_info *cp);
void set_sonogram_cutoff(snd_state *ss,float val);
float set_global_fft_size(snd_state *ss,float val);
void display_fft_peaks(chan_info *cp);

axis_info *free_axis_info(axis_info *ap);
short grf_x(double val, axis_info *ap);
short grf_y(float val, axis_info *ap);
void make_axes_1(chan_info *cp, axis_info *ap, int x_style, int srate);
double ungrf_x(axis_info *ap, int x);
float ungrf_y(axis_info *ap, int y);
axis_info *make_axis_info (chan_info *cp, float xmin, float xmax, float ymin, float ymax, 
			   char *xlabel, float x0, float x1, float y0, float y1,
			   axis_info *old_ap);
void set_y_limits(chan_info *cp, axis_info *ap, float val);
void set_xy_bounds(chan_info *cp,axis_info *ap);
void set_x_bounds(axis_info *ap);

mark *add_mark(int samp, char *name, chan_info *cp);
void free_mark_list(chan_info *cp, int ignore);
void collapse_marks (snd_info *sp);
void delete_mark(int samp, chan_info *cp);
void draw_mark(chan_info *cp, axis_info *ap, mark *mp);
mark *hit_mark(chan_info *cp, int x, int y);
void move_mark(chan_info *cp, mark *mp, int x, int y);
void finish_moving_mark(chan_info *cp, mark *mp);
mark *hit_triangle(chan_info *cp, int x, int y);
void ripple_marks(chan_info *cp, int beg, int change);
void marks_off(chan_info *cp);
void release_pending_marks(chan_info *cp, int edit_ctr);
int goto_mark(chan_info *cp,int count);
int goto_named_mark(chan_info *cp, char *name);
int add_named_mark(chan_info *cp);
void move_mark_2(chan_info *cp);
mark *find_named_mark(chan_info *cp, char *name);
int move_play_mark(chan_info *cp, int *mc, int cx);
void finish_moving_play_mark(chan_info *cp);
void save_marks(snd_info *sp);
void clm_add_marks(snd_info *sp);

char *snd_error_name(int i);
snd_info *snd_open_file (char *filename, snd_state *ss);
void snd_close_file(snd_info *sp,snd_state *ss);
int disk_kspace (int fd);
time_t file_write_date(char *filename);
int snd_ok (snd_info *sp);
int snd_checked_write(snd_state *ss, int fd, unsigned char *buf, int bytes);
int copy_file(char *oldname, char *newname, snd_info *sp);
int snd_translate(snd_state *ss, char *oldname, char *newname);
void snd_update(snd_state *ss, snd_info *sp);
snd_info *snd_update_1(snd_state *ss, snd_info *sp, char *filename);

enum {snd_no_error,snd_cannot_write_header,snd_cannot_open_temp_file,
      snd_cannot_allocate_io_buffers,snd_cannot_write_data,
      snd_cannot_remove_file,snd_cannot_rename_file,
      snd_cannot_read_header,snd_unsupported_file_type,
      snd_cannot_find_file,snd_unsupported_data_format,
      snd_pending_open};

file_info *make_file_info(char *fullname,snd_state *ss);
file_info *make_file_info_1(char *fullname, snd_state *ss);
file_info *free_file_info(file_info *hdr);
file_info *make_temp_header(char *fullname, file_info *old_hdr, int samples);
int *make_file_state(int fd, file_info *hdr, int direction, int chan, int suggested_bufsize);
int *free_file_state(int *datai);
dir *filter_sound_files(dir *dp, char *pattern);
dir *find_sound_files_in_dir (char *name);
dir *find_session_files_in_dir (char *name);
dir *free_dir (dir *dp);
int open_temp_file(char *ofile, int chans, file_info *hdr, snd_state *ss);
int close_temp_file(int ofd, file_info *hdr, long bytes, snd_info *sp);
void file_change_samples(int beg, int num, char *tempfile, chan_info *cp, int chan, int auto_delete, int lock);
void file_insert_samples(int beg, int num, char *tempfile, chan_info *cp, int chan, int auto_delete);
void file_override_samples(int num, char *tempfile, chan_info *cp, int chan, int auto_delete, int lock);
int *load_samples(int beg, int num, chan_info *cp);

void free_edit_list(chan_info *cp);
void free_sound_list (chan_info *cp);
int current_ed_samples(chan_info *cp);
void insert_samples(int beg, int num, int *vals, chan_info *cp);
void delete_samples(int beg, int num, chan_info *cp);
void change_samples(int beg, int num, int *vals, chan_info *cp, int lock);
float sample (int samp, chan_info *cp);
snd_fd *free_snd_fd(snd_fd *sf);
snd_fd *init_sample_read (int samp, chan_info *cp, int direction);
float any_sample(snd_fd *sf, int off);
int next_sound (snd_fd *sf);
int previous_sound (snd_fd *sf);
int next_sub_sound (snd_fd *sf, int inc);
float next_sample (snd_fd *sf);
float previous_sample (snd_fd *sf);
int read_sample_eof (snd_fd *sf);
snd_data *make_snd_data_file(char *name, int *io, int *data, file_info *hdr, int temp, int ctr);
snd_data *make_snd_data_buffer(int *data, int len, int ctr);
ed_list *initial_ed_list(int beg, int end);
int next_sample_1 (snd_fd *sf);
int previous_sample_1(snd_fd *sf);
void undo_EDIT(void *ptr, int count);
void redo_EDIT(void *ptr,int count);
void undo_edit(chan_info *cp, int count);

#define NEXT_SAMPLE(val,sf)  {if (sf->data > sf->last) val=next_sound(sf); else val=(*sf->data++);}
#define NEXT_SUB_SAMPLE(val,sf,inc) {if ((int *)(sf->data+inc) > sf->last) val=next_sub_sound(sf,inc); else {val=(*sf->data); sf->data+=inc;}}
#define PREVIOUS_SAMPLE(val,sf)  {if (sf->data < sf->first) val=previous_sound(sf); else val=(*sf->data--);}

int chan_save_edits(chan_info *cp, char *ofile);
int save_edits(snd_info *sp, void *ptr);
int revert_edits(chan_info *cp, void *ptr);
char *only_save_edits(snd_info *sp, file_info *nhdr, int *err);

snd_info *make_snd_info(snd_info *sip, snd_state *state, char *filename, file_info *hdr, int snd_slot);
snd_info *free_snd_info(snd_info *sp);
chan_info *make_chan_info(chan_info *cip, int chan, snd_info *sound, snd_state *state);
int map_over_sounds (snd_state *ss, int (*func)(snd_info *,void *), void *userptr);
int map_over_chans (snd_state *ss, int (*func)(chan_info *,void *), void *userptr);
int map_over_sound_chans (snd_info *sp, int (*func)(chan_info *,void *), void *userptr);
int map_over_separate_chans(snd_state *ss, int (*func)(chan_info *,void *), void *userptr);
char *snd_NAME(void *w);
int snd_SRATE (void *ptr);
int snd_TYPE (void *ptr);
int graph_low_SAMPLE (void *ptr);
int graph_high_SAMPLE (void *ptr);
int active_channels (snd_state *ss,int count_virtual_channels);
int find_free_sound_slot (snd_state *state);
snd_info *selected_sound(snd_state *ss);
int incf_active_sounds (snd_state *ss);
int decf_active_sounds (snd_state *ss);
snd_state *main_STATE(void *w);

void report_in_minibuffer(snd_info *sp, char *message);
void append_to_minibuffer(snd_info *sp, char *message);
void clear_minibuffer(snd_info *sp);
void reflect_file_revert_in_label (snd_info *sp);

snd_info *add_sound_window (char *filename, snd_state *state);
void add_sound_data(char *filename, snd_info *sp, snd_state *ss);
void add_channel_data(char *filename, chan_info *cp, file_info *hdr, snd_state *ss);
void add_channel_data_1(chan_info *cp, snd_info *sp, snd_state *ss, int graphed);

void check_for_first_edit(chan_info *cp);
void handle_cursor(chan_info *cp, int redisplay);
void normalize_all_sounds(snd_state *ss);
void select_channel(snd_info *sp, int chan);
void unselect_channel(void *ptr);
chan_info *selected_channel(void *ptr);
snd_info *any_selected_sound (snd_state *ss);
chan_info *any_selected_channel(snd_info *sp);
int syncd_chans(snd_state *ss);
chan_info *current_channel(void *ptr);
void select_sound (snd_state *ss, snd_info *sp);
int active_selection (chan_info *cp);
chan_info *virtual_selected_channel(chan_info *cp);


int feed_dac(dac_manager *tm);
int dac_is_running(void);
void close_dac (void);
void write_dac(short *buf, int samps, int cadr);
void start_playing(void *ptr, int start);
void stop_playing(void *dp);


void display_channel_data (chan_info *cp, snd_info *sp, snd_state *ss);
void display_channel_marks (chan_info *cp);
void draw_graph_cursor(chan_info *cp);
void show_cursor_info(chan_info *cp);
int update_graph(chan_info *cp, void *ptr);
void apply_x_axis_change(axis_info *ap, chan_info *cp, snd_info *sp);
void sy_changed(int value,chan_info *cp);
void sx_changed(int value,chan_info *cp);
void zy_changed(int value,chan_info *cp);
void zx_changed(int value,chan_info *cp);
void sx_incremented(chan_info *cp, float amount);
void resize_sx(chan_info *cp);
void resize_zx(chan_info *cp);
int move_axis(chan_info *cp, axis_info *ap, int x);
void set_axes(chan_info *cp,float x0,float x1,float y0,float y1);
void gzy_changed(int value,chan_info *cp);
void gsy_changed(int value,chan_info *cp);


int cursor_search(chan_info *cp, int count);
char *global_search(snd_state *ss);

void snd_info_activate(snd_info *sp, int keysym);
void snd_add_locals (snd_state *ss);
float get_snd_var(int var);
float set_snd_var(int var, float val);
void save_snd_options (snd_state *ss);
int open_snd_init_file (snd_state *ss);

int cursor_moveto (chan_info *cp,int samp);
int keyboard_command (chan_info *cp, int keysym, int state);

void load_macro(char *name, char *macdef, int start, int end);
void save_macros(snd_state *ss);
void save_macro(snd_state *ss,char *name);
int execute_macro(chan_info *cp, char *name, int count);
void save_macro_state (snd_state *ss, int fd);

void snd_load_init_file(snd_state *ss);
int get_clm_string(snd_state *ss, int fd);
int snd_load_file(snd_state *ss,char *filename);
void snd_exit_cleanly(snd_state *ss);
void save_snd_state (snd_state *ss);
void restore_state(snd_state *ss, char *file);
void remove_backup_file(snd_state *ss);

void snd_help(snd_state *ss, char *subject, char *help);
void ssnd_help(snd_state *ss, char *subject, ...);

int run_amp_env(snd_info *sp);
int amp_env_usable(chan_info *cp,float samples_per_pixel);
int amp_env_graph(chan_info *cp, axis_info *ap, float samples_per_pixel, int srate);
void clobber_amp_env(chan_info *cp);

env *copy_env(env *e);
env *free_env(env *e);
env *scan_envelope_and_report_error(snd_info *sp, char *str, int *err);

void init_regions(void);
int region_chans(int n);
snd_info *region_sound(int n);
int selection_is_ours(void);
int selection_len(void);
int selection_beg(chan_info *cp);
int *send_selection(snd_state *ss);
int *send_region(snd_state *ss, int n);
void receive_selection(int *data, int len);
void give_up_selection(void);
void delete_selection(void);
void paste_region(int n, chan_info *cp);
void add_region(int n, chan_info *cp);
void display_selection(chan_info *cp);
void play_region(snd_state *ss,int n, void *r);
void define_selection(chan_info *cp);
void create_selection(chan_info *cp);
void selection_off(chan_info *cp);
int selection_member(snd_info *sp);
void define_region(chan_info *cp, int beg, int end);
void mark_define_region(chan_info *cp,int count);
int region_len(int n);
int region_srate(int n);
float region_maxamp(int n);
snd_fd *init_region_read (snd_state *ss, int n, int chan, int direction);
void start_selection (chan_info *cp,int x);
void select_region(int n);
int delete_region(int n);
void free_region_state (region_state *r);
region_state *region_report(void);
void protect_region(int n,int protect);
void ripple_selection(chan_info *cp, int beg, int num);
void start_keyboard_selection(chan_info *cp, int x);
void finish_keyboard_selection(void);
int cancel_keyboard_selection(void);
void check_keyboard_selection(chan_info *cp, int x);
void cleanup_region_temp_files(void);
void deactivate_selection(void);
file_info *fixup_region_data(chan_info *cp, int chan, int n);
int save_region(snd_state *ss, int n, char *ofile);

void free_chan_env(chan_info *cp);
void free_sound_env(snd_info *sp, int in_progress);
env *make_envelope(float *env_buffer, int len);

void free_sync_info (sync_info *si);
sync_info *region_sync(int n);
sync_info *snd_sync(snd_state *ss);
sync_info *make_simple_sync (chan_info *cp, int beg);


void ps_set_grf_points(double x, int j, float ymin, float ymax);
void ps_set_grf_point(double x, int j, float y);
void ps_allocate_grf_points(void);
void ps_draw_grf_points(snd_state *ss,chan_info *cp, axis_info *ap, int j);
void ps_draw_both_grf_points(snd_state *ss,chan_info *cp, axis_info *ap, int j);
void ps_draw_line (chan_info *cp, int x0,int y0,int x1,int y1);
void ps_fill_rectangle (chan_info *cp, int x0, int y0, int width, int height);
void ps_draw_string (chan_info *cp, int x0, int y0, char *str);
void ps_set_number_font(chan_info *cp);
void ps_set_label_font(chan_info *cp);
void ps_set_bold_peak_numbers_font(chan_info *cp);
void ps_set_peak_numbers_font(chan_info *cp);
void ps_draw_sono_rectangle(chan_info *cp, axis_info *ap, int color, float x, float y, float width, float height);
void ps_reset_color(chan_info *cp);
int set_dot_size(snd_state *ss, int val);
void ps_draw_spectro_line(chan_info *cp, int color, float x0, float y0, float x1, float y1);

void snd_print(snd_state *ss, char *output, int syncing);
void region_print(char *output, char* title, chan_info *cp);

int invoke_ufun_with_ptr(chan_info *cp, void *ptr, float *args, int nargs, int count, int reg);
void *find_ufun(snd_info *sp, char *fun);
void receive_ufun_selection(int chans, int srate, float **data, int *lens);

typedef struct {
  int length;
  int type;
  float *data;
  axis_info *axis;
  int peaks_ok;
  float scaler;
} ufun_info;

ufun_info *free_ufun_info(chan_info *cp);
int snd_load_ufun(char *library, char *fun);
void receive_ufun_file(char *filename);

void record_amp_change(snd_info *sp,int scroll_val,float amp_val);
void record_speed_change(snd_info *sp,int scroll_val,float speed_val);
void record_expand_change(snd_info *sp,int scroll_val,float expand_val);
void record_reverb_change(snd_info *sp,int scroll_val,float reverb_val);
void record_contrast_change(snd_info *sp,int scroll_val,float contrast_val);
void record_direction_change(snd_info *sp,int scroll_val,float direction_val);

void start_record_and_replay(snd_state *ss, snd_info *sp);
void finish_record_and_replay(void);
void initialize_record(snd_info *sp);
void initialize_replay(snd_info *sp);
int apply_controls(void *sp);
void flush_actions(snd_info *sp);

void replay_amp(void *ap);
void replay_expand(void *ap);
void replay_contrast(void *ap);
void replay_reverb(void *ap);
void replay_speed(void *ap);
void replay_direction(void *ap1);

void save_control_state(snd_info *sp);
void restore_control_state(snd_info *sp);
void free_controls(snd_info *sp);

void initialize_apply(snd_info *sp);
int run_apply(snd_info *sp, int ofd);
void finalize_apply(snd_info *sp);
void stop_applying(snd_info *sp);
void *make_apply_state(void *xp);

void tickle_clm(snd_state *ss);
void initialize_scrollbars(chan_info *cp);
void clm_doit(snd_state *ss, char *buf, int start, int end);
int amp_env_maxamp_ok(chan_info *cp);
float amp_env_maxamp(chan_info *cp);
void apply_env(chan_info *cp, env *e, int beg, int dur, float scaler, int regexpr, int from_enved);

void display_info(snd_info *sp);
void set_new_header_type(int type);
int get_new_header_type(void);
char *sound_comment(file_info *hdr);
int file_maxamps(char *ifile, float *vals, int *changes);

void reset_spectro(snd_state *state);
int save_selection(snd_state *ss, char *ofile,int type, int format, int srate);
int save_edits_2(snd_info *sp, char *new_name, int type, int format, int srate);
snd_info *find_sound(snd_state *ss, char *name);
snd_info *make_sound_readable(snd_state *ss, char *filename, int post_close);
void set_session_name (snd_state *ss, char *name);
void report_chan_marks(chan_info *cp, int fd);
void save_state (snd_state *ss, char *session_name);

#if defined(NEXT) || defined(BEOS)
char *tempnam(char *ignored, char *tmp);
#endif

void remix_file(mixdata *md);
void remix_file_with_group(grp_info *g, int row);
float get_maxamp(snd_state *ss, snd_info *sp, chan_info *cp);
void scale_by(snd_state *ss, snd_info *sp, chan_info *cp, float *scalers, int len, int selection);
void scale_to(snd_state *ss, snd_info *sp, chan_info *cp, float *scalers, int len, int selection);
void make_temporary_graph(chan_info *cp, mixdata *md, console_state *cs);
int make_graph(chan_info *cp, snd_info *sp, snd_state *ss);

void mix_complete_file(snd_info *sp, char *str, int source);
void mix_array(int beg, int num, int **data, chan_info **out_cps, int in_chans, int out_chans, int from_ufun, int nominal_srate);
void mix_file(int beg, int num, char *file, chan_info **cps, int out_chans, int from_ufun);
void mix(int beg, int num, int chans, chan_info **cps, char *mixinfile, int temp, int clm, int group);
mixdata *free_mixdata(mixdata *m);
chan_info *m_to_cp(mixmark *m);
snd_info *make_mix_readable(mixdata *md);
void free_mix_list(chan_info *cp);
void reset_mix_list(chan_info *cp);
void clm_add_mixes(snd_info *sp);

mixdata *active_mix(chan_info *cp);
mark *active_mark(chan_info *cp);
int mix_beg(chan_info *cp);
int mark_beg(chan_info *cp);

void fill_number(char *fs, char *ps);
float srate_changed(int ival, char *srcbuf, int style, int tones);
float ur_srate_changed(float val, char *srcbuf, int style, int tones);
void set_mix_amp_scaler(float amp);
float get_mix_amp_scaler(void);
void set_mix_speed_scaler(float amp);
float get_mix_speed_scaler(void);
void set_mix_tempo_scaler(float amp);
float get_mix_tempo_scaler(void);
char *shorter_tempnam(char *dir,char *prefix);

void release_mixes(chan_info *cp);

void clear_sync_moves(mixdata *md);
void set_sync_moves(mixdata *md);
void move_or_disable_sync_chain(snd_info *sp,mixdata *md,int beg,int nx);
void speed_or_disable_sync_chain(snd_info *sp,mixdata *md,float speed, int val);
void speed_sync_chain(mixdata *md, float spd, int ival);
void toggle_syncd_group(mixdata *md, int on, int ival);
void anchor_or_disable_sync_chain(snd_info *sp, mixdata *md, int anchor);


void set_group_bounds(grp_info *g);
void set_group_out_names(grp_info *g, char **filenames, int size);
void ripple_mixes(chan_info *cp, int beg, int change);
void move_associated_mixes(mixdata *md, int amount, int include_current);
void make_temporary_graph_over_group(snd_state *ss, grp_info *g);
void make_temporary_graph_over_groups(snd_state *ss, int gr);
void remix_file_over_group(grp_info *g);
void remix_file_over_groups(snd_state *ss, int gr);
int ready_mix(mixdata *md);
void reset_syncd_origs(mixdata *md, int amount);
void reset_associated_origs(mixdata *md, int amount);
int disk_space_p(snd_info *sp, int fd, int bytes, int other_bytes);
int snd_write(chan_info *cp, int tfd, int beg, int end, int chans, int **bufs, int datum_size);
void cleanup_group_temp_files(snd_state *ss);
void regraph_all_mixmarks(chan_info *cp);
void remix_sync_chain(mixdata *md);
grp_info *get_current_group(void);
void set_current_group(int i);
void notify_group(mixdata *md, int g, int on);
void update_group_browser_labels(snd_state *ss, mixdata *md, console_state *cs);
void clear_groups(snd_state *ss);
void update_groups(void);
void refigure_amp(snd_state *ss, mixdata *md);
void refigure_amps(snd_state *ss, int row);
void refigure_amp_envs(snd_state *ss, int row);
void refigure_one_amp_env(snd_state *ss, mixdata *md);
void refigure_speed(snd_state *ss, mixdata *md);
void refigure_tempo(snd_state *ss, grp_info *g);
void update_group_speed(snd_state *ss, grp_info *g);
void remix_group_speeds(snd_state *ss, grp_info *g);
void update_group_tempo(snd_state *ss, grp_info *g);
void remix_group_tempo(snd_state *ss, grp_info *g);
int update_group_positions(snd_state *ss, mixdata *md);
void start_playing_group(snd_state *ss, grp_info *g);
void stop_playing_group(snd_state *s,grp_info *g);
void check_and_allocate_groups(snd_state *ss);
void update_groups_and_envs(mixdata *md);
int map_over_channel_mixes(chan_info *cp, int (*func)(mixdata *, void *), void *ptr);

snd_data *free_snd_data(snd_data *sf);
snd_data *copy_snd_data(snd_data *sd, chan_info *cp);
int int_from_md(snd_state *ss, mixdata *md);
int goto_mix(chan_info *cp,int count);

float mx_get_group_amp(snd_state *ss, int n, int row);
float mx_get_group_tempo(snd_state *ss, int n);
float mx_get_group_beg(snd_state *ss, int n);
float mx_get_group_end(snd_state *ss, int n);
float mx_get_group_speed(snd_state *ss, int n);
void mx_set_group_amp(snd_state *ss, int n, int row, float val);
void mx_set_group_speed(snd_state *ss, int n, float val);
void mx_set_group_tempo(snd_state *ss, int n, float val);
void mx_set_group_beg(snd_state *ss, int n, float val);
void mx_set_group_end(snd_state *ss, int n, float val);
int current_location(snd_fd *sf);

void set_keymap_entry(int sym, char *val);
void toggle_dac_pausing(snd_state *ss); /* snd-dac.c */
int play_in_progress(void);
void play_button_pause(snd_state *ss, int pausing); /* snd-xsnd.c */
file_info *copy_header(char *fullname, file_info *ohdr);

void display_channel_mixes(chan_info *cp);
void release_pending_mixes(chan_info *cp, int edit_ctr);
void update_all_consoles(snd_state *ss);
void lock_affected_mixes(chan_info *cp, int beg, int end);
void free_mixes(chan_info *cp);
void move_selection_2(chan_info *cp);
void move_selection(chan_info *cp, int x);

void create_envelope_editor (snd_state *ss);
int snd_amp_to_int(float amp);
int snd_srate_to_int(float val);
int snd_expand_to_int(float ep);
int snd_contrast_to_int(float val);
int snd_revscl_to_int(float val);
int snd_revlen_to_int(float val);
env* find_lv_env(char *str);
float *find_lv_float(char *str);
float set_lv_float(char *str, float val);
void def_float(char *name);
char *env_to_string(env *e);
float *magify_env(env *e, int dur, float scaler);
double *dmagify_env(env *e, int dur, float scaler);
void alert_lv_env(char *name, env *val);
void make_filter(int order, float *env, float *a);
float list_interp(float x, float *e, int pts);
void apply_filter(chan_info *cp, int order, env *e, int from_enved);
void src(snd_state *ss, char *env_or_num, int from_enved);
void enved_print(char *output, chan_info *cp, int y0);

src_state *make_src(snd_state *ss, float srate, snd_fd *sf);
float run_src(src_state *sr, float sr_change);
src_state *free_src(src_state *sr);
void transform_type(snd_state *ss, int type);

#endif

