/* 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 size;
  int *fragments;
  int beg,len;
  char *origin;
  int sfnum;
} 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 */
  char *comment;          /* output case, not input */
} file_info;

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

typedef struct {
  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 length,data_size;
  float *data;
  axis_info *axis;
  int peaks_ok;
  float scaler;
} lisp_grf;

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

typedef struct {
  float *data;
  int pts,data_size;
  int exponential;
  float base;
} 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;
  float scale;
  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 lisp_graphing;       /* lisp function display state */
  lisp_grf *lisp_info;
  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;
  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;
  int hookable;
} 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,local_explen,local_exprmp,local_exphop;
  float contrast;
  float revlen,revscl,local_revfb,local_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,lisp_graphing,macroing,grouping;
  sop *eval_tree;
  char *eval_expr;
  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 viewing;
  int ctrls_height,channel_min_height;
  int from_clm, to_clm; /* 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 place_scroll_size;
  void *help_monolog;
  char *init_file;
  int max_sounds;
  int play_start_time;
  snd_info *mx_sp;
  char *pending_open;
  char *pending_change;
  char *pending_new;
  int print_choice;
  int stopped_explicitly,checking_explicitly;
  int result_printout,listening,respond_to_clm;
  int open_hook_active,close_hook_active,fft_hook_active,graph_hook_active,exit_hook_active,start_hook_active;
#ifdef _DEBUG_MALLOC_INC
  unsigned long orig_size;
#endif
  int Subsampling,Show_Fft_Peaks,Show_Y_Zero,Show_Marks,Fft_Log_Frequency,Fft_Log_Magnitude,Channel_Style,Sound_Style,Show_Wave_In_Enved;
  char *Eps_File,*Temp_Dir;
  int Mixer_Groups,Mixer_Group_Max_Out_Chans,Verbose_Cursor; /* CLM_Interruptible */
  int Filter_Env_Order;  /* for spectral envelopes from the envelope editor */
  float Vu_Size,Vu_Font_Size;
  char *Vu_Font;
  float Spectro_X_Scale,Spectro_Y_Scale,Spectro_Z_Scale,Spectro_Z_Angle,Spectro_X_Angle,Spectro_Y_Angle,Spectro_Cutoff;
  int Default_Output_Type,Spectro_Hop,Spectro_Color,Wavelet_Type,Transform_Type,Dot_Size;
  int Fft_Size,Fft_Window,Fft_Style,Zero_Pad,Ask_Before_Overwrite,Line_Size,Wavo_Hop,Wavo,Wavo_Trace;
  float Fft_Beta;
  float Color_Scale,Color_Cutoff;
  int Color_Inverted,Speed_Style,Movies,Normalize_Fft,Mix_Duration_Brackets,Fit_Data_On_Open;
  int Speed_Tones,Sinc_Width,X_Axis_Style,Zoom_Focus_Style,Save_State_On_Exit,Graph_Style;
  int Window_Width,Window_Height,Window_X,Window_Y;
  int Normalize_On_Open,Auto_Resize;
  float Initial_X0,Initial_X1,Initial_Y0,Initial_Y1,Xmin,Xmax,Ymin,Ymax;
  float Default_Amp,Default_Expand_Length,Default_Expand_Ramp,Default_Expand_Hop;
  float Default_Reverb_Feedback,Default_Reverb_Lowpass,Default_Expand,Reverb_Decay;
  float Default_Speed,Default_Contrast,Default_Reverb_Scale,Default_Reverb_Length,Default_Contrast_Amp;
  int Default_Expanding,Default_Contrasting,Default_Reverbing,Default_Filtering,Default_Filter_Order;
  int Raw_Srate,Raw_Chans,Raw_Format,Raw_Type,Use_Raw_Defaults;
  int Print_Length,Show_Mix_Consoles;
  char *Recorder_File,*Session_File;
  float Enved_Base;
  int Recorder_Autoload,Recorder_Buffer_Size,Recorder_In_Format,Recorder_Out_Format,Recorder_Out_Chans,Recorder_Srate;
  int Enved_Clipping,Enved_Exping,Enved_Target,Enved_Waving,Prefix_Arg,Show_Edit_History,Edit_History_Width;
#if HAVE_XmHTML
  int HTML_Width,HTML_Height;
  char *HTML_Dir,*HTML_Font_Size_List,*HTML_Fixed_Font_Size_List;
#endif
} 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 */
  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;


#if (!(HAVE_XmHTML))
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_expression_help(void);
char *get_recording_help(void);
char *get_envelope_editor_help(void);
char *get_edit_history_help(void);
#endif

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);
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);

int output_type_and_format_ok(int type, int format);
char *copy_string (char *str);
int snd_strlen(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);
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_state(chan_info *cp);
void set_spectro_cutoff_and_redisplay(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 low, float high);
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);
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 is_link(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);

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, snd_state *ss);
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, char *origin);
void file_insert_samples(int beg, int num, char *tempfile, chan_info *cp, int chan, int auto_delete, char *origin);
void file_override_samples(int num, char *tempfile, chan_info *cp, int chan, int auto_delete, int lock, char *origin);
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, char *origin);
void delete_samples(int beg, int num, chan_info *cp, char *origin);
void change_samples(int beg, int num, int *vals, chan_info *cp, int lock, char *origin);
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, int temp_chan);
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);
void redo_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);

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);
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 clear_minibuffer_prompt(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 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 apply_y_axis_change (axis_info *ap, chan_info *cp);
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);
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);
int save_options (snd_state *ss);
FILE *open_snd_init_file (snd_state *ss);
void save_snd_state_options (snd_state *ss, FILE *fd);

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

void save_macros(snd_state *ss);
int execute_macro(chan_info *cp, char *name, int count);
void save_macro_state (snd_state *ss, FILE *fd);

void snd_load_init_file(snd_state *ss);
int get_clm_string(snd_state *ss, int fd, int from_clm);
int snd_load_file(snd_state *ss,char *filename);
void snd_exit_cleanly(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 region_ok(int n);
int selection_len(void);
int selection_beg(chan_info *cp);
void delete_selection(char *origin);
void paste_region(int n, chan_info *cp, char *origin);
void add_region(int n, chan_info *cp, char *origin);
void mix_region(int n, chan_info *cp, int beg, float scaler);
float region_sample(int reg, int chn, int samp);
void region_samples(int reg, int chn, int beg, int num, float *data);
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);
int selection_active(chan_info *cp);
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 save_regions(FILE *fd);

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);

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 initialize_scrollbars(chan_info *cp);
int clm_doit(snd_state *ss, char *buf, int from_clm);
int clm_just_doit(snd_state *ss, char *buf);
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, char *origin);

void display_info(snd_info *sp);
int file_maxamps(snd_state *ss, 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, char *comment);
int save_edits_2(snd_info *sp, char *new_name, int type, int format, int srate, char *comment);
snd_info *find_sound(snd_state *ss, char *name);
snd_info *make_sound_readable(snd_state *ss, char *filename, int post_close);
void report_chan_marks(chan_info *cp, int fd);
int save_state (snd_state *ss, char *session_name);

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

void remix_file(mixdata *md, char *origin);
void remix_file_with_group(grp_info *g, int row,char *origin);
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, char *origin);
void mix_array(int beg, int num, int **data, chan_info **out_cps, int in_chans, int out_chans, int nominal_srate, char *origin);
void mix_file(int beg, int num, char *file, chan_info **cps, int out_chans, char *origin);
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);
char *snd_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, char *origin);
void remix_file_over_groups(snd_state *ss, int gr, char *origin);
int ready_mix(mixdata *md);
void reset_syncd_origs(mixdata *md, int amount);
void reset_associated_origs(mixdata *md, int amount);
void check_group_max_out_chans(snd_state *ss, int n);
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, char *origin);
void update_group_tempo(snd_state *ss, grp_info *g);
void remix_group_tempo(snd_state *ss, grp_info *g, char *origin);
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 int_from_md(snd_state *ss, mixdata *md);
int goto_mix(chan_info *cp,int count);

float mx_get_group_amp(int n, int row);
float mx_get_group_tempo(int n);
float mx_get_group_beg(int n);
float mx_get_group_end(int n);
float mx_get_group_speed(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 key, int state, 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* name_to_env(char *str);
char *env_to_string(env *e);
float *magify_env(env *e, int dur, float scaler);
double *dmagify_env(env *e, int dur, float scaler);
float *fixup_exp_env(env *e, float *offset, float *scaler, float base);
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, char *origin);
/* void src(snd_state *ss, char *env_or_num, int from_enved); */
void print_enved(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 cleanup_dac(void);
void src_env_or_num(snd_state *ss, env *e, float ratio, int just_num, int from_enved, char *origin);

#ifdef _DEBUG_MALLOC_INC
  #define snd_calloc(a,b,c) calloc((b),(c))
  #define snd_realloc(a,b,c) realloc((b),(c))
#else
  void *snd_calloc(snd_state *ss, size_t num, size_t size);
  void *snd_realloc(snd_state *ss, void *original_ptr, size_t size);
#endif

char *shortname(snd_info *sp);
int make_fft_window_1(float *window, int size, int type, float beta, int scaled);

int snd_regions(void);
void set_x_axis_style(snd_state *ss, int val);
void clm_x_axis (chan_info *cp, float x0, float x1);
void clm_y_axis (chan_info *cp, float y0, float y1);
void goto_previous_graph (chan_info *cp, int count);
void goto_next_graph (chan_info *cp, int count);
int sono_update(chan_info *cp, void *ptr);
void clear_soundcard_inputs(void);
int active_groups(snd_state *ss);
int group_ok(snd_state *ss, int n);
int mix_position(snd_state *ss, int n);
int mix_length(snd_state *ss, int n);
int mix_anchor(snd_state *ss, int n);
int mix_groups(snd_state *ss, int n);
int in_mix_state(snd_state *ss, int n);
float in_mix_speed(snd_state *ss, int n);
float in_mix_amp(snd_state *ss, int n, int chan);
int set_mix_position(snd_state *ss, int n, int val);
int set_mix_length(snd_state *ss, int n, int val);
int set_mix_anchor(snd_state *ss, int n, int val);
int in_set_mix_state(snd_state *ss, int n, int val);
int set_mix_groups(snd_state *ss, int n, int val);
float in_set_mix_speed(snd_state *ss, int n, float val);
float in_set_mix_amp(snd_state *ss, int n, int chan, float val);
mixdata *file_mix_samples(int beg, int num, char *tempfile, chan_info *cp, int chan, int temp, int clm, int out_chans, char *origin);
void g_snd_callback(snd_state *ss, int callb);
void clm_left_axis(chan_info *cp, int left);
void clm_right_axis(chan_info *cp, int right);
env *scan_envelope(char *str);
void handle_cursor_with_sync(chan_info *cp,int decision);
int *clm_snd_data(snd_state *ss, int *length);
void snd_clm_data (snd_state *ss, int len, int *data);
void clm_snd_replace_samples(snd_state *ss, char *tempf, snd_info *sp);
void add_or_edit_symbol(char *name, env *val);
void edit_history_to_file(FILE *fd, chan_info *cp);
char *edit_to_string(ed_list *ed);
void save_mark_list(FILE *fd, chan_info *cp);
mark *make_mark(int samp, char *name);

void set_wavo(snd_state *ss, int on);

#if HAVE_GUILE
  int after_fft(snd_state *ss, chan_info *cp, float scale);
  int dont_graph(snd_state *ss, chan_info *cp);
  int dont_close(snd_state *ss, snd_info *sp);
  int dont_open(snd_state *ss, char *file);
  int dont_exit(snd_state *ss);
  int dont_start(snd_state *ss);
  int handle_keymap(chan_info *cp, char *code);
  SCM g_restore_region(SCM n, SCM chans, SCM len, SCM srate, SCM maxamp, SCM name, SCM start, SCM end, SCM data);
  void handle_mouse_release(snd_state *ss, snd_info *sp, chan_info *cp, float x, float y, int button, int state);
  void handle_mouse_press(snd_state *ss, snd_info *sp, chan_info *cp, float x, float y, int button, int state);
  void handle_mouse_drag(snd_state *ss, snd_info *sp, chan_info *cp, float x, float y);
  int handle_key_press(snd_state *ss, snd_info *sp, chan_info *cp, int key, int state);
#endif

#endif

